Specifying only a single index of a 1D array in a data file - minizinc

Consider the following toy model, call it foo.mzn:
int: n = 2;
array[1..n] of var 0..2: vert;
constraint vert[1] != vert[2];
solve satisfy;
The documentation (Listing 2.2.3) shows an example where the data file specifies the entire array. That is, you could do:
./minizinc -D "vert=[0,1]" foo.mzn
However, what if I only want to specify one index of the array? It feels reasonable to be able to do:
./minizinc -D "vert[1]=0" foo.mzn
but this results in
Error: syntax error, unexpected =, expecting ':'
Is it possible to specify only a single index of an array in a data file? An alternative is to do away without an array, but perhaps this is not necessary.

One way is to define the second element as an unknown/unassigned value (_), e.g.
./minizinc -D "vert[0,_]" foo.mzn
This yields two solutions:
vert: [0, 1]
vert: [0, 2]

Related

length of a just one array dimension in minizinc

If I define my array like this:
array[_, 1..2] of J: A;
where J is a enum, what function can I use to get the length of the first dimension of A? The length function returns 14 (and states that it doesn't work for multiple dimensions). I had it hard-coded like so in my testing, but it won't always be 13:
constraint forall(row in 1..13)(S[A[row, 2]] >= C[A[row, 1]]);
The length function is really only meant for getting the number of elements. When you want the retrieve indexes of an array, you should instead use the index_set function. This returns the actual index set, which you can iterate over: i in index_set(A)
For multidimensional arrays there are specific functions for each index set of the array. For example, to get the first index set from a two-dimensional array (as in your code fragment) you can use the function index_set_1of2

Conditional output minizinc

I'm messing arround with minizinc and I'm trying to achieve a conditional output where, if an array element has value 'true', the program outputs information concerning these element's array indexes. This is what I have:
include "globals.mzn";
int: time=5;
int: n=3;
int: l=n*n;
array[1..4,0..time,1..l] of var bool: X;
constraint X[1,5,7]=true;
constraint X[2,5,3]=true;
constraint X[3,5,9]=true;
constraint X[4,5,7]=true;
solve satisfy;
I attempted to solve this problem using concat, like so:
output ["X_"++concat(["\(r)_\(t)_\(pos)"
| pos in 1..l, r in 1..4, t in 0..time, where X[r,t,pos]==true])++"\n"];
However I am not allowed,
"MiniZinc: type error: no function or predicate with this signature found: `concat(array[int] of var opt string)'"
What I want is something like,
for pos in 1..l, r in 1..4, t in 0..time
if X[r,t,pos]==true
output ["X_\(r)_\(pos)_\(t)"]
How can I achieve it?
Try using fix(...) around the decision variable in the where clause, e.g.
output ["X_"++concat(["\(r)_\(t)_\(pos)"
| pos in 1..l, r in 1..4, t in 0..time, where fix(X[r,t,pos])==true])++"\n"];
fix is (often) needed when one use the actual values of decision variables, e.g. for comparing its values etc.
(The message about var opt string is perhaps misleading in this context.)

Initialize only certain elements of array in dzn file

I'm messing arround with minizinc and I want to have a static mzn file where I make the solving using only the dzn.
For a better understanding of the question, here's a sample:
include "globals.mzn";
include "data.dzn";
int: time;
int: n;
int: l=n*n;
array[1..4,0..time,1..l] of var bool: X;
solve satisfy;
I now want to initialize only few elements of X using the dzn file (the other elements should be vars).
The dzn would look like this
time=1;
n=3;
X[4,1,7]=true;
Since this initialization is impossible, I also tried using X=array3d(1..4,0..time,1..l,[false,...,false] where every element other than the element in position (4,1,7) is false. However this initializes every element and I cannot obtain the result I wish since it cannot satisfy the constraints I have.
Is there a way to initialize only one or some elements of this array using the dzn file?
One way to do this is to use the anonymous variable (_) in the data matrix in the dzn file. Here is a simple example:
% mzn file
include "data.dzn";
int: time;
int: n;
array[1..time,1..n] of var bool: X;
solve satisfy;
And the data file:
% data.dzn
time=3;
n=2;
X = array2d(1..3,1..2,
[_,_,
_,_,
_,false
]);
Note that this approach requires at least one non-anonymous value, otherwise this message is thrown: array literal must contain at least one non-anonymous variable.

How to select rows from character array that match char string and save them in a new array?

I have a char array A which basically contains a list of files names (each row one file)
(char, 526x26)
val =
0815_5275_UBA_A_1971.txt
0815_5275_UBA_A_1972.txt
0823_6275_UBA_A_1971.txt
0823_6275_UBA_A_1972.txt
0823_6275_UBA_A_1973.txt
...
I also have a variable
B = '0815_5275'
I'd like to select all rows (filenames) that start with B and save them in a new array C.
This should be simple, but somehow I can't make it work.
I've got this:
C = A(A(:,1:9) == B);
but I get the error message:
Error using ==
Matrix dimensions must agree.
I do not know in advance how many rows will match, so I can not pre-define an empty array.
thanks, any help is appreciated!
Try ismember(A(:, 1:numel(B)), B, 'rows') rather to get a logical vector that indexes only the rows you want
and now
A(C,:) to extract the rows
The reason you're getting a dimension mismatch error is because your A(:,1:9) has many rows but B only has one and Matlab does not automatically broadcast like Octave or Python. You could do it using either repmat or bsxfun but in this case ismember is the correct function to choose.

assigning values to a field of an structure array in MATLAB

I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.