ortools - CP-SAT :如果最好的现有解决方案在 'x' 秒后没有改变,如何获取可行的解决方案



我正在利用CP-SAT求解器(ortools(解决整数编程问题。查看日志,我注意到求解器找到了实际上是最优的(稍后证明(解决方案,但在证明最优性方面花费了大量时间。从本质上讲,最佳现有解决方案和最佳界限之间的差距慢慢缩小。

如果MIP间隙%:(abs(objective-best_bound(/objective(<0.05,但没有帮助。由于收敛缓慢。

from ortools.sat.python import cp_model as cp
import time
class PrinterClass(cp.CpSolverSolutionCallback):
def __init__(self):
cp.CpSolverSolutionCallback.__init__(self)
self.__solution_count = 0
self.__start_time = time.time()
def on_solution_callback(self):
current_time = time.time()
objective = self.ObjectiveValue()
best_bound = self.BestObjectiveBound()
print("Solution %i, time = %f s, objective = %i, best_bound = %i" %
(self.__solution_count, current_time - self.__start_time,
objective, best_bound))
self.__solution_count += 1

if (abs(objective - best_bound) / objective) < 0.05:
print('Stop search')
self.StopSearch()

def total_num_solutions(self):
return self.__solution_count

我想尝试的是:如果最好的现有解决方案在10秒内没有改变(比如(,那么我想输出这个特定的可行解决方案并停止搜索。而不是求解者花费200秒(比如(试图缩小现有解决方案和最佳边界之间的差距。

例如,如果你看下面的日志,求解器会找到一个可行的解决方案(实际上是最优的,稍后会证明(,2.75秒时的解决方案#13,

Solution 13, time = 2.745947 s, objective = 2032, best_bound = 1479

然后再花费约25秒来证明它实际上是最优的,当求解器花费额外的10秒并且无法改进当前的现有解决方案时,我可以停止搜索并获得解决方案吗。低于点

#Bound  12.14s best:2032  next:[1532,2030] pseudo_costs

我只是想尝试一下,至少为了我的学习,有人能帮我吗?

以下是生成的日志:

Starting Search at 0.28s with 8 workers.
6 full subsolvers: [default_lp, no_lp, max_lp, reduced_costs, pseudo_costs, quick_restart]
Interleaved subsolvers: [feasibility_pump, rnd_var_lns_default, rnd_cst_lns_default, graph_var_lns_default, graph_cst_lns_default, routing_random_lns_default, routing_path_lns_default, routing_full_path_lns_default, rins_lns_default, rens_lns_default]
#1       0.44s best:4884  next:[0,4883]   no_lp fixed_bools:1/931
Solution 0, time = 0.435596 s, objective = 4884, best_bound = 0
#Bound   0.45s best:4884  next:[0,4882]   no_lp
#2       0.46s best:4336  next:[0,4335]   no_lp fixed_bools:1/935
Solution 1, time = 0.466841 s, objective = 4336, best_bound = 0
#Bound   0.47s best:4336  next:[0,4334]   no_lp
#Bound   0.48s best:4336  next:[1278,4334] max_lp initial_propagation
#3       0.54s best:3972  next:[1278,3971] no_lp fixed_bools:1/939
Solution 2, time = 0.544969 s, objective = 3972, best_bound = 1278
#Bound   0.55s best:3972  next:[1278,3970] no_lp
#4       0.55s best:3492  next:[1278,3491] routing_random_lns_default(d=0.50 s=12 t=0.10 p=0.00)
Solution 3, time = 0.560597 s, objective = 3492, best_bound = 1278
#Bound   0.56s best:3492  next:[1278,3490] no_lp
#5       0.57s best:2968  next:[1278,2967] no_lp fixed_bools:1/944
Solution 4, time = 0.576220 s, objective = 2968, best_bound = 1278
#Bound   0.58s best:2968  next:[1278,2966] no_lp
#6       0.62s best:2944  next:[1278,2943] no_lp fixed_bools:1/949
Solution 5, time = 0.632293 s, objective = 2944, best_bound = 1278
#Bound   0.64s best:2944  next:[1278,2942] no_lp
#Bound   0.65s best:2944  next:[1352,2942] max_lp
#7       0.65s best:2876  next:[1352,2875] no_lp fixed_bools:1/950
Solution 6, time = 0.663560 s, objective = 2876, best_bound = 1352
#Bound   0.66s best:2876  next:[1352,2874] no_lp
#8       0.67s best:2648  next:[1352,2647] no_lp fixed_bools:1/954
Solution 7, time = 0.679179 s, objective = 2648, best_bound = 1352
#Bound   0.68s best:2648  next:[1352,2646] no_lp
#9       0.70s best:2420  next:[1352,2419] no_lp fixed_bools:1/957
Solution 8, time = 0.710431 s, objective = 2420, best_bound = 1352
#Bound   0.71s best:2420  next:[1352,2418] no_lp
#10      0.72s best:2396  next:[1352,2395] no_lp fixed_bools:1/958
Solution 9, time = 0.726056 s, objective = 2396, best_bound = 1352
#Bound   0.73s best:2396  next:[1352,2394] no_lp
#Bound   0.91s best:2396  next:[1356,2394] pseudo_costs
#11      0.94s best:2260  next:[1356,2259] no_lp fixed_bools:1/960
Solution 10, time = 0.960437 s, objective = 2260, best_bound = 1356
#Bound   0.96s best:2260  next:[1399,2259] max_lp
#Bound   0.97s best:2260  next:[1399,2258] no_lp
#12      0.98s best:2192  next:[1399,2191] no_lp fixed_bools:1/960
Solution 11, time = 0.991691 s, objective = 2192, best_bound = 1399
#Bound   0.99s best:2192  next:[1399,2190] no_lp
#Bound   1.46s best:2192  next:[1450,2190] reduced_costs
#Bound   1.87s best:2192  next:[1461,2190] reduced_costs
#13      2.18s best:2168  next:[1461,2167] default_lp fixed_bools:1/931
Solution 12, time = 2.183427 s, objective = 2168, best_bound = 1461
#Bound   2.19s best:2168  next:[1461,2166] no_lp
#Bound   2.24s best:2168  next:[1473,2166] pseudo_costs
#Bound   2.50s best:2168  next:[1479,2166] pseudo_costs
#14      2.74s best:2032  next:[1479,2031] no_lp fixed_bools:2/968
Solution 13, time = 2.745947 s, objective = 2032, best_bound = 1479
#Bound   2.75s best:2032  next:[1479,2030] no_lp
#Bound   2.83s best:2032  next:[1484,2030] reduced_costs
#Bound   3.23s best:2032  next:[1491,2030] pseudo_costs
#Bound   3.50s best:2032  next:[1493,2030] pseudo_costs
#Bound   3.73s best:2032  next:[1494,2030] pseudo_costs
#Bound   4.89s best:2032  next:[1498,2030] pseudo_costs
#Bound   5.36s best:2032  next:[1500,2030] pseudo_costs
#Bound   8.63s best:2032  next:[1503,2030] pseudo_costs
#Bound   8.85s best:2032  next:[1508,2030] pseudo_costs
#Bound   9.93s best:2032  next:[1514,2030] pseudo_costs
#Bound  10.18s best:2032  next:[1518,2030] pseudo_costs
#Bound  10.80s best:2032  next:[1523,2030] pseudo_costs
#Bound  11.05s best:2032  next:[1527,2030] pseudo_costs
#Bound  11.25s best:2032  next:[1531,2030] pseudo_costs
#Bound  12.14s best:2032  next:[1532,2030] pseudo_costs
......
......
......
#Bound  26.09s best:2032  next:[1647,2030] pseudo_costs
#Bound  26.60s best:2032  next:[1719,2030] pseudo_costs
#Bound  26.76s best:2032  next:[1720,2030] pseudo_costs
#Bound  26.94s best:2032  next:[1724,2030] pseudo_costs
#Done   26.94s pseudo_costs
#Done   26.96s default_lp

您应该阅读这个线程。

特别是来自stradivari96@的回调代码

from threading import Timer
from ortools.sat.python import cp_model

class ObjectiveEarlyStopping(cp_model.CpSolverSolutionCallback):
def __init__(self, timer_limit: int):
super(ObjectiveEarlyStopping, self).__init__()
self._timer_limit = timer_limit
self._timer = None
self._reset_timer()
def on_solution_callback(self):
self._reset_timer()
def _reset_timer(self):
if self._timer:
self._timer.cancel()
self._timer = Timer(self._timer_limit, self.StopSearch)
self._timer.start()
def StopSearch(self):
print(f"{self._timer_limit} seconds without improvement")
super().StopSearch()

相关内容

  • 没有找到相关文章

最新更新