Our three heroes are interested.
If they had more money, how much better an army could they have?
So here's our army model that we made a few lectures ago,
but we've made one change.
So before we had that the budget was 10,000, but
we've removed that, so we've left the budget unspecified.
So this is a parameter where we haven't given it the value.
This is a parameter without a value.
So, we need to run that.
So when we run that model, we're going to have to give that parameter a value.
So a parameter is not a decision, so it has to be given a value before
the solver can actually know what problem it's solving.
So we're going to have to get that value some way.
So one way is to do it this way, so we're running with a model file and
a data file, army.dzn.
And we'll assume this data file here has this content, budget equals 20000.
So this is an assignment giving the missing value to budget.
So now the parameter, budget, has a value, and now it can be solved.
And we'll get a new description saying, okay, if we have that much army,
that much money, then we could get this army, which will be the better army.
Alternatively, we can do it this way.
Since this data file is so small,
we can actually put the data file on the command line.
And we do this with this -D flag, and
then this string here, budget = 20000, is in fact the data file, itself.
So we can run this alternatively this way by putting the missing
values to the parameters on the command line, itself.
Okay, of course,
we can use the integrated development environment to do this instead.
If we run this model, MiniZinc will realize, hang on,
you haven't given me a value for a parameter.
It will actually pop up a window and ask you to type in the missing parameter.
So we can type in the missing parameter for
budget here, and hit Continue and we'll get a solution.
Another way to do it is if we have army.dzn loaded into the IDE and
we free run, we can select a data file from this drop-down menu when we run.
And that will allow us to select army.dzn which has the parameter value for
budget, and that will also allow us to give the parameter a value.
The brothers observed that there was a shortage of soldiers in their army, so
they planned to recruit some more, but
they needed to loan money from some business man in order to afford this.
Zhang Shiping suggested that they ask his friend, Su Shuang, for the loan.
Zhang Shiping spoke highly of the brothers and encouraged Su Shuang to help them.
The businessman, Su Shuang, agreed to lend money to the brothers, provided they would
pay back the loan, plus interest, over four installments in the following year.
Liu Bei tried to figure out exactly how much they needed to pay back
each installment.
He took out the magical tablet.
So our heroes go with Zhang Shiping to the money lender in order to get
some more money to hire a bigger army.
So, the money lender will lend them some money, but they're going to
have to make a repayment at the end of every season, that is, every quarter.
So let's look at the way the loan is going to work.
The money lender will lend them an amount, which is the principle.
That's how much money they get to lend.
They'll make a regular repayment, R, and there's a quarterly interest rate, I.
And at the end of Ith quarter, the balance that they'll owe, the I, is given by
the previous balance, plus the interest on the previous balance minus the repayment.
So let's look at a MiniZinc model to do that.
So here's our model.
Now we got some some new features.
So here we have here a float variable, so
var float: R; defining the repayment amount which is going to be unknown.
And here we have a float range, from 0.0 to 2.0, so
that's the interest rate between 0% to 200%.
So that is going to be another decision, possibly.
So let's look at our model.
So we've basically got these decisions, the repayment, the principal,
the balances after each of the quarters, and then the constraints that relate them.
So the balance after the first quarter, we take the principal,
we multiply by 1.0 + the interest rate to get the new principal plus the interest,
and we subtract the repayment.
Similarly, the balance after the second quarter is we take the balance after
the first quarter and do the same calculation.
And we can see the same thing for each of the other quarters.
And then we're going to ask to find a solution, and
we'll have a complicated output function which we won't show you for lack of space.
Now, let's ask some questions of this model.
So if Liu Bei wants to borrow $10000 at 4%,
repaying $2600 every quarter, how much does he owe at the end?
So we can have a data file that defines this instance by saying, well,
the interest rate is 4%, the principal is 10000 and the repayment is 2600.
And we can run the model by saying minizinc loan.mzn loan1.dzn.
So this is our data file here for this particular set of data.
And if we run this, we'll get the result saying that at the end we're going to
owe $657.78.
So how would we use the IDE?
Well, it's a bit tricky here because MiniZinc's
expecting when you use the IDE to fill in parameter values,
and here we're actually filling in decision variable values.
So it won't, by default, ask you for a data file.
But we can go to the configuration page, and select a data file in this top,
select a field, that's one way of doing it, and then type run.
Or, if we've got a project file open, we can go down, find the data file we're
interested with, have our model open, here, and say, run with this data file.
And that will also allow us to run our model with the data file.
So we can ask different questions with this model,
that's one of the reasons of our having different data files.
And, here, because we're changing the variables,
the decision variables that we're giving, we're asking different kinds of questions.
So if Liu Bei wants to borrow 10000 at 4% and
owe nothing at the end, how much does he have to repay each quarter?
So here's the data file for this where we're given the interest rate,
the principal, and the balance at the end rather than the repayment amount.
And this time, if we run this using the same thing, we'll find out that he has
to repay, basically, 2,700 every quarter in order to make this loan work.
So this is an example where we're using the same model
with different data to actually answer a different question because
the different data is specifying different decision variable entry values.
So here's a more interesting question.
If Liu Bei wants to borrow $10000, owe nothing at the end, and
he can repay $3000 quarterly, what is the interest rate he could afford to pay?
So here we're given a principal of 10000, a balance of 0.0 and
a repayment amount of 3000.
Again, we can run it just the same as we did before, and
we'll find out that he can repay up to an interest rate of 7.71%.
So, interestingly, this last question is quite a hard question to answer,
it's actually solving non-linear constraints.
And if we ask this to be solved via the G12 MIP solver, for example, which is
a mixed interest programming solver, we're going to get this kind of error,
that built-in operation float times is not supported by the MIP solver backend.
So to explain what's happening here is this problem is, essentially,
non-linear for a loan3.dzn.
Basically, we have to work out the interest rate,
we're going to solve a polynomial equation.
And the MIP solver just cannot express that multiplication of
continuous variables.
So it's just cannot solve this problem.
The default solver that we use, Gecode, uses interval arithmetic, and it can
solve this problem, so that's why it could solve loan3.dzn without any problem.
So not all solvers are equal, and you may see this that some models can run for
some solver and others won't.
Because of features of the solver, you'll certainly see differences in how quickly
various solvers can solve which model,
and which solvers can solve which models in practice.
So usually, though, data files define values for parameters,
that's the main use of parameters.
We also note they could be enumerated types as well.
For example, for
our color file we could have changed the enumerator type to just say color, so
just declaring that there is a color in the enumerator type in our MiniZinc model.
And then we could have had the color in the enumerator type declared in
a data file.
So, we'd get a five color data in the data file, and
we could have five-colored our map, instead.
So MiniZinc data files must end in .dzn.
And usually the data files only contain assignment items and usually only for
parameters.
But it's also possible for decision variables, as we saw in the lone examples.
And any parameters not assigned in the model must be assigned in the data file.
So there must be some way of getting that value into the model,
otherwise we won't be able to run it.
You can add multiple data files where you assign different values and
different parameters.
So on the command line it's straightforward by using
multiple data files, one after the other.
Much more difficult in the IDE, and
we won't go into how to do that because usually we won't have to bother.
So, in summary, a model, remember,
is a formal description of actually a class of optimization problems.
And an instance is one particular optimization problem.
And the way you get an instance from a model is you add the data.
So, typically, we're going to build now models which answer many,
many different optimization problems, and then we'll give them different data in
order to solve different instances of the problem.
So in MiniZinc, we do this by using data files, which is .dzn files.