Referring to decision variable arrays in MiniZinc functions - minizinc

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?

Related

How do I splice two vectors in MATLAB?

I need to splice two vectors based on a condition that also takes a vector as an argument. Example:
vec_cond = -5:5; % The exact values are calculated differently
vec1 = 0:10;
vec2 = 5:15;
I need a resulting vector to be comprised from values out of both vectors based on a condition from the third vector. Let's assume this is the condition: vec_cond >= 0
Then if this is true, I want vec_result to have values from vec1 on appropriate indexes, and if not, take values from vec2 on appropriate indexes:
vec_result = vec1 if (vec_cond >=0) else vec2
This is portion of my MATLAB script (original comments were Czech) where I would need to use that:
%% Draw output current and voltage characteristics
R = 100:5:2*10^3; % Load rezistor [ohm]
U_2 = R .* (I * 10^(-3)); % Load voltage [V]
U_1stab = U_LM + U_x + U_2; % Min. required input voltage
% for stabilization [V]
U_delta = U_1 - U_1stab; % Difference between actual and
% min. req. input voltage [V]
U_2norm = U_1 - U_LM - U_x % Calculating output load
% voltage based on params [V]
I_z = U_2norm ./ R .* 10^3; % Load current param based[mA]
I_r1 = I * I_z.^0; % Stabilizator current [mA]
So the condition would be U_delta >= 0.
I tried to use a ternary operator, which I found here:
I_graph = (U_delta >= 0) : (#() I) : (#() I_z); % Current splice [mA]
U_graph = (U_delta >= 0) : (#() U_2) : (#() U_2norm); % Voltage splice [V]
That means that for I_graph, if the condition is met, take a constant value I and vectorize it, otherwise take values from I_z vector. For U_graph, if the condition is met, take values from U_2 vector, otherwise take constant value of U_2norm and vectorize it.
But it didn't work, this is what it tells me:
Operator ':' is not supported for operands of type 'function_handle'.
Error in vypocet1 (line 52)
I_graph = (U_delta >= 0) : (#() I) : (#() I_z); % Current splice [mA]
I guess that I might want to use for loop, but I'm not sure how it will help me and how can I actually construct the necessary vector using a for loop.
Given:
vec_cond = -5:5;
vec1 = 0:10;
vec2 = 5:15;
You can set:
out = vec2;
I = vec_cond >= 0;
out(I) = vec1(I);
This uses logical indexing, which is indexing with a logical array.
By the way, the ternary operator you found is an exercise to overload the : operator for a specific class to do something that it normally doesn’t do. Note how you use the colon when creating vec_cond. This is what the colon operator does normally.

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.

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(%)

Matlab unique function

I'm struggling with determining the probability of occurrence of unique elements in thresh_strain matrix (which can be seen below as a 100 x 16). I was trying to use the code at the bottom to do this, but I get an equal probability of occurrence associated with each of the elements, whereas I want the probability of occurrence associated with unique elements in thresh_strain.
function [thresh_strain] = MCsolution()
no_iterations = 100;
thresh_strain = zeros(100, 16);
casechoice =input('Enter 1 for 1st Layup and 2 for 2nd layup:');
for i=1:no_iterations
for j=1:16
J = Nielsennew(casechoice);
thresh_strain(i,j) = J(1, j);
end
end
% [uniqueValues,~,uniqueIndex] = unique(thresh_strain);
% frequency = accumarray(uniqueIndex(:),1)./numel(thresh_strain);
Thanks
It is not really clear from the title and description, but I suppose you may be looking for something like this:
myUniqueValues = unique(myMatrix);
nelements = hist(myMatrix(:),myUniqueValues);
%plot(myUniqueValues,nelements)
Basically calculating how often each unique value occurs. From here getting the corresponding percentage is of course trivial.

Compute the convolution of two arrays in MATLAB

I am trying to generate an array from some starting values using this formula in MATLAB:
yt = a0 + ∑i=1p (ai ⋅ yt-i), t ≥ p
p is some small number compared to T (max t). I have been able to make this using two for cycles but it is really slow. Is there some easy way to do it?
First p values of y are provided and vector a (its length is p+1) is provided too...
This is what I have so far, but now when I tried it, it doesn't work 100% (I think it's because of indexing from 1 in MATLAB):
y1 = zeros(T+1, 1);
y1(1:p) = y(1:p);
for t = p+1:T+1
value = a1(1);
for j = 2:p+1
value = value + a1(j)*y1(t-j+1);
end
y1(t) = value;
end
EDIT: I solved it, I am just not used to Matlab indexing from 1...
This statement
if(p>=t)
looks odd inside a loop whose index expression is
for t = p+1:T+1
which seems to guarantee that t>p for the entire duration of the loop. Is that what you meant to write ?
EDIT in response to comment
Inside a loop indexed with this statement
for j = 2:p
how does the reference you make to a(j) ever call for a(0) ?
y1 = zeros(T+1, 1);
y1(1:p) = y(1:p);
for t = p+1:T+1
value = a1(1);
for j = 2:p+1
value = value + a1(j)*y1(t-j+1);
end
y1(t) = value;
end