是否可以定义不兼容约束?

时间:2019-05-10 18:35:50

标签: integer-programming operations-research

我正在使用jsLPSolver解决整数编程问题。

我无法调整模型以包含不兼容约束。 我有以下模型:

{
    "optimize": "cost",
    "opType": "min",
    "constraints": {
        "c1": { "min": 36000.0, "max": 36800.0 },
        "c2": { "min": 12000.0, "max": 12800.0 },
        "c3": { "equal": 1000.0 }
    },
    "variables": {
        "p1": { "c1": 0, "c2": 0, "c3": 1, "cost": 437.47, },
        "p2": { "c1": 0, "c2": 60.0, "c3": 1, "cost": 1964.49, },
        "p3": { "c1": 34.0, "c2": 0, "c3": 1, "cost": 1428.98, },
        "p4": { "c1": 46.0, "c2": 0, "c3": 1, "cost": 1973.11, }
    },
    "ints": { "p1": 1, "p2": 1, "p3": 1, "p4": 1 }
}

可行结果

{ bounded: true, feasible: true, p2: 200, p3: 66, p4: 734, result: 1935473.42 }

但是,存在一个约束条件,p3p4 在解决方案中不能在一起,因为它们不兼容。

是否可以定义不兼容约束来定义p3p4是不兼容的变量?

编辑

我正在考虑使用类似p3 + p4 = 0的约束:

{
    "optimize": "cost",
    "opType": "min",
    "constraints": {
        "c1": { "min": 36000.0, "max": 36800.0 },
        "c2": { "min": 12000.0, "max": 12800.0 },
        "c3": { "equal": 1000.0 },
        "incompatible": { "equal": 0.0 }
    },
    "variables": {
        "p1": { "c1": 0, "c2": 0, "c3": 1, "cost": 437.47, "incompatible": 0.0 },
        "p2": { "c1": 0, "c2": 60.0, "c3": 1, "cost": 1964.49, "incompatible": 0.0 },
        "p3": { "c1": 34.0, "c2": 0, "c3": 1, "cost": 1428.98, "incompatible": 1.0 },
        "p4": { "c1": 46.0, "c2": 0, "c3": 1, "cost": 1973.11, "incompatible": 1.0 }
    },
    "ints": { "p1": 1, "p2": 1, "p3": 1, "p4": 1 }
}

但是请查看在这种情况下解决方案会发生什么:

{ bounded: true, feasible: false, p2: 200, p3: -3000, p4: 3000, result: 0 }
https://runkit.com/tetrimesquita/incompatible-contraint上看到的

,这是正确,但不可行

3 个答案:

答案 0 :(得分:1)

我现在看到p3p4是连续的。 (如果它们实际上是二进制的,请参见this answer。)在这种情况下,添加两个新的二进制变量,例如z3z4,如果p3和{{ 1}}(分别)大于零:

p4

其中p3 <= Mz3 p4 <= Mz4 是一个大数字。然后添加约束

M

前两个约束条件表明,如果z3 + z4 <= 1 ,则p3 > 0必须等于z3(对于1p4也是如此)。第三个约束条件是z4z3中的一个最多可以等于1,即z4p3中的一个最多可以是正数。

如果p4p3不受限制(允许为正数或负数),并且您想要求其中最多一个为 nonzero ,则还要添加:

p4

答案 1 :(得分:0)

可能不是最优雅的版本,但这应该可以做到:

var solver = require("javascript-lp-solver");

var model = {
    "optimize": "cost",
    "opType": "min",
    "constraints": {
        "c1": { "min": 36000.0, "max": 36800.0 },
        "c2": { "min": 12000.0, "max": 12800.0 },
        "c3": { "equal": 1000.0 }
    },
    "variables": {
        "p1": { "c1": 0, "c2": 0, "c3": 1, "cost": 437.47, },
        "p2": { "c1": 0, "c2": 60.0, "c3": 1, "cost": 1964.49, },
        "p3": { "c1": 34.0, "c2": 0, "c3": 1, "cost": 1428.98, },
    },
    "ints": { "p1": 1, "p2": 1, "p3": 1}
}

var results_p3 = solver.Solve(model);

var model = {
    "optimize": "cost",
    "opType": "min",
    "constraints": {
        "c1": { "min": 36000.0, "max": 36800.0 },
        "c2": { "min": 12000.0, "max": 12800.0 },
        "c3": { "equal": 1000.0 }
    },
    "variables": {
        "p1": { "c1": 0, "c2": 0, "c3": 1, "cost": 437.47, },
        "p2": { "c1": 0, "c2": 60.0, "c3": 1, "cost": 1964.49, },
        "p4": { "c1": 46.0, "c2": 0, "c3": 1, "cost": 1973.11, }
    },
    "ints": { "p1": 1, "p2": 1, "p4": 1 }
}

var results_p4 = solver.Solve(model);

var finalResults = (results_p3.feasible && (results_p3.result < results_p4.result)) ? results_p3 : results_p4;

console.log(results_p3);
console.log(results_p4);
console.log(finalResults);

想法是您运行模型两次-一次固定p3,一次固定p4。然后,您采取遵循约束条件并产生更好结果的解决方案[1]。

在此处查看输出:

https://runkit.com/dionhaefner/so-incompatible-constraint

[1]您可能应该稍微完善一下最后的检查。例如,如果两个结果都不可行怎么办?如果两个结果均为0怎么办?您可能还必须检查bounded属性。

答案 2 :(得分:0)

如果p3p4是二进制的,则可以使用

p3 + p4 <= 1

或者如果您想恰好其中之一等于1,则使用

p3 + p4 = 1

我对jsLPSolver的语法不熟悉,但是上面的约束提供了逻辑。