如果上限在 x 秒后没有变好,如何在 CP Optimizer 中停止搜索
How to stop the search in CP Optimizer if the upper bound doesn't get better after x seconds
我想知道 CP Optimizer 12.10 中是否有一种方法可以在上限(最小化问题)在 "x" 秒后没有变好时停止搜索。当尝试解决 NP-Hard 问题的困难实例并且搜索停留在一个现有解决方案中时,这将特别有用。
我知道有一些参数可以控制搜索,如 cp.param.TimeLimit
(我正在使用它)或 cp.param.FailLimit
,但这不是我的问题所需要的。
如有任何帮助,我们将不胜感激。
如果你依赖 OPL API,你可以做的是使用一个主块(流量控制),在这个主块中你给出 x 秒的时间限制,然后你得到边界和当前 objective,如果您认为应该更进一步就保存它们,或者如果您对解决方案没问题就停止。
让我分享一个来自 OPL 产品中 lifegame 示例的完整示例。再次记住 John Conway。
using CP;
int n=20;
int Half=n div 2;
range FirstHalf = 1..Half;
range LastHalf = n-Half+1..n;
range States = 0..1;
range Bord = 0..(n+1);
range Interior = 1..n;
range obj = 0..(n*n);
tuple neighbors {
int row;
int col;
}
{neighbors} Neighbor =
{<(-1),(-1)>,<(-1),0>,<(-1),1>,<0,(-1)>,<0,1>,<1,(-1)>,<1,0>,<1,1>};
dvar int Life[Bord][Bord] in States;
dvar int Obj in obj;
dvar int x[0..(n+2)*(n+2)-1];
maximize Obj;
subject to {
forall(i,j in Bord) Life[i][j]==x[i*(n+2)+j];
//ct1:
Obj == sum( i , j in Bord )
Life[i][j];
forall( i , j in Interior ) {
ct21:
2*Life[i][j] - sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 0;
ct22:
3*Life[i][j] + sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 6;
forall( ordered n1 , n2 , n3 in Neighbor ) {
ct23:
-Life[i][j]+Life[i+n1.row][j+n1.col]
+Life[i+n2.row][j+n2.col]
+Life[i+n3.row][j+n3.col]
-sum( nb in Neighbor : nb!=n1 && nb!=n2 && nb!=n3 )
Life[i+nb.row][j+nb.col] <= 2;
}
}
forall( j in Bord ) {
ct31:
Life[0][j] == 0;
ct32:
Life[j][0] == 0;
ct33:
Life[j][n+1] == 0;
ct34:
Life[n+1][j] == 0;
}
forall( i in Bord : i<n ) {
ct41:
Life[i][1]+Life[i+1][1]+Life[i+2][1] <= 2;
ct42:
Life[1][i]+Life[1][i+1]+Life[1][i+2] <= 2;
ct43:
Life[i][n]+Life[i+1][n]+Life[i+2][n] <= 2;
ct44:
Life[n][i]+Life[n][i+1]+Life[n][i+2] <= 2;
}
ct5:
sum( i in FirstHalf , j in Bord )
Life[i][j] >=
sum( i in LastHalf , j in Bord )
Life[i][j];
ct6:
sum( i in Bord , j in FirstHalf )
Life[i][j] >=
sum( i in Bord , j in LastHalf )
Life[i][j];
}
main
{
thisOplModel.generate();
cp.param.timelimit=10;
var obj=0;
var bound=0;
var oldobj=0;
var oldbound=0;
while (1==1)
{
cp.solve();
obj=cp.getObjValue();
bound=cp.getObjBound();
writeln("bound and obj =",bound," ",obj);
if (Opl.abs((oldobj-oldbound-obj+bound))<=0) break;
oldobj=obj;
oldbound=bound;
}
}
这给出了
bound and obj =398 181
bound and obj =398 180
bound and obj =398 180
// Script execution finished with status 1.
我想知道 CP Optimizer 12.10 中是否有一种方法可以在上限(最小化问题)在 "x" 秒后没有变好时停止搜索。当尝试解决 NP-Hard 问题的困难实例并且搜索停留在一个现有解决方案中时,这将特别有用。
我知道有一些参数可以控制搜索,如 cp.param.TimeLimit
(我正在使用它)或 cp.param.FailLimit
,但这不是我的问题所需要的。
如有任何帮助,我们将不胜感激。
如果你依赖 OPL API,你可以做的是使用一个主块(流量控制),在这个主块中你给出 x 秒的时间限制,然后你得到边界和当前 objective,如果您认为应该更进一步就保存它们,或者如果您对解决方案没问题就停止。
让我分享一个来自 OPL 产品中 lifegame 示例的完整示例。再次记住 John Conway。
using CP;
int n=20;
int Half=n div 2;
range FirstHalf = 1..Half;
range LastHalf = n-Half+1..n;
range States = 0..1;
range Bord = 0..(n+1);
range Interior = 1..n;
range obj = 0..(n*n);
tuple neighbors {
int row;
int col;
}
{neighbors} Neighbor =
{<(-1),(-1)>,<(-1),0>,<(-1),1>,<0,(-1)>,<0,1>,<1,(-1)>,<1,0>,<1,1>};
dvar int Life[Bord][Bord] in States;
dvar int Obj in obj;
dvar int x[0..(n+2)*(n+2)-1];
maximize Obj;
subject to {
forall(i,j in Bord) Life[i][j]==x[i*(n+2)+j];
//ct1:
Obj == sum( i , j in Bord )
Life[i][j];
forall( i , j in Interior ) {
ct21:
2*Life[i][j] - sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 0;
ct22:
3*Life[i][j] + sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 6;
forall( ordered n1 , n2 , n3 in Neighbor ) {
ct23:
-Life[i][j]+Life[i+n1.row][j+n1.col]
+Life[i+n2.row][j+n2.col]
+Life[i+n3.row][j+n3.col]
-sum( nb in Neighbor : nb!=n1 && nb!=n2 && nb!=n3 )
Life[i+nb.row][j+nb.col] <= 2;
}
}
forall( j in Bord ) {
ct31:
Life[0][j] == 0;
ct32:
Life[j][0] == 0;
ct33:
Life[j][n+1] == 0;
ct34:
Life[n+1][j] == 0;
}
forall( i in Bord : i<n ) {
ct41:
Life[i][1]+Life[i+1][1]+Life[i+2][1] <= 2;
ct42:
Life[1][i]+Life[1][i+1]+Life[1][i+2] <= 2;
ct43:
Life[i][n]+Life[i+1][n]+Life[i+2][n] <= 2;
ct44:
Life[n][i]+Life[n][i+1]+Life[n][i+2] <= 2;
}
ct5:
sum( i in FirstHalf , j in Bord )
Life[i][j] >=
sum( i in LastHalf , j in Bord )
Life[i][j];
ct6:
sum( i in Bord , j in FirstHalf )
Life[i][j] >=
sum( i in Bord , j in LastHalf )
Life[i][j];
}
main
{
thisOplModel.generate();
cp.param.timelimit=10;
var obj=0;
var bound=0;
var oldobj=0;
var oldbound=0;
while (1==1)
{
cp.solve();
obj=cp.getObjValue();
bound=cp.getObjBound();
writeln("bound and obj =",bound," ",obj);
if (Opl.abs((oldobj-oldbound-obj+bound))<=0) break;
oldobj=obj;
oldbound=bound;
}
}
这给出了
bound and obj =398 181
bound and obj =398 180
bound and obj =398 180
// Script execution finished with status 1.