我正在使用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 }
但是,存在一个约束条件,p3
和p4
在解决方案中不能在一起,因为它们不兼容。
是否可以定义不兼容约束来定义p3
和p4
是不兼容的变量?
编辑
我正在考虑使用类似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上看到的,这是正确,但不可行。
答案 0 :(得分:1)
我现在看到p3
和p4
是连续的。 (如果它们实际上是二进制的,请参见this answer。)在这种情况下,添加两个新的二进制变量,例如z3
和z4
,如果p3
和{{ 1}}(分别)大于零:
p4
其中p3 <= Mz3
p4 <= Mz4
是一个大数字。然后添加约束
M
前两个约束条件表明,如果z3 + z4 <= 1
,则p3 > 0
必须等于z3
(对于1
和p4
也是如此)。第三个约束条件是z4
和z3
中的一个最多可以等于1,即z4
和p3
中的一个最多可以是正数。
如果p4
和p3
不受限制(允许为正数或负数),并且您想要求其中最多一个为 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)
如果p3
和p4
是二进制的,则可以使用
p3 + p4 <= 1
或者如果您想恰好其中之一等于1,则使用
p3 + p4 = 1
我对jsLPSolver的语法不熟悉,但是上面的约束提供了逻辑。