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
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.
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.
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)
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
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'));