3

I'm familiarizing with the basic of MiniZinc. So, armed with the MiniZinc IDE, I write snippets like

solve satisfy;

string: s1 = "hello";
string: s2 = "world";

function list of int: cdr(list of int: v) =
  [v[i] | i in 1..length(v)];
function list of string: cdr(list of string: v) =
  [v[i] | i in 1..length(v)];

function string: concat(list of string: V) =
  if length(V) == 0 then "" else V[0] ++ concat(cdr(V)) endif;

output [concat([s1," ",s2])++" "++show(cdr([1,2,3]))];

that displays

Compiling hello.mzn
Running hello.mzn
hello world [1, 2, 3]
----------
Finished in 49msec

now, the cdr of a list of ints seems to be wrong. I assume it's my bug, albeit I cannot spot it.

Could assertions help me here ? Since I'm going to use Gecode (and then I have Gist) to actually put my code in production, could I follow that route ?

Any hint appreciated...

edit this snippet

solve satisfy;

function list of string: cdr_s(list of string: v) =
  [v[i] | i in 2..length(v)];

function string: vcat(list of string: V) =
  if length(V) == 0 then "" else V[1] ++ vcat(cdr_s(V)) endif;

output [vcat(["hello"," ","world"])];

reports

MiniZinc: type error: no function or predicate with this signature found: `cdr_s(array[int] of string)'
/tmp/MiniZinc IDE-9nYiuF/hello.ozn:2
CapelliC
  • 59,646
  • 5
  • 47
  • 90

2 Answers2

4

MiniZinc is a constraint solver rather than a normal programming language. It knows variables and parameters. You define constraints to delimit the search space for variable values forming the solutions. The output statement is then used to display the solution in a formatted way.

Your code does neither contain variable definitions nor constraints. Assertions are being used in MiniZinc as special constraints ("constraint assert") to detect invalid parameters. This is similar to the assert macro in C/C++.

User-defined functions were introduced in MiniZinc 2.0 to write constraints in a more elegant fashion. Recursion is also supported.

Have a look at the tutorial and the examples.

Hakan Kjellerstrand's MiniZinc page is also an excellent start.

Your gecode tag refers to one of the supported solver back-ends for MiniZinc. The MiniZinc IDE allows to select the back-end. Some back-ends require installations of external packages. The MiniZinc compiler creates intermediate FlatZinc code which is finally interpreted and solved by one of the solver back-ends.

Axel Kemper
  • 10,544
  • 2
  • 31
  • 54
  • Thanks. With my silly test I was trying to understand the extent to where user functions overloading was supported, and the debugging tools available. So far, I have not yet found a practical way to debug... – CapelliC Jan 23 '15 at 08:11
  • In some cases, it helps to have a look at the FlatZinc file. It shows how MiniZinc interprets the constraint programming specification. Apart from that, you might want to start minizinc.exe with the --keep-files parameter to have the chance to analyze intermediate files. Most executables around MiniZinc have debugging flags as optional commandline parameters. – Axel Kemper Jan 23 '15 at 09:01
  • 1
    @CapelliC One way to debug is to use trace/1 for printing indices etc. – hakank Jan 23 '15 at 10:33
  • 1
    @CapelliC trace is good when you suspect that indices are not correct. In general it's harder to debug a constraint programming model than in traditional programming languages since all the constraints "happens at the same time". A simple approach for debugging is to comment out most constraint and add each and see which one does give a failure. There are some CP systems (e.g. ECLiPSE) with some kind of step-debug in the constraints, but MiniZinc don't have this feature. – hakank Jan 23 '15 at 10:56
4

I'm a little confused of what you think is a bug and there are some other issues.

The output of the model seems fine with the "cdr([1,2,3])" giving "[1,2,3]". The name "cdr" suggests that you want the "but first" function, but MiniZinc is a default 1-based system (not 0-based) so your function should probably be

 function list of int: cdr(list of int: v) =
   [v[i] | i in 2..length(v)];

Since one can define the indices of an array (e.g. that start index is 0), a more general definition is this (which I'm not very happy with but you probably get my point):

function list of int: cdr3(list of int: v) =
   [v[i] | i in index_set(v) diff {min(index_set(v))}];

So now you can write something like this:

% ...
array[int] of int: t = array1d(0..3, [1,2,3,4])
output [
   show(cdr3(t))
];

Also, your "concat" function is not used at all, instead the built-in "concat" it used. (Try to rename your version to "concat1".) That is also why you don't get an error for the "V[0]" construct (which should give out of bounds error). I would have expected that trying to re-define a built-in would generate an error, but MiniZinc 2.0 is more permissive than version 1.6 in certain areas.

And I agree with Axel's general comment. As a general programming language MiniZinc is not very impressive (at least in my book). The real power come when you add constraints and decision variables to the model. Please note that MiniZinc's list/array handling with decision variables is not as dynamic as Prolog. In general you should always think in term of arrays as having fixed length.

It's great that you start to look into MiniZinc. I hope that these comments actually help you when learning MiniZinc.

/Hakan

hakank
  • 6,629
  • 1
  • 17
  • 27
  • I should perhaps have mentioned that. Yes, http://hakank.org/ has been down for a week now. The best substitute is to use my GitHub page: https://github.com/hakank/hakank where almost all my CP models (and everything else) is published. – hakank Jan 23 '15 at 08:00
  • another bug of mine I found after I've fixed with your indication: seems that user functions cannot call other user functions... – CapelliC Jan 23 '15 at 10:44
  • @CapelliC Can you give an example of this ("unctions cannot call other user functions")? – hakank Jan 23 '15 at 11:00
  • @CapelliC "vcat" is a recursive function and you should be careful with these especially when handling decision variables. The recursive call in "vcat" seems to work in this case. However, something _is_ weird here since - surprisingly - this output actually works: output [ vcat(["hello"," ","world"]), " ", show(cdr_s(t)), "\n" ]; You should probably register a complaint... – hakank Jan 23 '15 at 17:59
  • @CapelliC Your original model didn't compile, but with the changed output section it compiled and showed the output. Perhaps relevant: I'm using the latest Git version when testing. – hakank Jan 23 '15 at 19:31
  • Since we mentioned it here earlier: http://hakank.org/ is starting to be accessible again (hopefully you notice that it's faster now). – hakank Jan 24 '15 at 18:40