Minizinc model fails with "MiniZinc: internal error: Error: solver backend cannot handle constraint: float_div"
Minizinc model fails with "MiniZinc: internal error: Error: solver backend cannot handle constraint: float_div"
我只是一个初学者,想看看我是否可以在日常工作中使用 minizinc。我尝试制作的第一个模型是 here and the data file is here
基本上,我要做的就是这个。一方面,我有一组具有某些属性的虚拟机,例如多个内核、RAM 等。另一方面,我有一组从云提供商那里提取的虚拟机。它们也具有相似的特性和价格。我要做的是匹配它们,然后在云中相应 VM 的大小与其价格之间找到最佳平衡。
例如,如果我有一个具有 2 个内核和 8 GB RAM 的 VM。为了匹配它,我可能会使用来自云提供商的几种 VM,它们应该具有不少于 2 个内核和不少于 8 GB 的 RAM/但是对于这些 VM 的集合,我希望将总体成本降到最低,并且同时尝试最大化性能,这是在 ACUs
云提供商方面衡量的。
我想使用 var float: targetFunc = (0.9 * totalPrice) / (0.1 * totalACU);
作为目标函数,假设系数将帮助我针对价格与性能微调模型。但是,也许我做错了。
为了简单起见,我只是复制并粘贴下面的代码。
enum existingVMs;
enum vmSizes;
enum vmDisks;
array[existingVMs] of int: vmCPU;
array[existingVMs] of int: vmRAM;
array[existingVMs] of int: vmDisk;
array[existingVMs] of int: vmCpuToRamRatio;
array[vmSizes] of int: vmSizeCPU;
array[vmSizes] of float: vmSizeRAM;
array[vmSizes] of int: vmSizePrice;
array[vmSizes] of int: vmSizeACU;
array[vmSizes] of int: vmSizeCpuToRamRatio;
array[vmDisks] of int: vmDiskSizes;
array[vmDisks] of float: vmDiskPrice;
array[existingVMs] of var vmSizes: selectedSize;
array[existingVMs] of var vmDisks: selectedDiskSize;
constraint forall(vm in existingVMs)(
vmSizeACU[selectedSize[vm]] > 50
);
constraint forall(vm in existingVMs)(
vmSizeRAM[selectedSize[vm]] >= vmRAM[vm]
);
constraint forall(vm in existingVMs)(
vmSizeCPU[selectedSize[vm]] >= vmCPU[vm] * 0.8
);
var int: totalPrice = sum(vm in existingVMs)(vmSizePrice[selectedSize[vm]]);
var int: totalACU = sum(vm in existingVMs)( vmSizeACU[selectedSize[vm]] );
var float: targetFunc = (0.9 * totalPrice) / (0.1 * totalACU);
solve maximize targetFunc;
output [ "\(totalPrice); \(totalACU)\n" ++ join("\n", ["\(vm), \(vmCPU[vm]), \(vmRAM[vm]), " ++
"\(vmDisk[vm]), \(selectedSize[vm]), \(vmSizeCPU[selectedSize[vm]]), " ++
"\(vmSizeRAM[selectedSize[vm]]), \(vmDiskSizes[selectedDiskSize[vm]]), " ++
"\(vmSizePrice[selectedSize[vm]]), \(vmSizeACU[selectedSize[vm]])" | vm in existingVMs]) ]
我运行它是:
minizinc.exe -i --solver coin-bc -s -a C:\Work\tools\demo\graphs-n-minizinc-demo\vmCostsCalculation.mzn C:\Work\tools\demo\graphs-n-minizinc-demo\vmData.dzn
并得到以下响应
82 POSTs [ 0,0,0,0,0,0,0,0,0,0, ], LINEQ [ 0,0,0,0,0,0,0,0,82, ], 82 / 82 vars, 82 cliques, 1 / 1 / 1 NSubIntv m/a/m, 252 / 252 / 252 SubIntvSize m/a/m, 82+0(0) clq eq_encoded ... % Generated FlatZinc statistics:
%%%mzn-stat: paths=0
%%%mzn-stat: flatIntVars=21158
%%%mzn-stat: flatFloatVars=20831
%%%mzn-stat: flatIntConstraints=412
%%%mzn-stat: flatFloatConstraints=20831
%%%mzn-stat: method="maximize"
%%%mzn-stat: flatTime=4.09564
%%%mzn-stat-end
MiniZinc: internal error: Error: solver backend cannot handle constraint: float_div
我尝试使用 gecode
但是它太慢了,而且永远无法找到最优解。
我是不是哪里做错了什么?也许我需要以不同的方式设置目标函数,但我真的不明白我应该改变什么以及为什么它不能这样工作。
谢谢!
CBC求解器报错backend cannot handle constraint: float_div
的原因是这个求解器不支持非线性约束,比如objective中的div
约束targetFunc
.它只支持线性约束。
有些求解器确实支持非线性浮点约束,例如 Gecode、JaCoP、OptiMathSAT 和 Choco。
为了加快 Gecode 求解器的速度,您可以尝试将搜索启发式添加到 solve
函数中,例如:
solve :: int_search(selectedDiskSize,first_fail,indomain_split) maximize targetFunc;
此处描述了搜索注释:https://www.minizinc.org/doc-2.4.3/en/lib-annotations.html#search-annotations .
我要求较小的数据集的原因是,在这些情况下,人们可能会尝试不同的启发式方法,然后较小的数据集可以更快地获得好的选择。
在数据和模型中使用浮点值限制了可以使用的 FlatZinc 求解器的范围。还有很多求解器可以处理仅包含整数变量和值的模型。
所以另一种方法可能是将所有浮点值转换为整数(通过乘以某个常数,并相应地调整其他值)。然后可以使用所有其他 FlatZinc 求解器,例如Chuffed、OR-tools、PicatSAT 等
我只是一个初学者,想看看我是否可以在日常工作中使用 minizinc。我尝试制作的第一个模型是 here and the data file is here
基本上,我要做的就是这个。一方面,我有一组具有某些属性的虚拟机,例如多个内核、RAM 等。另一方面,我有一组从云提供商那里提取的虚拟机。它们也具有相似的特性和价格。我要做的是匹配它们,然后在云中相应 VM 的大小与其价格之间找到最佳平衡。
例如,如果我有一个具有 2 个内核和 8 GB RAM 的 VM。为了匹配它,我可能会使用来自云提供商的几种 VM,它们应该具有不少于 2 个内核和不少于 8 GB 的 RAM/但是对于这些 VM 的集合,我希望将总体成本降到最低,并且同时尝试最大化性能,这是在 ACUs
云提供商方面衡量的。
我想使用 var float: targetFunc = (0.9 * totalPrice) / (0.1 * totalACU);
作为目标函数,假设系数将帮助我针对价格与性能微调模型。但是,也许我做错了。
为了简单起见,我只是复制并粘贴下面的代码。
enum existingVMs;
enum vmSizes;
enum vmDisks;
array[existingVMs] of int: vmCPU;
array[existingVMs] of int: vmRAM;
array[existingVMs] of int: vmDisk;
array[existingVMs] of int: vmCpuToRamRatio;
array[vmSizes] of int: vmSizeCPU;
array[vmSizes] of float: vmSizeRAM;
array[vmSizes] of int: vmSizePrice;
array[vmSizes] of int: vmSizeACU;
array[vmSizes] of int: vmSizeCpuToRamRatio;
array[vmDisks] of int: vmDiskSizes;
array[vmDisks] of float: vmDiskPrice;
array[existingVMs] of var vmSizes: selectedSize;
array[existingVMs] of var vmDisks: selectedDiskSize;
constraint forall(vm in existingVMs)(
vmSizeACU[selectedSize[vm]] > 50
);
constraint forall(vm in existingVMs)(
vmSizeRAM[selectedSize[vm]] >= vmRAM[vm]
);
constraint forall(vm in existingVMs)(
vmSizeCPU[selectedSize[vm]] >= vmCPU[vm] * 0.8
);
var int: totalPrice = sum(vm in existingVMs)(vmSizePrice[selectedSize[vm]]);
var int: totalACU = sum(vm in existingVMs)( vmSizeACU[selectedSize[vm]] );
var float: targetFunc = (0.9 * totalPrice) / (0.1 * totalACU);
solve maximize targetFunc;
output [ "\(totalPrice); \(totalACU)\n" ++ join("\n", ["\(vm), \(vmCPU[vm]), \(vmRAM[vm]), " ++
"\(vmDisk[vm]), \(selectedSize[vm]), \(vmSizeCPU[selectedSize[vm]]), " ++
"\(vmSizeRAM[selectedSize[vm]]), \(vmDiskSizes[selectedDiskSize[vm]]), " ++
"\(vmSizePrice[selectedSize[vm]]), \(vmSizeACU[selectedSize[vm]])" | vm in existingVMs]) ]
我运行它是:
minizinc.exe -i --solver coin-bc -s -a C:\Work\tools\demo\graphs-n-minizinc-demo\vmCostsCalculation.mzn C:\Work\tools\demo\graphs-n-minizinc-demo\vmData.dzn
并得到以下响应
82 POSTs [ 0,0,0,0,0,0,0,0,0,0, ], LINEQ [ 0,0,0,0,0,0,0,0,82, ], 82 / 82 vars, 82 cliques, 1 / 1 / 1 NSubIntv m/a/m, 252 / 252 / 252 SubIntvSize m/a/m, 82+0(0) clq eq_encoded ... % Generated FlatZinc statistics:
%%%mzn-stat: paths=0
%%%mzn-stat: flatIntVars=21158
%%%mzn-stat: flatFloatVars=20831
%%%mzn-stat: flatIntConstraints=412
%%%mzn-stat: flatFloatConstraints=20831
%%%mzn-stat: method="maximize"
%%%mzn-stat: flatTime=4.09564
%%%mzn-stat-end
MiniZinc: internal error: Error: solver backend cannot handle constraint: float_div
我尝试使用 gecode
但是它太慢了,而且永远无法找到最优解。
我是不是哪里做错了什么?也许我需要以不同的方式设置目标函数,但我真的不明白我应该改变什么以及为什么它不能这样工作。
谢谢!
CBC求解器报错backend cannot handle constraint: float_div
的原因是这个求解器不支持非线性约束,比如objective中的div
约束targetFunc
.它只支持线性约束。
有些求解器确实支持非线性浮点约束,例如 Gecode、JaCoP、OptiMathSAT 和 Choco。
为了加快 Gecode 求解器的速度,您可以尝试将搜索启发式添加到 solve
函数中,例如:
solve :: int_search(selectedDiskSize,first_fail,indomain_split) maximize targetFunc;
此处描述了搜索注释:https://www.minizinc.org/doc-2.4.3/en/lib-annotations.html#search-annotations .
我要求较小的数据集的原因是,在这些情况下,人们可能会尝试不同的启发式方法,然后较小的数据集可以更快地获得好的选择。
在数据和模型中使用浮点值限制了可以使用的 FlatZinc 求解器的范围。还有很多求解器可以处理仅包含整数变量和值的模型。
所以另一种方法可能是将所有浮点值转换为整数(通过乘以某个常数,并相应地调整其他值)。然后可以使用所有其他 FlatZinc 求解器,例如Chuffed、OR-tools、PicatSAT 等