how to port a minizinc model into Z3 using C# API via PowerShell #5790
-
Hello colleagues, I have a minizinc model, which is supposed to solve an "assignment" problem. Basically, having a list of Virtual Machine objects with their attributes, I'm trying to map them to their counterparts in Azure, in such a way that the counterpart has enough vCPUs and RAM. Additionally, I'm trying to minimize the target cost and maximize the performance attributes. To make it a bit more interactive, easier to use from the command line I'm want to use .NET interface through PowerShell. It allows to combine all necessary tools under the same umbrella, so one does not need to install anything except PowerShell, basically The minizinc model is here. So what I'm trying to do is literally map it to z3. First, I'm preparing necessary data by reading a few CSV files and indexing that data to hashtables, just to speed up access # import raw VM data and convert strings to ints
$sourceVMs = Import-Csv .\vmdata.csv
$sourceVMs | % { $_.cpu = [int]$_.cpu; $_.ram = [int]$_.ram; $_.datadisk = [int]$_.datadisk; }
$targetSizes = import-csv ".\vmCostACUData.csv"
## hash tables with data to simplify search
$sourceVmHt = @{}
$targetVmHt = @{}
$sourceVMs | % {
$sourceVmHt[$_.vmID] = $_
}
$targetSizes | % {
$targetVmHt[$_.Name] = $_
}
## Next, I basically create the necessary enums, as I did in the minizinc model. They are supposed to limit possible values of the decision variables and serve as indexes in some cases. # enum existingVMs;
# enum vmSizes;
$existingVMs = $ctx.MkEnumSort("existingVMs", $sourceVMs.vmid)
$vmSizes = $ctx.MkEnumSort("vmSizes", $targetSizes.Name) Create a bunch of decision variables, each of which is supposed to contain a name of that target VM size, calculated by the model, and store them in the array $selectedSize =
$sourceVMs | % {
$ctx.MkConst($_.vmid, $vmSizes)
} and add two main constraints # constraint forall(vm in existingVMs)(
# vmSizeCPU[selectedSize[vm]] >= vmCPU[vm]
# );
## assuming $_.ToString() returns the name of the variable
## and $_ it's value
$selectedSize | % {
$a = $ctx.MkNumeral($sourceVmHt[$_.ToString()].cpu, $ctx.MkIntSort())
$b = $ctx.MkNumeral($targetVmHt[$_].vCPUs, $ctx.MkIntSort())
$s.Add( $ctx.MkGt($a, $b))
}
# constraint forall(vm in existingVMs)(
# vmSizeRAM[selectedSize[vm]] >= vmRAM[vm]
# );
$selectedSize | % {
$a = $ctx.MkNumeral($sourceVmHt[$_.ToString()].ram, $ctx.MkIntSort())
$b = $ctx.MkNumeral($targetVmHt[$_].MemoryGB, $ctx.MkIntSort())
$s.Add( $ctx.MkGt($a, $b))
} At this point I expect the model to return at least something, but it returns an empty model PS C:\Work\z3tests> c:\Work\z3tests\z3.ps1
SATISFIABLE
PS C:\Work\z3tests> $m
NumConsts : 0
ConstDecls : {}
Consts : {}
NumFuncs : 0
FuncDecls : {}
Decls : {}
NumSorts : 0
Sorts : {} At least this is what I think I'm doing :) The question here is - what I'm doing wrong, and what should I do to make it right? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 21 replies
-
ctx.MkNumeral tries to parse your string as a numeric constant not as a variable. Use MkConst |
Beta Was this translation helpful? Give feedback.
-
I don't expect z3 to do well on problem domains it is not tuned for. It is not built specifically for OR domains. |
Beta Was this translation helpful? Give feedback.
I don't expect z3 to do well on problem domains it is not tuned for. It is not built specifically for OR domains.
These domains where z3 is not a suitable tool include LP problems, especially problems where constants are provided with a large decimal expansion and IP problems with bounded numbers. The sweet spot in some cases is discrete domains where you can leverage SMT features. See http://theory.stanford.edu/~nikolaj/supercharging.html for a case study.