Now, we need to make sure that all the building are covered.
So here's an example of where we can use a predicate, and
we're using some local variables to define that predicate.
So, do we cover a building on the position x, y?
This is what this predicate is meant to ensure.
So if we do cover a building on x, y,
there must be a point within a Manhattan distance of mDist from that building.
So we're introducing a local variable, i,
which is going to guess basically which exit point we're using.
And then we're going to calculate the distance from x, y to this exit point.
So the distance from x, y is just the position x minus the row of i,
the absolute value,.
Plus the absolute value of the y-th coordinate,
the column coordinate for the position we're looking at covering,
minus the column where we find the particular point we've picked.
So we're going to calculate that distance and then, say,
well that distance must be less than the maximum distance that we're
allowed in that model, in our example, which is 3.
So this is a predicate, which is going to test where this position x, y is covered.
And notice we're doing something quite clever here.
We're actually allowing it to pick which point is covering it.
So basically,
there's a pseudo decision here about which point is going to cover it.
Now, how do we apply the constraint?
So let's build basically the even numbers, right,
the huts occur on the even numbers, which is from i is 1 to size div 2 i times 2.
Let's build that array and then we'll say, forall i, j in huts.
So basically, picking all row columns in these even numbers,
we're going to check that it's covered.
All right, so we can see that by building this cover constraint,
we've made it clear what we're trying to do.
And then we're using this cover constraint on each of the hut positions,
improving readability and modularity.
Now finally, the objective we're trying to minimize the total cost of building, so
that's basically looking up the row and column.
Looking at the cost value for digging to that point and minimizing the total cost.
And if we can run their model, we'll find that we can actually cover the bandits
with only three points, if we pick these three points, and our cost is 18.
So, just to show you another use of let-in,
if we go back to the patrol problem we saw a number of lectures ago.
Then we needed that in every day,
the number of soldiers on evening shift was greater than equal some lower bound.
And every day the number of soldiers on the evening shift was less than equals to
some upper bound.
Well, another way we could do this rather than introducing direct common
subexpression based for this, we could just do it the same by using a local
variable to build up that expression that we're going to use twice.
So here, for each day, we're going to build a new local variable,
which is how many are on evening shift which is just this value, right?
The sum of the soldiers are on evening shift on that particular day.
And then we're going to add these constraints
that l is less or equal to u and on is less or equal to u.
Which is going to enforce these two constraints, so we're building a common
sub-expression but we're just using a local variable to do that.
It's often easier than building an array of intermediates,
which is what we did last time.
We were basically adding some global decisions into our model and
then use them in multiple places.
If we're only going to use them in one local place, we just add a local name for
this particular common subexpression and then reuse that local name.
So, let's look at another use of let-in.
Suppose our solver does not support division,
then we can actually define division using multiplication.
because really from a relation perspective,
they're really the same thing, like plus and minus are really the same relation.