约束规划建模技巧总结---中间变量和全局约束

本文分享了作者两年来在约束编程(CP)领域的经验,并通过or-tools实例介绍了提高模型求解效率的方法,包括引入中间变量和使用全局约束等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直以来都在关注CP(Constraint Programming),感觉它是一个特别实用的优化工具,虽然在最优解方面不是那么令人满意,但是大规模问题下的短时间内得到质量较好的可行解才是我们将OR落到企业中的的关键点。结合2年来的CP建模经验和最近在看的or-tools感受,总结下CP 建模的一些tricks,我将采用or-tools 中的案例来阐释:

1、尽量引入中间变量保存expression的值,且保持1对1的关系,这样有助于约束传播。code1 为最初版的代码,code2 为改进后的代码。

code1:

IntVar* diff1;
IntVar* diff2;
int k, l, next_k, next_l;
for (int i = 1; i < n - 1; ++i) {
   for (int j = i + 1; j <= n; ++j) {
        k = i;<span style="font-family: Arial, Helvetica, sans-serif;">     </span>
        l = j;<span style="font-family: Arial, Helvetica, sans-serif;">   </span>
        diff1 = s.MakeDifference(X[j], X[i])->Var();
        diff1->SetMin(1);
        while (next_interval(n, k, l, &next_k, &next_l)) {
        diff2 = s.MakeDifference(X[next_l], X[next_k])->Var();
        diff2->SetMin(1);
        s.AddConstraint(s.MakeNonEquality(diff1, diff2));
        k = next_k;
        l = next_l;
        }
    }
}
改进后的code2:

for (int i = 1; i < n; ++i) {
    for (int j = i + 1; j <= n; ++j) {
         Y[i][j] = s.MakeDifference(X[j], X[i])->Var();
         Y[i][j]->SetMin(1);
    }
}
int k, l, next_k, next_l;
for (int i = 1; i < n - 1; ++i) {
    for (int j = i + 1; j <= n; ++j) {
        k = i; l = j;
        while (next_interval(n, k, l, &next_k, &next_l)) {
        s.AddConstraint(s.MakeNonEquality(Y[i][j],Y[next_k][next_l]));
        k = next_k;
        l = next_l;
        }
     }
}
(如此采用Y[i][j]能大幅度提高求解性能)

2、建模时尽量使用全局约束(global constraint)。全局约束有更有助于约束传递和域收敛。我们对code1再次改进为code3.code1 中的s.MakeNonEquality为两两的局部比较,code3中s.MakeAllDifferent(Y)则为全局的比较。

code3:

std::vector<IntVar*> Y;
for (int i = 1; i <= n; ++i) {
    for (int j = i + 1; j <= n; ++j) {
          IntVar* const diff = s.MakeDifference(X[j], X[i])->Var();
          Y.push_back(diff);
          diff->SetMin(1);
     }
}
s.AddConstraint(s.MakeAllDifferent(Y));

总结:

1、中间变量记录expression的值的用法能大幅度提高模型求解效率,这种技巧不仅仅在CP 中有体现,笔者在采用LocalSolver建模时也深有体会。

2、ILOG-CP 中Scheduler包也是非常推崇全局约束的使用,例如noOverlap()等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值