Increasing optimization level results in errors - minizinc

Here is a simple model that requires all elements of one array to be equal to elements of the other one:
int: n = 3;
set of int: N = 1..n;
array[N, N] of var bool: P1 = [|true, false, false|
false, true, false|
false, false, false|];
array[N, N] of var bool: P2;
% constraint forall (x, y in N) (if P1[x,y] then P2[x,y] else true endif);
% constraint forall (x, y in N) (P1[x,y] == P2[x,y]);
constraint forall (x, y in N) (P1[x,y] <-> P2[x,y]);
solve satisfy;
When I run it with optimization levels -O0 or -O1, everything works fine, but when I switch to higher optimization levels, I get several errors of this kind:
Error: undefined identifier for type bool X_INTRODUCED_0_ in line no. 10
As you can see, I have tried many approaches. What could possibly cause a problem in such a simple program?
This happens even in the simplest case, with only one decision variable inside the array:
array[1..1] of bool: n = [true];
array[1..1] of var bool: k;
constraint n[1] == k[1];
solve satisfy;

This actually seems to be the same issue as this one. It might not look the same, but because it probably is as it seems that the optimisation phase is removing an identifier that is not yet marked to be part of the output. The issue should be solved in the next MiniZinc release.

Related

Referring to decision variable arrays in MiniZinc functions

I'd like to find the permutation steps that lead from the initial state to a required state. The decision variable array Steps is intended to record the permutation steps, encoded as integers. My approach is to constrain the values of Steps so that "replaying" the permutations identified by them on the initial state yields the
arranged state, represented by State. In order to select from various permutations, I'd have to refer to the items of Steps in a conditional expression, which results in a type error.
int : nrItems;
int : nrMaxSteps;
nrItems = 3;
nrMaxSteps = 10;
array [1..nrItems] of int : State;
State = [2,1,3];
array [1..nrMaxSteps] of var 0..4 : Steps;
% 0 - empty step for solutions shorter than nrMaxSteps
%**********************************************
% permute the initial state
function array [1..nrItems] of int: permute() =
% apply permutations on the initial state
% depending on the values of Steps
if(Steps[1] == 1) ... select permutation1
%**********************************************
predicate arranged() =
let { array [1..nrItems] of int : permuted = permute(); }
in permuted[1] == State[1] /\ permuted[2] == State[2] /\ permuted[3] == State[3];
constraint
arranged();
solve satisfy;
What would be the right approach here?

Support for pow() with decision variables in MiniZinc

I am trying to build a model with a decision variable that takes the range 0..10 with the constraint
that it must be divisible by 4.The output must be the one that minimizes the value (x-7)^2. Investigating I see that Gecode already supports it.
I have tried to build the model as follows but I get an error using the built-in pow()
% Decision variable
var 0..10: x;
% Constraints
constraint (x mod 4) == 0;
% Call to the resolver
int: obj = pow(x-7, 2);
solve minimize obj;
% Solution
output["x = ", show(x), "\nobj = ", show(obj)];
I get the following error:
MiniZinc: type error: initialisation value for `obj' has invalid type-inst: expected `int', actual `var int'
I think it occurs because is considering the variable as a decision variable instead of just an integer parameter.
#hankank's solution is correct. Using var int: obj = pow(x-7, 2);
Variables (e.g., var int) in MiniZinc are decision variables and other names (which you might call variables in Python) are referred to as parameters (e.g., par int or int). These are two distinct types for a good reason: any calculation with only parameter is guaranteed to be able to be executed during MiniZinc compilation, while any calculation that uses a variable will generally have to be decided by a solver.
Note, that using pow actually might also bring problems for linear solver (i.e., MIP solvers). In this case the calculation can still be made linear because the transformation is using a constant, but the expression pow(x,y) where both arguments are variables could not be decided by a linear solver.
To move the pow() call from solution time to compilation time, you could use a pre-calculated array:
% Decision variable
var 0..10: x;
set of int: DomainX = 0..10;
array[DomainX] of int: xa = array1d(DomainX, [pow(i-7, 2) | i in DomainX]);
% Constraints
constraint (x mod 4) == 0;
% Call to the resolver
var int: obj = xa[x];
solve minimize obj;
% Solution
output["x = ", show(x), "\nobj = ", show(obj)];
As commented by hakank, variable obj must be of type var int, as it depends on a decision variable.

Macro to generate element-wise methods

I see myself writing this pattern again and again, where a function can take an entity E or a iterator over Es and apply elementwise. eg:- an index or a vector. A column or a matrix. I was wondering if there is a macro so that I need not define multiple methods. I am looking for a julian way of doing this.
In the simplified version of my use case below, compare getrow which is naturally overloaded to work on ints or slices with innerprod that needs to be redefined for Vectors and Matrixes.
type Mat{T<:Number}
data::Matrix{T}
end
getrow{T}(m::Mat{T}, i=size(m)[1]) = m.data[i, :]
innerprod{T}(m::Mat{T}, v::Array{T}) = m.data*v
innerprod{T}(m::Mat{T}, vv::Matrix{T}) = mapslices(v->innerprod(m, v), vv, 1)
m = Mat(rand(1:9, 2, 3))
v = rand(1:9, 3, 4)
f = innerprod(m, v[:,1])
g = innerprod(m, v)

MuPAD evaluation of local variables, Sum of row of array

I have discovered a strange behavior in MuPAD version 5.7.0 (MATLAB R2011b), and I would like to know whether this is a bug, and if not so, what I am doing wrong. Ideally, I would also like to know why MuPAD does what it does.
Consider the array C of size 3x3, the elements of which have some example values. I would like to regard this array as an array of arrays and thus use cascaded indexing.
The problem apparently arises when both indices are local variables of different nested scopes, namely when the first index's scope is wider than the second index's one. There is no problem if the first index is a constant.
When I enter:
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
sum((C[3])[t], t = 1..3);
S := j -> sum((C[j])[t], t = 1..3);
S(3);
I get the following result:
I would expect lines 3 and 5 in the code (2 and 4 in the output) to yield the same result: g+h+i. Instead, line 5 produces a+e+i, which seems to be the diagonal of C.
When I do the same with product instead of sum, the result is even stranger, but might reveal more about the "error's" source, particularly DOM_VAR(0,2):
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
product((C[3])[t], t = 1..3);
eval(product((C[3])[t], t = 1..3));
S := j -> product((C[j])[t], t = 1..3);
S(3);
eval(S(3));
I get:
I might be on the wrong track here, but I suspect that a closure is created that tried to save the surrounding scope's local variables, which are undetermined at the time of the closure's creation. Also, substitutions seem to stop at some point, which is overridden by eval().
Practical Problem
The practical problem I am trying to solve is the following:
reset();
aVec := Symbol::accentUnderBar(Symbol::alpha)
Problem: Calculate multinomials of the form
hold(sum(x(i), i=i_0..i_k)^n)
On Wikipedia, the following form is defined:
sumf := freeze(sum):
hold(sum(x[i], i=1..m)^n)=sumf(binomial(n,aVec)*product(x[t]^aVec[t], t = 1..m), abs(aVec)=n);
In order to implement this, we need to define the set of vectors alpha, the sum of which equals m.
These correspond to the set of possible compositions of n with length m and possible zero elements:
C := (n,m) -> combinat::compositions(n, MinPart = 0, Length = m)
For example, the sum
n := 3:
m := 3:
sumf(x[i], i=1..m)^n = sum(x[i], i=1..m)^n;
would call for these combinations of powers, each of which is one vector alpha:
A := C(n,m)
Additionally, we need the multinomial coefficients.
Each such coefficient depends on vector alpha and the power n:
multinomial := (n, aVec) -> fact(n) / product(fact(aVec[k]), k = 1..nops(aVec))
For example, the number of times that the second composition appears, is:
multinomial(n, A[2])
Summation over all compositions yields:
sum(multinomial(n,A[i])*product(x[t]^A[i][t], t = 1..m), i = 1..nops(A))
The powers are correct, but the coefficients are not. This seems related to the boiled-down abstract problem stated first in this question.
The expression [[a,b,c],[d,e,f],[g,h,i]] is not an array in MuPAD. It is a "list of lists." I'm guessing that's not what you're after. Lists are commonly used to initialize arrays and matrices and other objects (more here). For these examples, either arrays or matrices will work, but note that these two data types have different advantages.
Using array:
reset();
C := array([[a,b,c],[d,e,f],[g,h,i]]);
sum(C[3, t],t=1..3);
S := j -> sum(C[j, t], t = 1..3);
S(3);
which returns
Note the different way row/column indexing is represented relative to that in your question. Similarly, modifying your other example
reset();
C := matrix([[a,b,c],[d,e,f],[g,h,i]]);
product(C[3, t], t = 1..3);
S := j -> product(C[j, t], t = 1..3);
S(3);
results in
If you do happen to want to use lists for this, you can do so like this
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
_plus(op(C[3]));
S := j -> _plus(op(C[j]));
S(3);
which returns
The _plus is the functional form of + and op extracts each element from the list. There are other ways to do this, but this is one of the simplest.
I am posting this answer only to provide a working example of the practical problem from the question. horchler provided the decisive solution by proposing to use a matrix instead of a list of lists.
Basically, this is a modified transscript of the practical problem.
Practical Solution
The practical problem I am trying to solve is the following:
reset();
aVec := Symbol::accentUnderBar(Symbol::alpha)
Problem: Calculate multinomials of the form
hold(sum(x(i), i=i_0..i_k)^n)
On Wikipedia, the following form is defined:
sumf := freeze(sum):
hold(sum(x[i], i=1..m)^n)=sumf(binomial(n,aVec)*product(x[t]^aVec[t], t = 1..m), abs(aVec)=n);
In order to implement this, we need to define the set of vectors alpha, the sum of which equals m.
These correspond to the set of possible compositions of n with length m and possible zero elements:
C := (n,m) -> combinat::compositions(n, MinPart = 0, Length = m)
For example, the sum
n := 3:
m := 3:
sumf(x[i], i=1..m)^n = sum(x[i], i=1..m)^n;
would call for these combinations of powers, each of which is one vector alpha:
A := matrix(nops(C(n,m)),m,C(n,m));
Additionally, we need the multinomial coefficients.
Each such coefficient depends on vector alpha and the power n:
multinomial := (n, aVec) -> fact(n) / product(fact(aVec[k]), k = 1..nops(aVec))
For example, the number of times that the second composition appears, is:
multinomial(n,A[2,1..m])
Summation over all compositions yields:
sum(multinomial(n,A[i,1..m])*product(x[t]^A[i,t], t = 1..m), i = 1..nops(C(n,m)));
Finally, prove that the result transforms back:
simplify(%)

Symbolic integration vs numeric integration in MATLAB

I have an expression with three variables x,y and v. I want to first integrate over v, and so I use int function in MATLAB.
The command that I use is the following:
g =int((1-fxyz)*pv, v, y,+inf)%
PS I haven't given you what the function fxyv is but it is very complicated and so int is taking so long and I am afraid after waiting it might not solve it.
I know one option for me is to integrate numerically using for example integrate, however I want to note that the second part of this problem requires me to integrate exp[g(x,y)] over x and y from 0 to infinity and from x to infinity respectively. So I can't take numerical values of x and y when I want to integrate over v I think or maybe not ?
Thanks
Since the question does not contain sufficient detail to attempt analytic integration, this answer focuses on numeric integration.
It is possible to solve these equations numerically. However, because of complex dependencies between the three integrals, it is not possible to simply use integral3. Instead, one has to define functions that compute parts of the expressions using a simple integral, and are themselves fed into other calls of integral. Whether this approach leads to useful results in terms of computation time and precision cannot be answered generally, but depends on the concrete choice of the functions f and p. Fiddling around with precision parameters to the different calls of integral may be necessary.
I assume that the functions f(x, y, v) and p(v) are defined in the form of Matlab functions:
function val = f(x, y, v)
val = ...
end
function val = p(v)
val = ...
end
Because of the way they are used later, they have to accept multiple values for v in parallel (as an array) and return as many function values (again as an array, of the same size). x and y can be assumed to always be scalars. A simple example implementation would be val = ones(size(v)) in both cases.
First, let's define a Matlab function g that implements the first equation:
function val = g(x, y)
val = integral(#gIntegrand, y, inf);
function val = gIntegrand(v)
% output must be of the same dimensions as parameter v
val = (1 - f(x, y, v)) .* p(v);
end
end
The nested function gIntegrand defines the object of integration, the outer performs the numeric integration that gives the value of g(x, y). Integration is over v, parameters x and y are shared between the outer and the nested function. gIntegrand is written in such a way that it deals with multiple values of v in the form of arrays, provided f and p do so already.
Next, we define the integrand of the outer integral in the second equation. To do so, we need to compute the inner integral, and therefore also have a function for the integrand of the inner integral:
function val = TIntegrandOuter(x)
val = nan(size(x));
for i = 1 : numel(x)
val(i) = integral(#TIntegrandInner, x(i), inf);
end
function val = TIntegrandInner(y)
val = nan(size(y));
for j = 1 : numel(y)
val(j) = exp(g(x(i), y(j)));
end
end
end
Because both function are meant to be fed as an argument into integral, they need to be able to deal with multiple values. In this case, this is implemented via an explicit for loop. TIntegrandInner computes exp(g(x, y)) for multiple values of y, but the fixed value of x that is current in the loop in TIntegrandOuter. This value x(i) play both the role of a parameter into g(x, y) and of an integration limit. Variables x and i are shared between the outer and the nested function.
Almost there! We have the integrand, only the outermost integration needs to be performed:
T = integral(#TIntegrandOuter, 0, inf);
This is a very convoluted implementation, which is not very elegant, and probably not very efficient. Again, whether results of this approach prove to be useful needs to be tested in practice. However, I don't see any other way to implement these numeric integrations in Matlab in a better way in general. For specific choices of f(x, y, v) and p(v), there might be possible improvements.