Increment variable array elements in Minizinc - constraint-programming

I would like to perform a simple increment operation on specific array elements:
Minimal Not-Working Example:
array[1..2] of var 0..1: a = [0, 0];
constraint forall (i in 1..2) (
a[i] = a[i] + 1
);
output ["\(a)"];
solve satisfy;
This produces the minizinc output
WARNING: model inconsistency detected
stack.mzn:3:
in call 'forall'
in array comprehension expression
with i = 1
stack.mzn:4:
in binary '=' operator expression
=====UNSATISFIABLE=====
% stack.fzn:1: warning: model inconsistency detected before search.
Why is this an inconsistency in the model -- why can't I reference the old value of the current array element? Is there some other way to increase the current array element by 1?
I'm new to constraint solving, so I hope this is not a terribly stupid question.

It is important to know that MiniZinc is a declarative language. In a constraint you're not stating an instruction, but you're stating the "truth" as know to the solvers.
That means that an instruction like a = a + 1 will not work because you are stating that we're looking for a value for a that is its own value + 1. Since no such value exist we call the model inconsistent since no solutions can be found.
The idea of the constraint items is to express relations between different variables and parameters. You could for example write: constraint forall(i in N) (a[i] = a[i-1] + 1). This will mean we will look for a value a[i] which is 1 more than a[i-1] for all i in N. (Note that we should probably add an if-statement to make sure i-1 stays within the given bounds)
As a general rule: if there is a literal on one side of an equals signs, using that literal on the other side will create an inconsistent model.
If you still wanted to create a MiniZinc model that increases the values of a given array by one, you could use the following model:
set of int: N = 1..2
array[N] of int: a = [0,1];
array[N] of var int: b;
constraint forall(i in N) (
b[i] = a[i] + 1
);
Since the variables a are now expressed in terms of b, this doesn't violate our rule.

Related

How can I generate a graph by constraining it to be subisomorphic to a given graph, while not subisomorphic to another?

TL;DR: How can I generate a graph while constraining it to be subisomorph to every graph in a positive list while being non-subisomorph to every graph in a negative list?
I have a list of directed heterogeneous attributed graphs labeled as positive or negative. I would like to find the smallest list of patterns(graphs with special values) such that:
Every input graph has a pattern that matches(= 'P is subisomorphic to G, and the mapped nodes have the same attribute values')
A positive pattern can only match a positive graph
A positive pattern does not match any negative graph
A negative pattern can only match a negative graph
A negative pattern does not match any negative graph
Exemple:
Input g1(+),g2(-),g3(+),g4(+),g5(-),g6(+)
Acceptable solution: p1(+),p2(+),p3(-) where p1(+) matches g1(+) and g4(+); p2(+) matches g3(+) and g6(+); and p3(-) matches g2(-) and g5(-)
Non acceptable solution: p1(+),p2(-) where p1(+) matches g1(+),g2(-),g3(+); p2(-) matches g4(+),g5(-),g6(+)
Currently, I'm able to generate graphs matching every graph in a list, but I can't manage to enforce the constraint 'A positive pattern does not match any negative graph'. I made a predicate 'matches', which takes as input a pattern and a graph, and uses a local array of variables 'mapping' to try and map nodes together. But when I try to use that predicate in a negative context, the following error is returned: MiniZinc: flattening error: free variable in non-positive context.
How can I bypass that limitation? I tried to code the opposite predicate 'not_matches' but I've not yet found how to specify 'for all node mapping, the isomorphism is invalid'. I also can't define the mapping outside the predicate, because a pattern can match a graph more than once and i need to be able to get all mappings.
Here is a reproductible exemple:
include "globals.mzn";
predicate p(array [1..5] of var 0..10:arr1, array [1..5] of 1..10:arr2)=
let{array [1..5] of var 1..5: mapping; constraint all_different(mapping)} in (forall(i in 1..5)(arr1[i]=0\/arr1[i]=arr2[mapping[i]]));
array [1..5] of var 0..10:arr;
constraint p(arr,[1,2,3,4,5]);
constraint p(arr,[1,2,3,4,6]);
constraint not p(arr,[1,2,3,5,6]);
solve satisfy;
For that exemple, the decision variable is an array and the predicate p is true if a mapping exists such that the values of the array are mapped together. One or more elements of the array can also be 0, used here as a wildcard.
[1,2,3,4,0] is an acceptable solution
[0,0,0,0,0] is not acceptable, it matches anything. And the solution should not match [1,2,3,5,6]
[1,2,3,4,7] is not acceptable, it doesn't match anything(as there is no 7 in the parameter arrays)
Thanks by advance! =)
Edit: Added non-acceptable solutions
It is probably good to note that MiniZinc's limitation is not coincidental. When the creation of a free variable is negated, rather then finding a valid assignment for the variable, instead the model would have to prove that no such valid assignment exists. This is a much harder problem that would bring MiniZinc into the field of quantified constraint programming. The only general solution (to still receive the same flattened constraint model) would be to iterate over all possible values for each variable and enforce the negated constraints. Since the number of possibilities quickly explodes and the chance of getting a good model is small, MiniZinc does not do this automatically and throws this error instead.
This technique would work in your case as well. In the not_matches version of your predicate, you can iterate over all possible permutations (the possible mappings) and enforce that they not correct (partial) mappings. This would be a correct way to enforce the constraint, but would quickly explode. I believe, however, that there is a different way to enforce this constraint that will work better.
My idea stems from the fact that, although the most natural way to describe a permutation from one array to the another is to actually create the assignment from the first to the second, when dealing with discrete variables, you can instead enforce that each has the exact same number of each possible value. As such a predicate that enforces X is a permutation of Y might be written as:
predicate is_perm(array[int] of var $$E: X, array[int] of var $$E: Y) =
let {
array[int] of int: vals = [i | i in (dom_array(X) union dom_array(Y))]
} in global_cardinality(X, vals) = global_cardinality(Y, vals);
Notably this predicate can be negated because it doesn't contain any free variables. All new variables (the resulting values of global_cardinality) are functionally defined. When negated, only the relation = has to be changed to !=.
In your model, we are not just considering full permutations, but rather partial permutations, and we use a dummy value otherwise. As such, the p predicate might also be written:
predicate p(array [int] of var 0..10: X, array [int] of var 1..10: Y) =
let {
set of int: vals = lb_array(Y)..ub_array(Y); % must not include dummy value
array[vals] of var int: countY = global_cardinality(Y, [i | i in vals]);
array[vals] of var int: countX = global_cardinality(X, [i | i in vals]);
} in forall(i in vals) (countX[i] <= countY[i]);
Again this predicate does not contain any free variables, and can be negated. In this case, the forall can be changed into a exist with a negated body.
There are a few things that we can still do to optimise p for this use case. First, it seems that global_cardinality is only defined for variables, but since Y is guaranteed par, we can rewrite it and have the correct counts during MiniZinc's compilation. Second, it can be seen that lb_array(Y)..ub_array(Y) gives the tighest possible set. In your example, this means that only slightly different versions of the global cardinality function are evaluated, that could have been
predicate p(array [1..5] of var 0..10: X, array [1..5] of 1..10: Y) =
let {
% CHANGE: Use declared values of Y to ensure CSE will reuse `global_cardinality` result values.
set of int: vals = 1..10; % do not include dummy value
% CHANGE: parameter evaluation of global_cardinality
array[vals] of int: countY = [count(j in index_set(Y)) (i = Y[j]) | i in vals];
array[vals] of var int: countX = global_cardinality(X, [i | i in 1..10]);
} in forall(i in vals) (countX[i] <= countY[i]);
Regarding the example. One approach might be to rewrite the not p(...) constraint to a specific not_p(...) constraint. But I'm how sure how that be formulated.
Here's an example but it's probably not correct:
predicate not_p(array [1..5] of var 0..10:arr1, array [1..5] of 1..10:arr2)=
let{
array [1..5] of var 1..5: mapping;
constraint all_different(mapping)
} in
exists(i in 1..5)(
arr1[i] != 0
/\
arr1[i] != arr2[mapping[i]]
);
This give 500 solutions such as
arr = [1, 0, 0, 0, 0];
----------
arr = [2, 0, 0, 0, 0];
----------
arr = [3, 0, 0, 0, 0];
...
----------
arr = [2, 0, 0, 3, 4];
----------
arr = [2, 0, 1, 3, 4];
----------
arr = [2, 1, 0, 3, 4];
Update
I added not before the exists loop.

HOW TO SUM UP IN STRING SET IN PYOMO

I have a constraint that I called Prod_H2 and it depends on (i,s). This equation have sum of some variables, FIJ (i,j) and FIK (i,k).
***i=['U4241', 'U241', 'U241A']
HN_model.i=Set(initialize=[(len(i))])
j=['U4283', 'U283', 'U283A', 'U3283', 'U2280', 'U1280']
HN_model.j=Set(initialize=[(len(j))])
k=['PSA4241', 'PSA241', 'PSA241A', 'PSA3241']
HN_model.k=Set(initialize=[(len(k))])
s=[1]
HN_model.s=Set(initialize=range(len(s)))
HN_model.FIJ=Var(HN_model.i, HN_model.j, HN_model.s,domain=PositiveReals)
HN_model.FIW=Var(HN_model.i, HN_model.s, within=PositiveReals)
HN_model.FIK=Var(HN_model.i, HN_model.k, HN_model.s,within=PositiveReals)***
HN_model.Prod_H2=Constraint(HN_model.i, HN_model.s, expr=sum(HN_model.FIJ[i,j] for j in [len(HN_model.j)]) + sum(HN_model.FIK for k in [len(HN_model.k)]) + HN_model.FIW)
I think the error is because the sum is in j, to keep the equation in function i.
DeveloperError: Internal Pyomo implementation error: 'Unknown problem encountered when trying to retrieve index for component FIJ' Please report this to the Pyomo Developers.
As #AirSquid said in its comment, you are not constructing correctly the model. First at all, Pyomo allows index to be any datatype, int, float, str or even datetime. So, there's no problem to use the actual values of your list i, j, k and s. You do not need to use len to construct the set or the constraint index
Now, you got some mistakes in the modelling, besides the previous commented stuff. I'll try to show you:
In the constraint modeling, you do not have any equality or inequality sign. In pyomo you need whether to use an equality/inequality sign (==, <= or >=) or use other class to model such Equality or Inequality (pyomo.environ.Expression.inequality(2, model.x) is equivalent to 2 <= model.x)
When you're declaring the variables, you're modeling the variables with some index and calling them in the constraint with less index. For example:
HN_model.FIJ is modeled with index i,j,s but you're using i,j index in the constraint
Finally, I encourage you, as AirSquid told you, to check some examples about how to correctly modeling optimization problems with Pyomo. If you need any help, StackOverflow is always there.
I leave you an example of how to model the problem you just posted
from pyomo.environ import *
#set the model
HN_model = ConcreteModel()
i=['U4241', 'U241', 'U241A']
HN_model.i=Set(initialize=i)
j=['U4283', 'U283', 'U283A', 'U3283', 'U2280', 'U1280']
HN_model.j=Set(initialize=j)
k=['PSA4241', 'PSA241', 'PSA241A', 'PSA3241']
HN_model.k=Set(initialize=k)
s=[1]
HN_model.s=Set(initialize=s)
HN_model.FIJ=Var(HN_model.i, HN_model.j, HN_model.s,domain=PositiveReals)
HN_model.FIW=Var(HN_model.i, HN_model.s, within=PositiveReals)
HN_model.FIK=Var(HN_model.i, HN_model.k, HN_model.s,within=PositiveReals)
def constraint(HN_model, i, s):
'''Constraint modeling. I assume you are using the >='''
return sum(HN_model.FIJ[i,j,s] for j in HN_model.j) + sum(HN_model.FIK[i,k,s] for k in HN_model.k) + HN_model.FIW[i,s] >= 0
HN_model.Prod_H2=Constraint(HN_model.i, HN_model.s, rule=constraint)

Why += is considered as an assignment operator while >= is not?

I was thinking why the '=' in '+=' is considered as assignment while '=' in '>=' is not considered as such. There is no importance behind this question but some random thought of a beginner. For example purpose, you can consider that
a = np.array([1,2,3,4,5])
a += 2 # array updated and assigned to a
a>=2 # becomes a boolean indexing filter
a += 2 changes the value of a. It reassigns it's value to be two more than it was before. By the way, += as a whole is the assignment operator, not just the =.
a>=2 does not change the value of a. Yes, it becomes true or false. But 'true' or 'false' is all it is. It does not get assigned to anything. The value of a is as it was before.
You can do b = a>=2. But in that case, = is the assignment operator because it is what assigns the value to b.

How To Understand THE Following Code Snippet?

i came up with understanding confusion , what will be the right explanation for this code?
a = [(0,1),(1,2),(2,3)]
result = sum(n for _,n in a)
print(result)
I guess that your confusion is coming from the , and the fact that sum also accepts a second argument.
In this case, only one argument is passed to sum because that line is evaluated as
result = sum(n for (_, n) in a)
This line simply sums all the second elements in the list of tuples, and it is equivalent to the following:
list_of_tuples = [(0,1),(1,2),(2,3)]
total = 0
for (first_element, second_element) in list_of_tuples:
total += second_element
print(total)
Technically _ is a normal, valid identifier name, but the convention is to use it for values that are disregarded in the next part of the code.
I think another way of thinking of it is:
result=0
for _,n in a:
result += n
You can substitute "_,n" for any other two variables like "x,y" for example.

What is call-by-need?

I want to know what is call-by-need.
Though I searched in wikipedia and found it here: http://en.wikipedia.org/wiki/Evaluation_strategy,
but could not understand properly.
If anyone can explain with an example and point out the difference with call-by-value, it would be a great help.
Suppose we have the function
square(x) = x * x
and we want to evaluate square(1+2).
In call-by-value, we do
square(1+2)
square(3)
3*3
9
In call-by-name, we do
square(1+2)
(1+2)*(1+2)
3*(1+2)
3*3
9
Notice that since we use the argument twice, we evaluate it twice. That would be wasteful if the argument evaluation took a long time. That's the issue that call-by-need fixes.
In call-by-need, we do something like the following:
square(1+2)
let x = 1+2 in x*x
let x = 3 in x*x
3*3
9
In step 2, instead of copying the argument (like in call-by-name), we give it a name. Then in step 3, when we notice that we need the value of x, we evaluate the expression for x. Only then do we substitute.
BTW, if the argument expression produced something more complicated, like a closure, there might be more shuffling of lets around to eliminate the possibility of copying. The formal rules are somewhat complicated to write down.
Notice that we "need" values for the arguments to primitive operations like + and *, but for other functions we take the "name, wait, and see" approach. We would say that the primitive arithmetic operations are "strict". It depends on the language, but usually most primitive operations are strict.
Notice also that "evaluation" still means to reduce to a value. A function call always returns a value, not an expression. (One of the other answers got this wrong.) OTOH, lazy languages usually have lazy data constructors, which can have components that are evaluated on-need, ie, when extracted. That's how you can have an "infinite" list---the value you return is a lazy data structure. But call-by-need vs call-by-value is a separate issue from lazy vs strict data structures. Scheme has lazy data constructors (streams), although since Scheme is call-by-value, the constructors are syntactic forms, not ordinary functions. And Haskell is call-by-name, but it has ways of defining strict data types.
If it helps to think about implementations, then one implementation of call-by-name is to wrap every argument in a thunk; when the argument is needed, you call the thunk and use the value. One implementation of call-by-need is similar, but the thunk is memoizing; it only runs the computation once, then it saves it and just returns the saved answer after that.
Imagine a function:
fun add(a, b) {
return a + b
}
And then we call it:
add(3 * 2, 4 / 2)
In a call-by-name language this will be evaluated so:
a = 3 * 2 = 6
b = 4 / 2 = 2
return a + b = 6 + 2 = 8
The function will return the value 8.
In a call-by-need (also called a lazy language) this is evaluated like so:
a = 3 * 2
b = 4 / 2
return a + b = 3 * 2 + 4 / 2
The function will return the expression 3 * 2 + 4 / 2. So far almost no computational resources have been spent. The whole expression will be computed only if its value is needed - say we wanted to print the result.
Why is this useful? Two reasons. First if you accidentally include dead code it doesn't weigh your program down and thus can be a lot more efficient. Second it allows to do very cool things like efficiently calculating with infinite lists:
fun takeFirstThree(list) {
return [list[0], list[1], list[2]]
}
takeFirstThree([0 ... infinity])
A call-by-name language would hang there trying to create a list from 0 to infinity. A lazy language will simply return [0,1,2].
A simple, yet illustrative example:
function choose(cond, arg1, arg2) {
if (cond)
do_something(arg1);
else
do_something(arg2);
}
choose(true, 7*0, 7/0);
Now lets say we're using the eager evaluation strategy, then it would calculate both 7*0 and 7/0 eagerly. If it is a lazy evaluated strategy (call-by-need), then it would just send the expressions 7*0 and 7/0 through to the function without evaluating them.
The difference? you would expect to execute do_something(0) because the first argument gets used, although it actually depends on the evaluation strategy:
If the language evaluates eagerly, then it will, as stated, evaluate 7*0 and 7/0 first, and what's 7/0? Divide-by-zero error.
But if the evaluation strategy is lazy, it will see that it doesn't need to calculate the division, it will call do_something(0) as we were expecting, with no errors.
In this example, the lazy evaluation strategy can save the execution from producing errors. In a similar manner, it can save the execution from performing unnecessary evaluation that it won't use (the same way it didn't use 7/0 here).
Here's a concrete example for a bunch of different evaluation strategies written in C. I'll specifically go over the difference between call-by-name, call-by-value, and call-by-need, which is kind of a combination of the previous two, as suggested by Ryan's answer.
#include<stdio.h>
int x = 1;
int y[3]= {1, 2, 3};
int i = 0;
int k = 0;
int j = 0;
int foo(int a, int b, int c) {
i = i + 1;
// 2 for call-by-name
// 1 for call-by-value, call-by-value-result, and call-by-reference
// unsure what call-by-need will do here; will likely be 2, but could have evaluated earlier than needed
printf("a is %i\n", a);
b = 2;
// 1 for call-by-value and call-by-value-result
// 2 for call-by-reference, call-by-need, and call-by-name
printf("x is %i\n", x);
// this triggers multiple increments of k for call-by-name
j = c + c;
// we don't actually care what j is, we just don't want it to be optimized out by the compiler
printf("j is %i\n", j);
// 2 for call-by-name
// 1 for call-by-need, call-by-value, call-by-value-result, and call-by-reference
printf("k is %i\n", k);
}
int main() {
int ans = foo(y[i], x, k++);
// 2 for call-by-value-result, call-by-name, call-by-reference, and call-by-need
// 1 for call-by-value
printf("x is %i\n", x);
return 0;
}
The part we're most interested in is the fact that foo is called with k++ as the actual parameter for the formal parameter c.
Note that how the ++ postfix operator works is that k++ returns k at first, and then increments k by 1. That is, the result of k++ is just k. (But, then after that result is returned, k will be incremented by 1.)
We can ignore all of the code inside foo up until the line j = c + c (the second section).
Here's what happens for this line under call-by-value:
When the function is first called, before it encounters the line j = c + c, because we're doing call-by-value, c will have the value of evaluating k++. Since evaluating k++ returns k, and k is 0 (from the top of the program), c will be 0. However, we did evaluate k++ once, which will set k to 1.
The line becomes j = 0 + 0, which behaves exactly like how you'd expect, by setting j to 0 and leaving c at 0.
Then, when we run printf("k is %i\n", k); we get that k is 1, because we evaluated k++ once.
Here's what happens for the line under call-by-name:
Since the line contains c and we're using call-by-name, we replace the text c with the text of the actual argument, k++. Thus, the line becomes j = (k++) + (k++).
We then run j = (k++) + (k++). One of the (k++)s will be evaluated first, returning 0 and setting k to 1. Then, the second (k++) will be evaluated, returning 1 (because k was set to 1 by the first evaluation of k++), and setting k to 2. Thus, we end up with j = 0 + 1 and k set to 2.
Then, when we run printf("k is %i\n", k);, we get that k is 2 because we evaluated k++ twice.
Finally, here's what happens for the line under call-by-need:
When we encounter j = c + c; we recognize that this is the first time the parameter c is evaluated. Thus we need to evaluate its actual argument (once) and store that value to be the evaluation of c. Thus, we evaluate the actual argument k++, which will return k, which is 0, and therefore the evaluation of c will be 0. Then, since we evaluated k++, k will be set to 1. We then use this stored evaluation as the evaluation for the second c. That is, unlike call-by-name, we do not re-evaluate k++. Instead, we reuse the previously evaluated initial value for c, which is 0. Thus, we get j = 0 + 0; just as if c was pass-by-value. And, since we only evaluated k++ once, k is 1.
As explained in the previous step, j = c + c is j = 0 + 0 under call-by-need, and it runs exactly as you'd expect.
When we run printf("k is %i\n", k);, we get that k is 1 because we only evaluated k++ once.
Hopefully this helps to differentiate how call-by-value, call-by-name, and call-by-need work. If it would be helpful to differentiate call-by-value and call-by-need more clearly, let me know in a comment and I'll explain the code earlier on in foo and why it works the way it does.
I think this line from Wikipedia sums things up nicely:
Call by need is a memoized variant of call by name, where, if the function argument is evaluated, that value is stored for subsequent use. If the argument is pure (i.e., free of side effects), this produces the same results as call by name, saving the cost of recomputing the argument.

Resources