Add iterated local search to solver for more stable results

This commit is contained in:
Ian Gulliver
2026-02-15 22:34:51 -08:00
parent 152bc6d4bb
commit 8cc524bff9

48
main.go
View File

@@ -1066,13 +1066,9 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
return currentScore return currentScore
} }
for restart := 0; restart < 50; restart++ { randomPlacement := func() bool {
if restart == 0 {
copy(assignment, initialAssignment)
} else {
perm := rand.Perm(len(groupList)) perm := rand.Perm(len(groupList))
for i := range roomCap { roomCap[i] = roomSize } for i := range roomCap { roomCap[i] = roomSize }
ok := true
for _, pi := range perm { for _, pi := range perm {
grp := groupList[pi] grp := groupList[pi]
placed := false placed := false
@@ -1098,16 +1094,48 @@ func handleSolve(db *sql.DB) http.HandlerFunc {
placed = true placed = true
break break
} }
if !placed { if !placed { return false }
ok = false
break
} }
return true
}
perturb := func(src []int, count int) {
copy(assignment, src)
indices := rand.Perm(len(uniqueGroups))
if count > len(indices) { count = len(indices) }
for _, gi := range indices[:count] {
grp := groups[uniqueGroups[gi]]
oldRoom := assignment[grp[0]]
rooms := rand.Perm(numRooms)
for _, room := range rooms {
if room == oldRoom { continue }
if roomCount(assignment, room)+len(grp) > roomSize { continue }
for _, m := range grp { assignment[m] = room }
if feasible(assignment) { break }
for _, m := range grp { assignment[m] = oldRoom }
} }
if !ok {
copy(assignment, initialAssignment)
} }
} }
copy(assignment, initialAssignment)
s := hillClimb(assignment)
if s > bestScore {
bestScore = s
copy(bestAssignment, assignment)
}
for restart := 0; restart < 30; restart++ {
if randomPlacement() {
s := hillClimb(assignment)
if s > bestScore {
bestScore = s
copy(bestAssignment, assignment)
}
}
}
for ils := 0; ils < 200; ils++ {
perturb(bestAssignment, 2+rand.Intn(3))
s := hillClimb(assignment) s := hillClimb(assignment)
if s > bestScore { if s > bestScore {
bestScore = s bestScore = s