package problem type Problem[State comparable] interface { // Discards the given state, allowing any resources associated with it to be released. Discard(state State) // Returns true if the first state is more likely to be a better solution than the second state, // assuming the best case scenario. This is used to determine the best state to expand next. // // If this were to compare the distance traveled so far, this would be equivalent to Dijkstra's algorithm. // // If you added a heuristic to estimate the remaining distance, this would be equivalent to A*. // // For the traveling salesman problem, you might use traveled distance plus half of the remaining greedy tour length as a lower bound (optimistic) estimate. OptimisticLess(a State, b State) bool // Returns true if the first state is more likely to be a better solution than the second state, // assuming the worst case scenario. This is used to determine if the worst state to discard when at capacity. // // This can be equivalent to OptimisticLess in many cases. // // For the traveling salesman problem, you might use traveled distance plus the remaining greedy tour length as an upper bound (pessimistic) estimate. // // You generally want to penalize states with a lot of uncertainty about their actual cost, especially // for something like the traveling salesman problem where finding the optimal solution is impractical. // We could maybe handle finding the optimal TSP solution for 100 points, but definitely not 1000. // For that, you'd likely want to cluster your points (maybe using k-means) into a manageable number of groups, // and recursively solve the problem on each group. PessimisticLess(a State, b State) bool } type ProblemStateUpdates[State comparable] interface { Problem[State] // If this function returns true, then the solver needs to keep track of // known states so that it can update their relative order when they're resubmitted. // // If a problem doesn't implement this method, then true is assumed by default. StateUpdates() bool } func RequiresStateUpdates[P Problem[State], State comparable](p Problem[State]) bool { if p, ok := p.(ProblemStateUpdates[State]); ok { return p.StateUpdates() } // return true as a safe default. return true }