Current location - Training Enrollment Network - Mathematics courses - MiniZinc (2) model abstraction for optimization modeling-separation of model and data
MiniZinc (2) model abstraction for optimization modeling-separation of model and data
In the first article, we introduced the basic components of the MiniZinc project.

As a review, we can look at a production planning problem:

We are at loggerheads with the Indian army at the border because we won't shoot. We want to produce a batch of cold weapons to arm the army. Spears, swords and hammers are optional. It takes some resources and craftsmen's time to produce weapons. The corresponding resource consumption of weapons is as follows:

Our resources are limited:

Each weapon corresponds to a certain combat effectiveness:

We hope to make full use of limited resources and maximize the combat effectiveness of our troops. How many pieces of each weapon do we need to produce?

The corresponding model is as follows:

By solving, we can get the answer:

Regarding the array and some built-in functions in the model, you can pull down to the back to see the explanation of MiniZinc syntax.

There seems to be nothing wrong with the above model, and it has been solved smoothly. But many times, we will face a series of hypothetical questions when modeling: what if I have more resources? What if I add some weapons to choose from?

We need to constantly modify the concrete model above to cope with the ever-changing data.

What if we are planning our final review plan instead of solving a weapon production problem? Do we need to rewrite the whole model?

In the practice of software engineering, the important enlightenment of design pattern is to separate the changing part from the relatively stable part, which is also true for our model. Similar production planning models have some similarities, so we can extract the thinking part and then separate the data.

Production planning model

In the production planning model, we can extract some similarities:

According to these similarities, we can generate an abstract model (2 _ 2 _ abstract production model. MZN):

We can see that there is no data in the abstract model. In this way, we separate the model from the data. For the same model, we can use it to solve different data sets with the same properties.

For verification, we can set up an independent data set 2_2_WeaponProduction.dzn for our weapon production problem as follows:

Run minizinc-solver bc2 _ 2 _ abstract production model.mzn2 _ 2 _ weaponproduction.dzn on the command line to specify the data set and solver to be solved, and get the result:

It can be seen that on the issue of weapons production, we have obtained the same results as before.

Allocation of self-study time

The advantage of abstract model is that it can deal with a kind of problems with the same model. Using the production problem model established earlier, we can look at the following time allocation problems:

We are faced with the final exams of three courses: operations research, discrete mathematics and C language. For each course review, an ideal scheme is to allocate a certain amount of computer review, discussion and book self-study respectively. The time ratio of the ideal review plan for each course is as follows:

However, due to the time constraints of the computer room, discussion room and study room, we can make an appointment as follows before the exam comes:

For every hour spent on different subjects, we can improve different GPA:

Assuming that our starting point is very low, this round of review will not brush the GPA of any subject, but we hope to brush the GPA as high as possible, so how should we allocate the rest of the review time?

We found that this problem is actually a production problem, and we don't need to make any changes to the model, just need to modify the data set. We create a data file 2_2_SwotUp.dzn and put it into the corresponding courses, time and benefits:

Run minizinc-solver bc2 _ 2 _ abstractproductmodel.mzn2 _ 2 _ swotup.dzn on the command line to solve:

Get the result:

Therefore, when modeling, it is usually suggested to abstract the model and separate the model file from the data file.

In the above program, we used the following statement:

This statement defines a two-dimensional array consumption, and its dimensions are weapons and resources respectively.

Array is a commonly used data structure. Below we will introduce the related knowledge of arrays:

Arrays can be one-dimensional or multidimensional, and they are declared in the following format:

Array [index_set 1, index_set2, ...] of <; type & gt

An array subscript set can be an enumeration type or a set expression.

The elements in an array can be of any built-in type except arrays, which means that MiniZinc does not support array nesting.

one-dimensional array

For one-dimensional arrays, we can initialize them through lists like most other languages, such as the following example:

two-dimensional array

Initialization of two-dimensional array in MiniZinc has specific syntax:

The two-dimensional array defined above is an example:

Pay special attention to the ending and don't forget the | symbol.

Built-in functions initialize arrays of arbitrary dimensions.

For any array whose k dimension is not greater than 6, we can initialize it with the built-in function arraykd, for example:

It is equivalent to our one-dimensional and two-dimensional array initialization method above.

In addition to using built-in functions or list forms for initialization accidents, MiniZinc also provides the same deductive way as Python to initialize arrays. Its syntax is:

[& lt; Expressions & gt| & ltgenerator-expr 1 >, & ltgenerator-expr2 >,...]

In the process of derivation, we can also carry out some tests:

[& lt; Expressions & gt| & ltgenerator-expr 1 >, & ltgenerator-expr2 >, ..., where & lt Boolean expression & gt]

take for example

Generate the following two arrays.

Note that because we don't know the length of the array in advance, we use array[int] to let the solver deduce the length of the array itself.

Accordingly, a set can also be generated by derivation, and the only difference is that [] is replaced by {}.

Because of the application of list derivation, we may not know the range of list subscripts. At this point, we can use the built-in function index_set to get the subscript range of one-dimensional array.

For example:

Here our k will get the range of 1 ... 12.

For multidimensional arrays, we need to specify the total dimension k of the array and the subscript of which dimension m we want to know.

A series of functions index _ set _

MiniZinc supports four basic integer operations: addition, subtraction, multiplication and division:+,-,*, div. For floating-point numbers, division is expressed as/.

& ltu> Note that the integer division here is div instead of/,and/specifically refers to the division of floating-point numbers in MiniZinc. When dealing with integers, you may get unexpected results.

In addition, there is a commonly used remainder mod. The integer remainder operation a mod b will get the same result as the symbol A, that is to say, there must be a = b * (a div b)+(a mod b).

Here are some built-in operation functions commonly used by MiniZinc.

For numbers:

For arrays: