" /> My Constraint Programming Blog: September 2009 Archives

« August 2009 | Main | October 2009 »

September 30, 2009

This weeks news

This is mostly a consolidation (with some additional information) of the tweets on twitter.com/hakankj since last time.

mzn_show.pl

The Perl program mzn_show.pl is used for making little better output from the FlatZinc solvers.

The parameters to the program are now:
  • {tr:from:to:}: translate digit to another digit/character
  • {trvar:var:from:to:}: translate digit to another digit/character for a specific variable var
  • {trtr:from_string:replacement_string:}: translates all digits in from_string to the corresponding digit/character in replacement_string (inspired from the Unix tr command)
  • {trtrvar:var:from_string:replacement_string:}: as trtr but for a specific variable var
  • {nospaces}: don't show space after character
  • {noprintf}: don't try to be clever with printf stuff
Example: for showing a nicer picture of a Nonogram:

flatzinc nonogram_create_automaton2.fzn | mzn_show.pl "{tr:1: :} {tr:2:#:} {nospace}"

Where the {tr:from:to:} means translate digit from to character to, and {nospace} means that no spaces are shown after each digit/character.

This is now probably better written with trtr:

flatzinc nonogram_create_automaton2.fzn | mzn_show.pl "{trtr:12: #:} {nospace}"

Also, see below for some more examples.

MiniZinc/Comet: Nonogram model fixed for "zero length" clues

I discovered that my MiniZinc and Comet models had a little bug in the generation of the automaton for "zero length" clues (i.e. the row/column is completely empty, just 0's).

The fixed versions is here:
* MiniZinc: nonogram_create_automaton2.mzn
* Comet: nonogram_regular.co

It was quite tricky to debug the generated automata, but I found a fix for it surprisingly soon. I won't publish the fixes here, but it suffice to say that the MiniZinc model is - shall we say - not more beautiful than before.

A test instance for this: T2 (source unknown)
* Comet: nonogram_t2.co. * MiniZinc: nonogram_t2.dzn

T2 has the following two solutions:
   ##   ##  ###
  #  # #  # #  #
  #      #  #  #
  #     #   ###
  #  # #  # #
   ##   ##  #

----------

   ##   ##  ###
  #  # #  # #  #
  #     #   #  #
  #      #  ###
  #  # #  # #
   ##   ##  #

One more Nonogram example

Besides the T2 problem instance mentioned above, there is a new Nonogram example: Gondola for both Comet and MiniZinc:
* Comet: nonogram_gondola.co
* MiniZinc: nonogram_gondola.dzn.
For the curious, here is the solution, using the following command (see above for the mzn_show.pl part):
$ mzn2fzn -G jacop --data nonogram_gondola.dzn nonogram_create_automaton2.mzn
$ java JaCoP.fz.Fz2jacop -a -s  nonogram_create_automaton2.fzn | mzn_show.pl "{trtr:12: #:} {nospaces}"
  #####      ######
  ######     #    #        #
     ###  ###########     ###
  ######   # #    #       # #
  #######  # # # ##   #   ###
     ####    #    #  ##   # ####
  #######    #  # # ##    ### #
  #######     #  # ###    # #
     ####     # #  # # #########
     ####   ######## # #
     ####  #     ####  #   ###
     #### # #######    #  #####
     #### # #  ## # ####  #    #
     #### #########      ## # ##
     #### # ###   #      ##    #
     #### # ######       #   # #
     #### ########      ###    #
     ########## ###    ##### ###
      #### # ## ###    #####  ##
      ### #####  ##     ########
      ## ######  ###      #    #
      # ############     #
  ####################   # #
    ## #########################
   ##   ### ####################
  ##     ##### ### ## ## ## ## #
  #   ##  ######################
            ####################
    ###       ##################
  #        ##

Updated Comet's SONET model

In About 20 more constraint programming models in Comet Pierre Schaus (on of Comet's developers) commented that my use of tryall outside the using block in the SONET problem (sonet_problem.co) was not to recommend.

I have updated the model with his suggestion that uses or instead:
m.post(or(ring in 1..r) (rings[ring,client1] + rings[ring, client2] >= 2));
Thanks for the correction (suggestion), Pierre.

New MiniZinc model: Letter Square problem

letter_square.mzn is (yet another) grid problem. From my comment in the model file:

This problem is from the swedish book Paul Vaderlind: Vaderlinds nya hjärngympa ('Vaderlind's new brain gymnastics'), page 63ff. Unfortunately, I don't know the origin of this problem.

The objective is to create a matrix where all values on each row/column is different, except for the blanks.

A set of hints is given: the (or some) first seen non blank of each
- upper row
- lower row
- left column
- right column
seen from that view.

Example:
    B B
  -------
 |A   B C| 
B|  B C A| 
B|B C A  | 
 |C A   B| 
 --------
  C
This model codes the hints as follows:
 blank -> 0
 A     -> 1
 B     -> 2
 C     -> 3

row_upper = [0,2,2,0];
row_lower = [3,0,0,0];
col_left  = [0,2,0,0];
col_right = [0,0,0,0];
Note: there are no hints for the right column.

Here is yet another opportunity to use mzn_show.pl (0 is here translated to blank, etc):

solver model.fzn | mzn_show.pl "{trtr:0123456: ABCDEF:}"

With the following output:
  A B   C
      A B C
  B C   A
    A C   B
  C   B   A
The following problem instances from the book has been created:

September 23, 2009

MiniZinc Challenge 2009 Results

The result of MiniZinc Challenge 2009 is presented in MiniZinc Challenge 2009 Results:
There were two entrants this year:

* Gecode
* SICStus

In addition, the challenge organisers entered the following three FlatZinc implementations:

* ECLiPSe
* G12/FD
* G12/LazyFD

As per the challenge rules, these entries are not eligible for prizes, but do modify the scoring results.

Summary of Results

fd_search

sicstus 1651.8
eclipse_ic 322.1
gecode 4008.8
g12_fd 2040.6
g12_lazyfd 1376.6

free_search

sicstus 1841.0
gecode 4535.5
g12_fd 1112.4
g12_lazyfd 2511.1


Congratulations to the Gecode team!

September 21, 2009

A few new MiniZinc models, and a lot of improved

Some news about my MiniZinc models.

New MiniZinc models

This last weeks I have implemented the following new MiniZinc models:

Corrected some models

When testing the MiniZinc/FlatZinc support for the new version of JaCoP , I found problems in some models. These are now corrected:
  • strech_path.mzn: The former implementation was not correct.
  • min_index.mzn and max_index.mzn:
    The minimum(x[i], x) and maximum(x[i], x) don't work with the current MiniZinc ROTD version. Substituted to x[i] = min(x) and x[i] = max(x).

Improved all global constraints models

The global constraints section of My MiniZinc Page contains about 160 decompositions of global constraints from Global Constraint Catalog (and some not in the Catalog). The following improvements has been done on all models, especially for the older models:
  • Corrected the links to Global Constraint Catalog in the presentation of the constraint (only older models)
  • Removed some strange characters in the quoted text from Global Constraint Catalog (I hope all these has been removed now).
  • Made older models more general by using index_set, ub, lb, instead of assuming that all arrays start with index 1 etc. Some examples of this generality
           ...
           let {
             int: lbx = min(index_set(x)),
             int: ubx = max(index_set(x))
           } in
             forall(i in lbx+1..ubx) (
               forall(j in i+1..ubx-1) (
                  % ...
               )
             )
    
            forall(i in index_set(x)) (
              all_different([x[i,j] | j in index_set(x)) 
            )
          
            
            

September 17, 2009

At Twitter: http://twitter.com/hakankj

Today I decided to use Twitter more, and more systematic. It doesn't mean that I will stop blogging, not at all. There I can direct notify when new models has been published instead of waiting some weeks until blogging about a couple new models; about some newly found papers etc. And also about new blog posts.

Sometimes there will be tweets about other things than constraint programming (and related paradigms), and - not very often - in swedish.

My Twitter page is: www.twitter.com/hakankj, note the username, with an ending "j".

I hope to see you over there.

September 16, 2009

JaCoP version 2.4 released

From JaCoP's news JaCoP version 2.4 is released:
Dear all,

We are happy to announce the release of a new version of our
Java-based solver JaCoP. This new version 2.4 has a number of new
features in addition to some bug fixes. The most important additions
in this version are:

1. The flatzinc interface that makes it possible to run minizinc
programs using JaCoP. The distribution contains number of different
minizinc examples.

2. Geometrical constraint, geost, based on pruning algorithms
originally proposed by Nicolas Beldiceanu et al. This constraint makes
it possible to define placement problems of non-convex objects in
k-dimensional space.

3. Knapsack constraint, which is based on the work published by Irit
Katriel et al. We extend the original work in number of ways, for example by
making it possible to use non-boolean quantity variables.

4. Set constraints defining typical operation on sets using set
interval variables.

This work would not be possible without help of several people. We
would like to thank Hakan Kjellerstrand for his help in testing
flatzinc parser as well as providing a number of examples in minizinc
format. We would also like to thank Meinolf Sellmann for his comments
on the initial implementation of knapsack constraint which have helped to
improve it further. Marc-Olivier Fleury has implemented most of the
functionality of the geost constraint. Robert Åkemalm has implemented the
first version of set constraint package. Wadeck Follonier has implemented
the first version of the Knapsack constraint. We would like to thank them
for their contributions.

As always feel free to send us ( radoslaw [dot] szymanek [at] gmail [dot] com )
feedback. We are always looking for cooperation to improve JaCoP. If you miss
some functionality of JaCoP we can help you to develop it so it can be done
efficiently and fast.


best regards,
Radoslaw Szymanek and Kris Kuchcinski
The latest version of JaCoP can be downloaded here.

For more information, see:
Also see My JaCoP page.

MiniZinc/FlatZinc support

I have especially tested the FlatZinc solver (Fz2jacop) and it is fast. For example, here is the statistics for nonogram_create_automaton2.mzn with the P200 problem (I wrote about this some days ago here):
Model variables : 629
Model constraints : 50

Search CPU time : 640ms
Search nodes : 1040
Search decisions : 520
Wrong search decisions : 520
Search backtracks : 520
Max search depth : 22
Number solutions : 1

Total CPU time : 1010ms
Note: JaCoP uses a special optimized regular constraint.

The FlatZinc solver has the following options:
$ java JaCoP.fz.Fz2jacop --help
Usage: java Fz2jacop [] .fzn
Options:
    -h, --help
        Print this message.
    -a, --all-solutions
    -t , --time-out 
         - time in second.
    -s, --statistics
    -n , --num-solutions 
         - limit on solution number.
Great work!

September 13, 2009

At last 2: A Nonogram solver using regular written in "all MiniZinc"

The model: nonogram_create_automaton2.mzn.

nonogram_regular.mzn

In At last, a Nonogram solver using regular constraint in MiniZinc I wrote about a Nonogram solver in MiniZinc using the regular solver, nonogram_regular.mzn. The drawback of this version is that an external program (make_nonogram_automata.pl) was needed to convert the Nonogram patterns (clues) to an automaton (finite states) for use in the regular constraint.

nonogram_create_automaton.mzn

In an update some hours later in the same blog post, the variant nonogram_create_automaton.mzn was mentioned. This is an "all MiniZinc" solution where the model also calculating the automata. The drawback of this was that the states is var int (decision variables), so it couldn't use the optimized regular constraint that some solvers (e.g. Gecode/FlatZinc) has implemented (this optimized version of regular is in fact the reason that Gecode/FlatZinc is so fast for the nonogram_regular.mzn model.) Instead a tweaked version of MiniZinc's standard regular constrant was used.

nonogram_create_automaton2.mzn

After a short discussion about this with Mikael Lagerkvist (of the Gecode team) the other day, we agreed that it would be nice thing to have the states calculated as "par" variables (i.e. not decision variables), thus the optimized regular could be used.

So I went got back to the drawing board and wondered how to do this. The solution I've found is not pretty, in fact it is hairy, very hairy: nonogram_create_automaton.mzn.

It is now as fast as nonogram_regular.mzn for solvers that use optimized version of regular, especially on the P200 problem.

Problem instances

Here are the problem instances I have tested (they are the same as used before.)

Comparison of calculating of the states

Now, let's compare the two different versions of calculating the automaton states.

First method: using decision variables

This is the version that is used in nonogram_create_automaton.mzn. The states are represented by the 2-dimensional array states.
states[1,1] = 1
/\ 
states[1,2] = 2
/\
forall(i in 2..len-1) (
   if i in zero_positions then
      states[i,1] = i+1 /\
      states[i,2] = 0 /\
      states[i+1,1] = i+1 /\
      states[i+1,2] = i+2
   else 
      if not(i - 1 in zero_positions) then
        states[i,1] = 0 /\
        states[i,2] = i+1
      else 
        true
      endif
   endif
)
/\
states[len,1] = len
/\
states[len,2] = 0
Quite neat, and relatively easy to understand.

Second method: no decision variables

And this is the non-decision variable version of calculating the finite states used in nonogram_create_automaton2.mzn. Note that states are represented by a 1-dimensional array, which is - as I have understood it - a requirement for this kind of initialisation of an array. It is also the cause of this hairyness.
array[1..2*len] of 0..len*2: states = 
[1, 2] ++
[
   if i div 2 in zero_positions then
       if i mod 2 = 0 then
        0
       else
        (i div 2) + 1
       endif
   elseif (i-1) div 2 in zero_positions then
       if i mod 2 = 0 then
        (i div 2)+1
       else
        (i div 2)+2
       endif
   else
     if not( (((i-1) div 2) - 1) in zero_positions) then
        if i mod 2 = 0 then
           (i div 2) + 1
        else 
          if (i div 2) + 1 in zero_positions then
              (i div 2) + 2
          else 
              0
          endif
        endif
      else
         if i mod 2 = 0 then
             (i div 2) + 1
         else 
            if not((i div 2) + 1 in zero_positions) then
               0
            else 
               (i div 2) + 2 
            endif
         endif
      endif
   endif
| i in 3..2*(len-1)]
++
[len, 0]
It could most probably be done in a more elegant fashion. And maybe I will think more about this later on.

September 09, 2009

At last, a Nonogram solver using regular constraint in MiniZinc

Here it is: nonogram_regular.mzn, a MiniZinc solver for Nonogram problems, using regular constraint.

In Comet version 2.0 released I wrote about the rewritten automata handler for the new Comet model nonogram_automaton.co (using the built-in constraint regular and helper function Automaton, both new in Comet version 2.0). This inspired me to finish the project of a "real" Nonogram solver for MiniZinc which use the regular constraint instead of the old (very slow) model nonogram.mzn.

Since MiniZinc has a built-in regular constraint, the hardest part was to create an automaton (finite state machine) given a Nonogram pattern. To be honest, I didn't write it purely in MiniZinc; instead a Perl program was written for this conversion (see below for more information about this program). Update: Well, I do have a version fully written in MiniZinc, nonogram_create_automaton.mzn, but it is not fast enough to be really interesting (must faster than the old version, nonogram.mzn, though). End of update this time.

The conversion pattern -> automaton is the same as described in Comet: regular constraint, a much faster Nonogram with the regular constraint, some OPL models, and more. To quote verbatim:
For the Nonogram clue [3,2,1] - which represents the regular expression 
"0*1110*110*10*" - the following automata (transition matrix) is 
generated:
1 2
0 3
0 4
5 0
5 6
0 7
8 0
8 9
9 0

Note that the regular function uses 0 (zero) as the failing state, so the states 
must start with 1..

Results: P200

In fact, the only model I was really curious about was the P200 problem since it has been the one that was the challenge for the Comet Nonogram solver. See the following posts for more about this quest: First, here is a picture of the solution of the P200 problem (nonogram_p200_aut.dzn, generated by the minizinc solver (currently the only solver that use output as formatting output):
 ##   ##     ###
####  # #    # ####
 #### # ##   #     #
####  # # #  #  #  #
 ##   # # ##  ###  #####
      #   # #   #  ##  #
     ###  # #####  #  ##
   ### ##  ##    # ##  ##
  ## #  ####   # # #    #
 ##      ## # ## #     ##
 #  #     # ### ##   ###
 #  # ##  #######  ###
 # ##     ## # #####
 ###  ## ##  #  ##
  ###   ##   #   ##
    #####    #    ##
  ##   ##    #     ##
 ####   ##   #    ##
######   ##  ### ##
#######   #### ###  ##
 #######    ####   ####
#######      #      ####
######       #     ####
 ####       ##      ##
  ##         #

P200: How does different solver do?

Here is a small benchmark for solving the P200 problem with different solvers. It was run on a Linux machine (Mandriva), Dual CPU 3.40GHz, 2Gb memory. "Runtime" is the total runtime, including converting from MiniZinc model to FlatZinc, startup, and also small time for running a wrapper program (where I can choose solver etc). Also, the solvers searched through the whole search tree for a solution (which happens to be exactly one).

All versions of the solvers was "the latest" as of 2009-09-08, i.e. the versions from respective CVS, SVN, or release of the day.

The search strategy used was first_fail where the columns (j) is labeled before rows (i):
solve :: int_search(
        [x[i,j] | j in 1..col_max, i in 1..row_max],
        first_fail,
        indomain_min,
        complete
        ) 
    satisfy;
For the MiniZinc/lazy solver, I also tested with solve satisfy since it often do very well without any specific search heuristics.
  • Gecode/FlatZinc: runtime 1.0s, solvetime 0.2s, failures 520 (also see below)
  • MiniZinc/minizinc: runtime 9s, 7697 choice points
  • MiniZinc/lazy: runtime 6s, choice points 2572
  • MiniZinc/lazy (with solve satisfy): runtime 13s, choice points 0
  • MiniZinc/fd: runtime 14s, choice points 11615
  • MiniZinc/fdmip: runtime 14s, choice points 11615
  • ECLiPSe/ic: runtime 109s
  • ECLiPSe/fd: runtime 34s
The Gecode/FlatZinc solver was by far the fastest. Here is the full statistics (for one random instance):
runtime:       0.207 (207.693000 ms)
solvetime:     0.198 (198.988000 ms)
solutions:     1
variables:     625
propagators:   50
propagations:  22940
nodes:         1041
failures:      520
peak depth:    22
peak memory:   1220 KB
mzx.pl nonogram_regular.mzn --fz --data nonogram_p200_aut.dzn  0,96s user 0,10s system 98% cpu 1,078 total
For comparison, here is the statistics for running the Comet model nonogram_automaton.co:
time:      459
#choices = 520
#fail    = 794
#propag  = 693993
comet nonogram_automaton.co  1,32s user 0,09s system 90% cpu 1,558 total
And, finally, the statistics for the Gecode (C++) program nonogram solving the P200 problem:
$ time nonogram -solutions 0 9
# ....
Initial
        propagators:  50
        branchings:   25

Summary
        runtime:      1.342 (1342.926000 ms)
        solutions:    1
        propagations: 35728
        nodes:        1409
        failures:     704
        peak depth:   25
        peak memory:  1027 KB
nonogram -solutions 0 9  1,45s user 0,06s system 99% cpu 1,517 total
It seems that the Gecode/FlatZinc version compares quite good.

For completion, here is the time for generating the automata of the P200 problem using the Perl program:
$ time perl make_nonogram_automata.pl nonogram_p200.dzn 1 > nonogram_p200_aut.dzn
0,20s user 0,02s system 96% cpu 0,233 total

Model and problem instances

Below are the problem instances as MiniZinc data file (.dzn), all the Nonogram problems listed on My Comet page, and some more. For each instance there are two variants: the "normal" version (which is the input file of the transformation) called "nonogram_name.dzn", and the generated automata version, called "nonogram_name_aut.mzn". It is the latter version ("_aut") that is used with nonogram_regular.mzn.

The program for converting to automata

As noted above, the Perl program make_nonogram_automata.pl converts a Nonogram problem instannce in "normal" pattern (clue) format to a format using automata.

The requirement of the indata file is semi-strict: the names must be the one in the example below, and each patterns must be on a separate line. The program use regular expressions to extract the information and can handle some variants in the format. The result is printed to standard output.
%% This is the problem instance of 'Hen', in "normal" pattern format.
%% Comments is keeped as they are
rows = 9;
row_rule_len = 2;
row_rules = array2d(1..rows, 1..row_rule_len,
       [0,3, 
        2,1, 
        3,2, 
        2,2, 
        0,6, 
        1,5, 
        0,6, 
        0,1, 
        0,2]);

   cols = 8;
   col_rule_len = 2;
   col_rules = array2d(1..cols, 1..col_rule_len,
       [1,2,
        3,1, 
        1,5, 
        7,1, 
        0,5, 
        0,3, 
        0,4, 
        0,3]);
To run the program:
$ perl make_nonogram_automata.pl nonogram_hen.dzn 1 > nonogram_hen_aut.dzn
The second parameter parameter 1 gives some more debugging info. The result is nonogram_hen_aut.dzn.

Minor note: For easy of debugging and further developments I decided to keep the 1-based version of arrays from the Comet model (Perl is 0-based) which made the code somewhat uglier.

September 05, 2009

Comet version 2.0 released

Comet version 2.0 has been released! That's great news.

Version 2.0 can be downloaded from Dynadec's Download page.

Here are the improvements in version 2.0 compared to version 1.2.
This release has the following new features [with bug tracking id where applicable]:
Major additions:

    * The SCIP MIP solver is now included (See license agreement for details)
    * Java API wrapper around the C++ API using Java Native Interface
    * Global Constraints for Rostering (stretch and regular) and Soft Global Constraints 
      (atLeastNValue, softCardinality, softAtMost, softAtLeast)

Other improvements:

    * Directory browsing support [#286]
    * Equality testing between ranges [#285]
    * Added getCPSolver(expr{int}) [#294]
    * Removed debugging printouts from C++ interface [#305]
    * Added inputFloatArrayArray to the C++ interface [#261]
    * Added support for arrays of ranges [#269]
    * Added changes() event to var{float} [#214]
    * Added access (by copy) to the set of a trail{set} [#196]
    * Added events on var{float} [#208]
    * Added clear method on VisualTextTable (qtvisual) [#310]
    * Improved zooming in the VisualDrawingBoard (qtvisual)
    * Additions to the Tutorial:
          o introduction to the Comparable interface,
          o trigonometric functions,
          o a section with an example on user defined reified constraints,
          o list of methods available for incremental variables.

Included from the 2.0 Beta release
Major additions:

    * New XML library (cotxml).
    * New visualization library (qtvisual) using the Qt toolkit on all platforms
    * New graphical debugger (-gqt command line option) using the Qt 
      library on all platforms
    * New support for external plugins
    * New Comet language documentation with code samples

Other improvements:

    * JIT level 2 is now the default [#259]
    * New quiet mode with -q switch [#229]
    * Addition functionality in FloatExpr [#233]
    * Improved support for normalization and large domains [#236]
    * Added support for Solver::getSolution() with satisfaction problems. [#146]
    * Added a "Stop" button to the debugger to interrupt running programs. [#186]
    * Added support for an array of sets of strings [#194]
    * Added support for hexadecimal constants. [#217]
    * Added support for constraint handles from expressions [#203]
    * Added string comparison method [#235]
    * Improved scalability in linear expressions in CP [#251]
    * Added bounds checking on individual indices of matrices [#271]
    * Added events to CP float variables [#208]
    * Added multiknapsackWithPrecedences constraint in CP

Some comments

Comet tutorial
In Comet version 2.0-Beta released I was excited about the Comet tutorial. I have now read it (the Beta version). It is a great work that explains very well in detail (and with many examples) the three different modeling paradigms of Comet: constraint programming, constraint-based local search, and mathematical programming.

My Comet models
I have also changed some of my Comet models so they run with version 2.0:
  • nonogram_regular.co : There is now a built in regular constraint, but I'm still using my own home-brewed which is renamed to myregular. (I have to test the model using the built-in constraint. Update: Which I know have done, see below.)
  • Some of the models had the last element in a list followed by a , which is not supported any more.
Update: I have also added some models which use some of the new functionality in version 2.0:
  • steiner_sets.co that use variable sets, i.e. var{set{int}}.
  • least_diff_gui.co, my standard problem Least diff problem with animation of the solution (and the search tree) using the new qtvisual library.
  • diet_gui.co: simple Diet problem with animation of the solution (and search tree) using the new qtvisual library.
  • debruijn_gui.co, de Bruijn sequence. As debruijn.co with animation of the solution (and the search tree) using the new qtvisual library.
  • nonogram_automaton.co: A version of nonogram_regular.co (which used my home-brewn version of regular constraint), using the new built-in regular constraint and Automaton.

September 04, 2009

The MiniZinc Wiki

The MiniZinc Wiki in brand new and includes (right now) for example: I have great hopes for the MiniZinc tutorial ("a work in progress") which now includes some commented models. Hopefully this will expand into a full tutorial of MiniZinc.

Worth of notice is also the SVN repository of MiniZinc examples: http://www.g12.cs.mu.oz.au/mzn. From the README file:
This subversion repository can be read and written by anyone in the constraint programming community who wishes to contribute MiniZinc models to the public domain.