我只是个初学者,想看看我是否能在日常生活中使用minizinc。我试图建立的第一个模型是这里,数据文件是这里
基本上,我想做的就是这个。一方面,我有一组具有一些属性的虚拟机,比如一些内核、RAM等等。另一方面,我从云提供商那里提取了一组VM。它们也有相似的属性和价格。我要做的是匹配它们,然后在云中相应VM的大小与其价格之间找到最佳平衡。
例如,如果我有一个有两个核心和8GB RAM的VM。为了与之匹配,我可能会使用云提供商提供的几种VM,这些VM应该具有不少于2个内核和不少于8GB的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,但是它太慢了,永远无法找到最优的解决方案。
我做错什么了吗?在哪里?也许我需要以不同的方式设置目标函数,但我不能真正理解我应该改变什么,以及为什么它不能以这种方式工作。
谢谢!
发布于 2021-11-25 06:01:02
CBC求解程序抛出错误backend cannot handle constraint: float_div的原因是该求解器不支持非线性约束,例如目标targetFunc中的div约束。它只支持线性约束。
有些求解器确实支持非线性浮点约束,例如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解算器都可以使用,例如,PicatSAT,或工具,等等.
https://stackoverflow.com/questions/70092487
复制相似问题