reset password
Author Message
iamrajakumar
Posts: 9
Posted 18:22 Nov 04, 2019 |

We tried a lot to find a way to store arithmetic operation in an array and then use them for processing.

eg. get + or - or / or * in an array like say array opp = [+,+.-,*,/,+] and then use them like 5 opp[1] 10 = to get 15. or like opp[1](5,10) to get 15

We are able to do it for normal variable but not on array. 

eg. as below

builtin-num-bin-op: opp = "+";
int: val = opp(5,10);

We are able to get the expected result in val. 

But can't declare an array of that type builtin-num-bin-op, and thus can't solve the our problem to get the operations as input.

Please advice.

rabbott
Posts: 1649
Posted 19:01 Nov 04, 2019 |

When I try to run this model:

builtin-num-bin-op: opp = "+";
int: val = opp(5,10);
output [show(val)];

I get this error message.

MiniZinc: type error: undefined identifier `op'

Would you mind showing me the actual model that you run and the output it produces. Thanks.

iamrajakumar
Posts: 9
Posted 19:47 Nov 04, 2019 |
The actual code that worked before is below. But now even after removing array it is not working. I am also getting the same error as yours. 

int: boardSize = 7;
% tried to parameterize operator. It worked initially but now not working. Especially not working with array so harcoded operators.
builtin-num-bin-op : opp = "-";
int: val = opp(boardSize,boardSize+1);
output["\(val)"];

 

This is the code worked like an hour ago. It seems I have modified a lot after that and now this initial one not working at all. I was able to pring -1. 

Then I do not have the output and the exact item i had while initial writing it and then creating the modal based on it. 

Is there any other way to parameterize operation or operators like +, -, *  and /, 

So that I need not hard code these values and get them as input from User and work for all different puzzles.

Last edited by iamrajakumar at 19:47 Nov 04, 2019.
iamrajakumar
Posts: 9
Posted 20:21 Nov 04, 2019 |

May be it did not work when I tried and I saw some other version out as -1 and got excited. 

Ignore this code all together. And help me with an example to get arithmetic operations as input to a variable or to an array.

Any such example puzzle where these operation are input how are those solved in MiniZinc.

It will be so hlepful, and sorry for confusing with my code snippet.

rabbott
Posts: 1649
Posted 21:36 Nov 04, 2019 |

As far as I know, there is no way to do what you want to do. There is no type in MiniZinc for functions. So you can't assign a function to a variable as you can in Haskell, Python, etc. The closest you can come is to do this:

output ["\('+'(3, 4))  \('+'(3, 4) == '+'(5, 2))"];   % => 7 true

But you can't even use that trick to put '+' into an enum.

enum operators = {'+', '-', '*', '/'}
 
generates an error message. You can put most things inside single quotes and make it into an identifier, but it doesn't work for operators.

 

avelu
Posts: 2
Posted 00:26 Nov 05, 2019 |

Since we were not able to do it directly, created a indirect method to achieve what we wanted. Array of operators as input.

If others are having same need please try to customize below for your need.

enum math = {P,M,S,D}; % P for +, M for -, S for * and D for / (Divide)
%let ops be operations + - * / in same order meaning 1 means +, 2 means -, 3 means * and 4 means /
set of int: ops=1..4;
function var int: opx(var int: x2, var int: c, int: opp)
if opp == 1 then x2 + c 
elseif opp == 2 then x2 - c  
elseif opp == 3 then x2 * c  
else x2 div c 
endif;
array[1..12] of ops: operations;
constraint opx(solution[1],solution[2],operations[1]) = <some_Val>;
%Then for output 
output ["\(math[operations[1]])];
Last edited by avelu at 00:28 Nov 05, 2019.
rabbott
Posts: 1649
Posted 08:39 Nov 05, 2019 |

You might want to look at something like this.

enum OP = {plus, minus, times, divided_by}; 
predicate eval_op(var SMALL_INT: v1, var  OP: op, var SMALL_INT: v2, var  SMALL_INT: v3) =
    op == plus /\ v1 + v2 == v3 \/
    op == minus /\ v1 - v2 == v3 \/
    op == times /\ v1 * v2 == v3 \/
    op == divided_by /\ v1 div v2 == v3;

 
set of int: SMALL_INT = 1..10;
set of int: VERY_SMALL_INT = 3..5;
var VERY_SMALL_INT: val_1;
var OP: op;
var VERY_SMALL_INT: val_2;
var SMALL_INT: val_3;
constraint eval_op(val_1, op, val_2, val_3);
solve satisfy;
output ["\(val_1) \(op) \(val_2) == \(val_3)"];

 

Set the Configuration Editor (top right icon) to User-defined behavior and Stop after this many solutions to, say, 20.

I got the following output.

 

Running untitled_model.mzn
3 plus 3 == 6

----------

3 times 3 == 9

----------

3 divided_by 3 == 1

----------

4 plus 3 == 7

----------

4 minus 3 == 1

----------

4 divided_by 3 == 1

----------

5 plus 3 == 8

----------

5 minus 3 == 2

----------

5 divided_by 3 == 1

----------

3 plus 4 == 7

----------

4 plus 4 == 8

----------

4 divided_by 4 == 1

----------

5 plus 4 == 9

----------

5 minus 4 == 1

----------

5 divided_by 4 == 1

----------

3 plus 5 == 8

----------

4 plus 5 == 9

----------

5 plus 5 == 10

----------

5 divided_by 5 == 1

----------

==========

Finished in 218msec

 

 

 

 

 

 

rabbott
Posts: 1649
Posted 12:13 Nov 05, 2019 |

This also works.

enum OP = {' + ', ' - ', ' * ', ' / '}; 
predicate eval_op(var int: v1, var OP: op, var int: v2, var int: v3) =
    op == ' + ' /\ v1 + v2 == v3 \/
    op == ' - ' /\ v1 - v2 == v3 \/
    op == ' * ' /\ v1 * v2 == v3 \/
    op == ' / ' /\ v1 div v2 == v3;

set of int: SMALL_INT = 0..16;
set of int: VERY_SMALL_INT = 2..5;

var VERY_SMALL_INT: val_1;
var OP: op;
var VERY_SMALL_INT: val_2;
var SMALL_INT: val_3;

constraint eval_op(val_1, op, val_2, val_3);

solve satisfy;

output ["\(val_1)\(op)\(val_2) == \(val_3)"];
Last edited by rabbott at 12:15 Nov 05, 2019.