Quick note 1: the data input format for MiniZinc model is, in general, dictated by the model. Therefore, we cannot use a generic interface such as JSON or YAML.
Quick note 2: depending on the MiniZinc version, we can describe empty matrices like "M = []". On version 2.2.1, we have to build an empty matrices explicitly: "M = array2d(0..0, 1..10, [])". The dimensions must agree with the model. So, for example, if you have in the model file:
Code Block | ||
---|---|---|
| ||
int: numElements;
int: numAttributes;
array[1..numElements, 1..numAttributes] of int: attributes; |
but we have no attributes, the data file should look like this:
Code Block | ||
---|---|---|
| ||
numElements = 4; numAttributes = 0; % attributes = []; does not work on version 2.2.1 attributes = array2d(1..numElements, 1..numAttributes, []); % attributeConcurrencyLimit = []; does not work on version 2.2.1 attributeConcurrencyLimit = array2d(1..numAttributes, 1..maxTime, []); |
Note that you may use a simpler syntax in other MiniZinc versions.
For generic model model generic_attributes.mzn, this is one possible data input file (lines starting with % are comments, and they are not needed in the file):
Code Block | ||
---|---|---|
| ||
numElements = 3;5; maxTime = 5; numLoaders = 1; maxTime = 5; noConflict = [| true , true , true , true , true | true , true , true , true , true | false , true , false , true , false |]; elementSlotCapacity |= false[1, 2, false1, 3, false , false , false | true , false , true , false , true |]; slotCapacity = [5, 5, 5, 5, 5]; 3]; % Since the (unique) loader has virtually % infinity capacity, we assign the number % of elements as capacity. % We can also do: % loaderCapacity = [| % numElements, numElements, numElements, numElements, numElements % |]; loaderCapacity = [| 53, 53, 53, 53, 5 3 |]; numAttributes = 0; attributesRange = []; % attributes = []; does not work on version 2.2.1. % We must built it explicitly attributes = array2d(1..numElements, 1..numAttributes, []); % attributeConcurrencyLimit = []; does not work on version 2.2.1. % We must built it explicitly attributeConcurrencyLimit = array2d(1..numAttributes, 1..maxTime, []); |
This request will represent the information gathered by the Scheduler Optimizer to be passed to the Mini Zinc schedule optimizer engine.
...
- numLoaders is 1 (scheduler)
- loaderCapacity is unlimited (scheduler must be able to support the slotCapacity)
- numAttributes, attributeRange, attributes and attributeConcurrencyLimit - From policy / templates.
To solve the problem, we use the following command line:
Code Block | ||
---|---|---|
| ||
$ minizinc --solver OSICBC --time-limit 60000 --soln-sep '' --search-complete-msg '' generic_attributes.mzn generic_attributes_3.dzn |
where:
- --solver OSICBC: uses the Coin CBC solver, with is the preferable solver in the most cases. For cases it does not work, we recommend to use Google OR tools. Other academic/experimental solvers like Gecode are slow and we do not recommend them for production;
- --time-limit 60000: 60 seconds of time limit. If the input is big, the solver may require more time to deploy a solution;
- --soln-sep '': avoid to print "----" between solutions;
- --search-complete-msg '': avoid to print "====" between solutions in the end.
This is the result output when using the command line (it may varies if using IDE or underline solver):
Code Block | ||||
---|---|---|---|---|
| ||||
results: - results: result: num_scheduled: 0 total_completion_time: 0 element_slot_loader: | 1,0,1 2,0,1 3,0,1 4,0,1 5,0,1 result: num_scheduled: 1 total_completion_time: 2 element_slot_loader: | 1,0,1 2,0,1 3,2,1 4,0,1 5,0,1 result: num_scheduled: 43 total_completion_time: 85 element_slot_loader: | 1,2,1 2,1,1 3,2,1 4,0,1 5,3,1 elapsed_millis: 3400 |
This request will represent the information returned to the Scheduler Optimizer from the Mini Zinc schedule optimizer engine.
Multiple "schedules" may be returned the objective being to schedule the most changes in the least amount of time.
Other important notes:
Remember that we are going towards descriptive models that aims to make it easier to add and remove constraints on the fly. Currently, OOF is not doing that yet, but using the models as static ones. In this modeling approach, one we have the model, we need to create the input data for it (in general, in a specific format dictated by the model). Therefore, any pre-processing or "imperative" operation must be done outside of the model. As modeling language, we chose MiniZinc, that is an open-source language and translation system. To solve the problem itself, MiniZinc calls an underlying solver such as Coin CBC, Google OR-tools, Gecode, and others (from an open-source side), and IBM ILOG CPLEX, and SCIP (from commercial and custom licensing). So, MiniZinc does not solve anything, but the underlying solver. Therefore, the performance relies on how we model the problem, and which solver we choose to solve the problem. Not all solvers can solve all problems (there is no silver bullet here). Satisfiability models are better solved with Google OR-tools (constraint programming model), and optimization models with Coin CBC (assuming we are not using any commercial solver for this).