Iterate over an array in minizinc and output it - minizinc

I would like to iterate over an array in MiniZinc and output the result : something like this
array[1..4] of int: my_array = [4,5,1,3];
output [forall(c in 1..4)("element index c is: \(array[c])")];
the output should be like this
element index 1 is :4
element index 1 is :5
element index 1 is :1
element index 1 is :3
is there a way to do this in MiniZinc because I would not find it in the handbook.
Thank you
array[1..4] of int: my_array = [4,5,1,3];
output [forall(c in 1..4)("element index c is: \(array[c])")];
the output should be like this
element index 1 is :4
element index 1 is :5
element index 1 is :1
element index 1 is :3

(I assume that the indices should change, i.e. from 1..4).
The output section requires a little different syntax. Here's one way of doing this:
array[1..4] of int: my_array = [4,5,1,3];
solve satisfy;
output [
"element index \(c) is: \(my_array[c])\n"
| c in 1..4
];
The output is
element index 1 is: 4
element index 2 is: 5
element index 3 is: 1
element index 4 is: 3
There is another way of doing this, outside the output section, and can be used for debugging indices and values in fixed arrays: using trace. Here's a variant that prints the same thing, but uses trace in the forall loop in the constraint section:
array[1..4] of int: my_array = [4,5,1,3];
solve satisfy;
constraint
forall(c in 1..4) (
trace("element index \(c) is: \(my_array[c])\n")
)
;
Note: using trace does not print decision variables in any intelligible way.

Related

q - internal state in while loop

In q, I am trying to call a function f on an incrementing argument id while some condition is not met.
The function f creates a table of random length (between 1 and 5) with a column identifier which is dependent on the input id:
f:{[id] len:(1?1 2 3 4 5)0; ([] identifier:id+til len; c2:len?`a`b`c)}
Starting with id=0, f should be called while (count f[id])>1, i.e. so long until a table of length 1 is produced. The id should be incremented each step.
With the "repeat" adverb I can do the while condition and the starting value:
{(count x)>1} f/0
but how can I keep incrementing the id?
Not entirely sure if this will fix your issue but I was able to get it to work by incrementing id inside the function and returning it with each iteration:
q)g:{[id] len:(1?1 2 3 4 5)0; id[0]:([] identifier:id[1]+til len; c2:len?`a`b`c);#[id;1;1+]}
In this case id is a 2 element list where the first element is the table you are returning (initially ()) and the second item is the id. By amending the exit condition I was able to make it stop whenever the output table had a count of 1:
q)g/[{not 1=count x 0};(();0)]
+`identifier`c2!(,9;,`b)
10
If you just need the table you can run first on the output of the above expression:
q)first g/[{not 1=count x 0};(();0)]
identifier c2
-------------
3 a
The issue with the function f is that when using over and scan the output if each iteration becomes the input for the next. In your case your function is working on a numeric value put on the second pass it would get passed a table.

Find substring in cell array of numbers and strings

I have a cell array consisting of numbers, strings, and empty arrays. I want to find the position (linear or indexed) of all cells containing a string in which a certain substring of interest appears.
mixedCellArray = {
'adpo' 2134 []
0 [] 'daesad'
'xxxxx' 'dp' 'dpdpd'
}
If the substring of interest is 'dp', then I should get the indices for three cells.
The only solutions I can find work when the cell array contains only strings:
http://www.mathworks.com/matlabcentral/answers/2015-find-index-of-cells-containing-my-string
http://www.mathworks.com/matlabcentral/newsreader/view_thread/255090
One work-around is to find all cells not containing strings, and fill them with '', as hinted by this posting. Unfortunately, my approach requires a variation of that solution, probably something like cellfun('ischar',mixedCellArray). This causes the error:
Error using cellfun
Unknown option.
Thanks for any suggestions on how to figure out the error.
I've posted this to usenet
EDUCATIONAL AFTERNOTE: For those who don't have Matlab at home, and end up bouncing back and forth between Matlab and Octave. I asked above why cellfun doesn't accept 'ischar' as its first argument. The answer turns out to be that the argument must be a function handle in Matlab, so you really need to pass #ischar. There are some functions whose names can be passed as strings, for backward compatibility, but ischar is not one of them.
How about this one-liner:
>> mixedCellArray = {'adpo' 2134 []; 0 [] 'daesad'; 'xxxxx' 'dp' 'dpdpd'};
>> index = cellfun(#(c) ischar(c) && ~isempty(strfind(c, 'dp')), mixedCellArray)
index =
3×3 logical array
1 0 0
0 0 0
0 1 1
You could get by without the ischar(c) && ..., but you will likely want to keep it there since strfind will implicitly convert any numeric values/arrays into their equivalent ASCII characters to do the comparison. That means you could get false positives, as in this example:
>> C = {65, 'A'; 'BAD' [66 65 68]} % Note there's a vector in there
C =
2×2 cell array
[ 65] 'A'
'BAD' [1×3 double]
>> index = cellfun(#(c) ~isempty(strfind(c, 'A')), C) % Removed ischar(c) &&
index =
2×2 logical array
1 1 % They all match!
1 1
Just use a loop, testing with ischar and contains (added in R2016b). The various *funs are basically loops and, in general, do not offer any performance advantage over the explicit loop.
mixedCellArray = {'adpo' 2134 []; 0 [] 'daesad'; 'xxxxx' 'dp' 'dpdpd'};
querystr = 'dp';
test = false(size(mixedCellArray));
for ii = 1:numel(mixedCellArray)
if ischar(mixedCellArray{ii})
test(ii) = contains(mixedCellArray{ii}, querystr);
end
end
Which returns:
test =
3×3 logical array
1 0 0
0 0 0
0 1 1
Edit:
If you don't have a MATLAB version with contains you can substitute a regex:
test(ii) = ~isempty(regexp(mixedCellArray{ii}, querystr, 'once'));
z=cellfun(#(x)strfind(x,'dp'),mixedCellArray,'un',0);
idx=cellfun(#(x)x>0,z,'un',0);
find(~cellfun(#isempty,idx))
Here is a solution from the usenet link in my original post:
>> mixedCellArray = {
'adpo' 2134 []
0 [] 'daesad'
'xxxxx' 'dp' 'dpdpd'
}
mixedCellArray =
'adpo' [2134] []
[ 0] [] 'daesad'
'xxxxx' 'dp' 'dpdpd'
>> ~cellfun( #isempty , ...
cellfun( #(x)strfind(x,'dp') , ...
mixedCellArray , ...
'uniform',0) ...
)
ans =
1 0 0
0 0 0
0 1 1
The inner cellfun is able to apply strfind to even numerical cells because, I presume, Matlab treats numerical arrays and strings the same way. A string is just an array of numbers representing the character codes. The outer cellfun identifies all cells for which the inner cellfun found a match, and the prefix tilde turns that into all cells for which there was NO match.
Thanks to dpb.

Discriminate between empty and non empty regexp matches in Matlab

I'm trying to match some strings in Matlab and create a new table from the matches.
The variable txt contains:
Columns 1 through 4
'Time' 'LR1R2' 'LR1R2_SD' 'LR1R2_I'
Columns 5 through 8
'LR1R2_SD' 'R1' 'R1_SD' 'R1_I'
Columns 9 through 12
'R1_I_SD' 'R2' 'R2_SD' 'R2_I'
Column 13
'R2_I_SD'
And I want to select all those with '_SD' on the end of the string
pattern='_SD';
match=regexp(txt,pattern)
which returns:
match =
Columns 1 through 8
[] [] [6] [] [6] [] [3] []
Columns 9 through 13
[5] [] [3] [] [5]
Does anybody know how to discriminate between the empty and non empty matches? My aim is to build a new table from the matches. Here is what I've tried
for i=match,
~isempty(i)
end
But this returns true for everything.
Thanks
The regexp function returns a cell array, where each cell contains either an empty array (i.e. []), or a number (e.g. [6]). To go through all cells of this cell array, you can use the cellfun function and apply the isempty function to each cell:
~cellfun(#isempty,match)
which returns
ans =
0 0 1 0 1 0 1 0 1 0 1 0 1
As #Divakar correctly remarks, using
~cellfun('isempty',match)
is much faster.
When the command is run 100'000 times, I measured the following run times:
With #isempty:
Elapsed time is 0.757626 seconds.
With 'isempty':
Elapsed time is 0.118241 seconds.
Note that this syntax is not available for all functions. From the MATLAB documentation on cellfun:
cellfun accepts function name strings for function func, rather than a
function handle, for these function names: isempty, islogical, isreal,
length, ndims, prodofsize, size, isclass. Enclose the function name in
single quotes.
The answer I was looking for is something like:
for i=1:length(match),
if ~isequal(match(i),{[]}),
num(:,i)
end
end
As hbaderts suggested the following is also a way to do this:
~cellfun(#isempty,match)

Conversion from cell array

I have a cell array of 150 by 1 . My problem is why cant we use the eq function, as in
the value of species(1) = 'setosa',
but when I write species(1) == 'setosa' I was expecting to get a logical 1 but MATLAB gives Undefined function eq for cell array . I require this because I want to convert it into a logical array . How should I achieve this
You can do this by using find() and strcmp() together.
Example:
stts = {'Gable','Hip','Shed','Shed','Other'}; % string cell array
[truefalse,index]=find(strcmp(stts,'Shed')) % do it here if you want to find `Shed`
After this, truefalse are the logical values and index are the according indexes found.
truefalse =
1 1
index =
3 4

How can I filter my array of numbers in Matlab/Octave?

I have a very trivial example where I'm trying to filter by matching a String:
A = [0:1:999];
B = A(int2str(A) == '999');
This
A(A > 990);
works
This
int2str(5) == '5'
also works
I just can't figure out why I cannot put the two together. I get an error about nonconformant arguments.
int2str(A) produces a very long char array (of size 1 x 4996) containing the string representations of all those numbers (including spacing) appended together end to end.
int2str(A) == '999'
So, in the statement above, you're trying to compare a matrix of size 1 x 4996 with another of size 1 x 3. This, of course, fails as the two either need to be of the same size, or at least one needs to be a scalar, in which case scalar expansion rules apply.
A(A > 990);
The above works because of logical indexing rules, the result will be the elements from the indices of A for which that condition holds true.
int2str(5) == '5'
This only works because the result of the int2str call is a 1 x 1 matrix ('5') and you're comparing it to another matrix of the same size. Try int2str(555) == '55' and it'll fail with the same error as above.
I'm not sure what result you expected from the original statements, but maybe you're looking for this:
A = [0:1:999];
B = int2str(A(A == 999)) % outputs '999'
I am not sure that the int2str() conversion is what you are looking for. (Also, why do you need to convert numbers to strings and then carry out a char comparison?)
Suppose you have a simpler case:
A = 1:3;
strA = int2str(A)
strA =
1 2 3
Note that this is a 1x7 char array. Thus, comparing it against a scalar char:
strA == '2'
ans =
0 0 0 1 0 0 0
Now, you might wanna transpose A and carry out the comparison:
int2str(A')=='2'
ans =
0
1
0
however, this approach will not work if the number of digits of each number is not the same because lower numbers will be padded with spaces (try creating A = 1:10 and comparing against '2').
Then, create a cell array of string without whitespaces and use strcmp():
csA = arrayfun(#int2str,A','un',0)
csA =
'1'
'2'
'3'
strcmp('2',csA)
Should be much faster, and correct to turn the string into a number, than the other way around. Try
B = A(A == str2double ('999'));