76 lines
1.5 KiB
Go
76 lines
1.5 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package bounded
|
|
|
|
import (
|
|
"container/heap"
|
|
|
|
"smariot.com/tsp/internal/solver/problem"
|
|
)
|
|
|
|
type minHeap[P problem.Problem[State], State comparable] struct {
|
|
problem problem.Problem[State]
|
|
items []State
|
|
}
|
|
|
|
func (h minHeap[P, State]) Len() int {
|
|
return len(h.items)
|
|
}
|
|
|
|
func (h minHeap[P, State]) Less(i, j int) bool {
|
|
return h.problem.OptimisticLess(h.items[i], h.items[j])
|
|
}
|
|
|
|
func (h minHeap[P, State]) Swap(i, j int) {
|
|
h.items[i], h.items[j] = h.items[j], h.items[i]
|
|
}
|
|
|
|
func (h *minHeap[P, State]) Push(x any) {
|
|
state := x.(State)
|
|
h.items = append(h.items, state)
|
|
}
|
|
|
|
func (h *minHeap[P, State]) Pop() any {
|
|
n := len(h.items)
|
|
state := h.items[n-1]
|
|
h.items = h.items[:n-1]
|
|
return state
|
|
}
|
|
|
|
type solver[P problem.Problem[State], State comparable] struct {
|
|
minHeap[P, State]
|
|
}
|
|
|
|
func (s *solver[P, State]) Push(state State) {
|
|
heap.Push(&s.minHeap, state)
|
|
}
|
|
|
|
func (s *solver[P, State]) Pop() (State, bool) {
|
|
if s.Len() == 0 {
|
|
var zero State
|
|
return zero, false
|
|
}
|
|
|
|
return heap.Pop(&s.minHeap).(State), true
|
|
}
|
|
|
|
func (s *solver[P, State]) Reset() {
|
|
for _, state := range s.items {
|
|
s.problem.Discard(state)
|
|
}
|
|
|
|
s.items = s.items[:0]
|
|
}
|
|
|
|
// Returns a solver for bounded problems.
|
|
//
|
|
// This solver does not track states. Submitting a state multiple times will
|
|
// result in multiple copies being stored, and multiple calls to problem.Discard.
|
|
func New[P problem.Problem[State], State comparable](problem P) *solver[P, State] {
|
|
return &solver[P, State]{
|
|
minHeap: minHeap[P, State]{
|
|
problem: problem,
|
|
},
|
|
}
|
|
}
|