initial commit
This commit is contained in:
168
backend/relay.go
Normal file
168
backend/relay.go
Normal file
@ -0,0 +1,168 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Event type represents different events
|
||||
type Event string
|
||||
|
||||
type Solver string
|
||||
|
||||
type SolverTimes map[Solver]map[Event]float64
|
||||
|
||||
type Assignment map[Solver][]Event
|
||||
|
||||
type PermWithTime struct {
|
||||
Perm []Solver
|
||||
Time float64
|
||||
}
|
||||
|
||||
type AssignmentWithTime struct {
|
||||
Assignment Assignment
|
||||
Time float64
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
SolverTimes SolverTimes `yaml:"solvers"`
|
||||
Events []Event `yaml:"events"`
|
||||
Participants []Solver `yaml:"participants"`
|
||||
}
|
||||
|
||||
//
|
||||
// Generic Functions
|
||||
//
|
||||
|
||||
func Combinations[T comparable](lst []T, n int) func() ([]T, bool) {
|
||||
length := len(lst)
|
||||
current := make([]T, n)
|
||||
index := make([]int, n)
|
||||
|
||||
// Initialize the first combination: ["lst[0]", "lst[0]", ..., "lst[0]"]
|
||||
for i := 0; i < n; i++ {
|
||||
current[i] = lst[0]
|
||||
index[i] = 0
|
||||
}
|
||||
|
||||
return func() ([]T, bool) {
|
||||
if current == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Copy current combination to return
|
||||
result := make([]T, n)
|
||||
copy(result, current)
|
||||
|
||||
// Find the next combination
|
||||
j := n - 1
|
||||
for j >= 0 && index[j] == length-1 {
|
||||
j--
|
||||
}
|
||||
|
||||
if j < 0 {
|
||||
current = nil
|
||||
} else {
|
||||
index[j]++
|
||||
current[j] = lst[index[j]]
|
||||
|
||||
for k := j + 1; k < n; k++ {
|
||||
index[k] = 0
|
||||
current[k] = lst[0]
|
||||
}
|
||||
}
|
||||
|
||||
return result, current != nil
|
||||
}
|
||||
}
|
||||
|
||||
func CombinationsWithStart[T comparable](start []T, lst []T, n int) func() ([]T, bool) {
|
||||
hasNext := true
|
||||
iter := Combinations(lst, n-len(start))
|
||||
var end []T
|
||||
return func() ([]T, bool) {
|
||||
end, hasNext = iter()
|
||||
return append(start, end...), hasNext
|
||||
}
|
||||
}
|
||||
|
||||
func countCombinations[T comparable](lst []T, n int) int {
|
||||
return int(math.Pow(float64(len(lst)), float64(n)))
|
||||
}
|
||||
|
||||
//
|
||||
// Relay Functions
|
||||
//
|
||||
|
||||
func CalculateRelayTime(perm []Solver, events []Event, solverTimes SolverTimes) float64 {
|
||||
solversTotalTimes := make(map[Solver]float64, len(events))
|
||||
for i, solver := range perm {
|
||||
solversTotalTimes[solver] += solverTimes[solver][events[i]]
|
||||
}
|
||||
|
||||
var relayTime float64
|
||||
for _, time := range solversTotalTimes {
|
||||
if time > relayTime {
|
||||
relayTime = time
|
||||
}
|
||||
}
|
||||
return relayTime
|
||||
}
|
||||
|
||||
//
|
||||
// Worker Functions
|
||||
//
|
||||
|
||||
func GenerateSolverCombinationsWorker(solverCombs chan<- func() ([]Solver, bool), solvers []Solver, events []Event) {
|
||||
hasNext := true
|
||||
iter := Combinations(solvers, len(events))
|
||||
for hasNext {
|
||||
var start []Solver
|
||||
start, hasNext = iter()
|
||||
solverCombs <- CombinationsWithStart(start, solvers, len(events))
|
||||
}
|
||||
}
|
||||
|
||||
func CalculateRelayTimesWorker(solverCombs <-chan func() ([]Solver, bool), assignments chan<- PermWithTime, events []Event, solverTimes SolverTimes) {
|
||||
for solverComb := range solverCombs {
|
||||
hasNext := true
|
||||
for hasNext {
|
||||
var comb []Solver
|
||||
comb, hasNext = solverComb()
|
||||
relayTime := CalculateRelayTime(comb, events, solverTimes)
|
||||
assignments <- PermWithTime{comb, relayTime}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Assign(solvers []Solver, solverTimes SolverTimes, events []Event) AssignmentWithTime {
|
||||
solverCombs := make(chan func() ([]Solver, bool))
|
||||
permsWithTime := make(chan PermWithTime)
|
||||
|
||||
go GenerateSolverCombinationsWorker(solverCombs, solvers, events)
|
||||
|
||||
bestAssignment := AssignmentWithTime{
|
||||
Assignment: Assignment{},
|
||||
Time: math.Inf(1),
|
||||
}
|
||||
// var bestAssignmentMu sync.Mutex
|
||||
|
||||
for i := 0; i < 64; i++ {
|
||||
go CalculateRelayTimesWorker(solverCombs, permsWithTime, events, solverTimes)
|
||||
}
|
||||
|
||||
totalPerms := countCombinations(solvers, len(events))
|
||||
|
||||
for i := 0; i < totalPerms; i++ {
|
||||
// fmt.Println("checking assignment")
|
||||
p := <-permsWithTime
|
||||
if p.Time < bestAssignment.Time {
|
||||
assignment := make(Assignment, len(p.Perm))
|
||||
for i, solver := range p.Perm {
|
||||
assignment[solver] = append(assignment[solver], events[i])
|
||||
}
|
||||
bestAssignment = AssignmentWithTime{assignment, p.Time}
|
||||
}
|
||||
}
|
||||
|
||||
return bestAssignment
|
||||
}
|
||||
Reference in New Issue
Block a user