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 等