May 12, 2013

Program for SweConsNet Workshop 2013 (Lund, 27 May 2013)

Here is the program for The 12th Workshop of the Network of Sweden-based researchers and practitioners of Constraint programming:
SweConsNet is the Network for Sweden-based researchers and practitioners of Constraint programming.

Following the previous successful workshops, we would like to announce the 12th SweConsNet workshop, which will take place in Lund, Sweden on May 27th 2013. The purpose of this workshop is to learn about ongoing research in constraint programming, as well as existing projects and products. We will also discuss the further development of the network, such as a possible widening to other Nordic countries.

The workshop is open to everybody interested in the theory and practice of constraint programming, whether based in Sweden or elsewhere. The scope of the workshop spans all areas of Constraint Programming, and is open to presentations and discussions addressing topics related to both theory and application.

Please forward a link of this page to people who might be interested but are not yet on the SweConsNet mailing list. They can subscribe to it by sending a message to Justin.Pearson [at] it.uu.se.

We hope for your participation, and highly encourage you to submit a proposal for a presentation of your ongoing work, recent results, or of a relevant discussion topic. There are no paper submissions, reviews, or proceedings, hence recent conference/journal papers may also be presented.

To register for partcipation in the registration form no later than May 22. The workshop does not have a registration fee.

Program

TimeContent
09.30Registration and coffee
10.00

Jean-Noël Monette (Uppsala University)
Towards solver-independent propagators

We present an extension to indexicals to describe propagators for global constraints. The resulting language is compiled into actual propagators for different solvers, and is solver-independent. In addition, we show how this high-level description eases the proof of propagator properties, such as correctness and monotonicity. Experimental results show that propagators compiled from their indexical descriptions are sometimes not significantly slower than built-in propagators of Gecode. Therefore, our language can be used for the rapid prototyping of new global constraints

10.40

Mats Carlsson (SICS) (joint work with Nicolas Beldiceanu & Aranud Letort)
Scalable Scheduling Constraints

The topic of this talk is synchronized sweep-based filtering algorithms for resource and precedence constraints that are common in scheduling problems.  We first describe a sweep-based implementation of the time-tabling method for "cumulative". Step by step, we then extend this algorithm to handle colored resources, multiple resources, and precedences.  We also derive from the filtering algorithm a greedy assignment algorithm, which is useful for very large scale problems where normal tree search would run out of memory.

11.20

Mehmet A. Arslan (LTH)
Instruction Selection and Scheduling for DSP Kernels on Custom Architectures

As custom architectures become more and more common for DSP applications, instruction selection and scheduling for such applications and architectures become important topics. In this paper, we explore the effects of defining the problem of finding an optimal instruction selection and scheduling as a constraint satisfaction problem (CSP). We incorporate methods based on sub-graph isomorphism and global constraints designed for scheduling. We experiment using several media applications on a custom architecture, a generic VLIW architecture and a RISC architecture, all three with several cores. Our results show that defining the problem with constraints gives flexibility in modeling, while state-of-the-art constraint solvers enable optimal solutions for large problems, hinting a new method for code generation. 

12.00LUNCH
13.00

Kim-Anh Tran (SICS)
Investigation of Implied Constraints in a Constraint-Based Compiler Back-end

Adding implied constraints addressing register allocation and instruction scheduling to the constraint model of a compiler back-end can be crucial to the performance of the code generator. In the hope of cutting down the search effort, implied constraints are investigated, implemented and evaluated. The talk will cover current findings of a master thesis on a set of implied constraints and give an insight into their actual impact on the code generation problem.

13.40

Håkan Kjellerstrand
What I like about Constraint Programming

This is a presentation about fascinating features in Constraint Programming: those I personally find very appealing and/or unique (e.g. compared to other programming paradigms/systems), especially regarding the modeling aspect.

14.20

Björn Regnell (LTH)
A Scala DSL for Constraint-based Requirement Engeineering

Software Requirements Engineering (RE) includes the challenging activities of release planning and prioritization, which both are suitable to be tackled by constraint solving. However, there is a need for integrating the representation of software requirements with the representation of constraints in a way that is easy to use by practitioners. This talk aims to interactively discuss what types of constraints are essential in this domain and present and invite feedback on a prototype tool that provides a Scala-internal DSL for Constraint-based RE, wrapping the JaCoP solver.

15.00Coffee break
15.30

Krzysztof Kuchcinski (LTH) 
Mapping Streaming Application into MPSoc

16.10Workshop closure

May 06, 2013

CP-2013 Workshops

The Workshops for CP-2013 (Uppsala, 16 September 2013) has been published. From the Workshops page:

The following workshops will take place before the main conference on September 16.

WCB13: Constraint Based Methods for Bioinformatics

WCB'13 is the 9-th of a series of consecutive Workshop on Constraint Based Methods for Bioinformatics. The topics of interest are all those concerning bioinformatics and constraints and related techniques.
workshop homepage

TRICS13: Techniques foR Implementing Constraint programming Systems

Constraint programming systems are software systems that support the modeling and solving of problems using constraint programming. Such systems include constraint programming libraries and runtime systems for constraint programming languages. This workshop, the fourth in the series, will focus on implementation issues of such systems.
workshop homepage

CSP-SAT: 3rd International Workshop on the Cross-Fertilization between CSP and SAT

Constraint Satisfaction Problems (CSP’s) and Boolean Satisfiability Problems (SAT) have much in common. However, they also differ in many important aspects, which result in major differences in solution techniques. This workshop is designed as a venue for bridging the gap and for cross-fertilization between the two communities.

CP Solvers: Modeling, Applications, Integration, and Standardization

The objective of this workshop is to get an industrial overview of currently available CP solvers and their use in real-world applications. The focus of the workshop will be not on implementation but rather on modeling, applications, integration, and standardization. Such an overview will fill a gap in the program of recent CP conferences and will allow CP developers and researchers to share the most recent experience of the actual use of different CP-based tools.
workshop homepage

Workshop on Optimization for Smart Cities

Policy makers who run the complex network of diverse people, expected services and aging infrastructure are on a constant search for more efficient ways to analyse data, anticipate problems and coordinate resources in their cities. This workshop has the purpose of bringing together scholars and practitioners that work on the solution of problems related to the improvement of the quality of life and the use of resources in cities, to make cities smarter.
workshop homepage

COSpeL: Domain Specific Languages in Combinatorial Optimization

Domain Specific Languages (DSLs) are programming languages or libraries developed to handle specific tasks. The aim of COSpeL is to bring together people interested in the development and use of DSLs in the context of combinatorial optimization.
workshop homepage

ModRef: Constraint Modelling and Reformulation

This workshop covers modelling and reformulation techniques that make constraint programming more accessible and easier to use, widening the use of CP technology.
workshop homepage

As mentioned earlier, I have a special interest in the CP Solvers: Modeling, Applications, Integration, and Standardization Workshop

April 25, 2013

CP-2013 CP Solver Workshop: Survey of CP Solvers

An addendum to CP-2013 Workshop "CP Solvers: Modeling, Applications, Integration, and Standardization" (Uppsala, Sweden):
If you an author of a CP solver, we ask you to fill out the following questionnaire (even if you do not plan to submit a presentation or attend the workshop). We plan to present a summary of all CP Solvers at this website before the start of the conference.
And here is the link to the workshop page: Workshop "CP Solvers: Modeling, Applications, Integration, and Standardization".

April 23, 2013

CP-2013 Workshop "CP Solvers: Modeling, Applications, Integration, and Standardization" (Uppsala, Sweden)

I'm very happy to announce the CP-2013 Workshop "CP Solvers: Modeling, Applications, Integration, and Standardization":
To be held at the 19th International Conference on the Principles and Practice of Constraint Programming (http://cp2013.a4cp.org/) in Uppsala, Sweden on Monday September 16, 2013.

Objectives and Scope
The objective of this workshop is to get an industrial overview of currently available CP solvers and their use in real-world applications. The focus of the workshop will be not on implementation but rather on modeling, applications, integration, and standardization. Such an overview will fill a gap in the program of recent CP conferences and will allow CP developers and researchers to share the most recent experience of the actual use of different CP-based tools.

We invite authors of all commercial and open source CP solvers to submit their presentations that should include (but not be limited to) the following topics:

  • Demonstration of modeling facilities using a commonly known problem from the CSPLib
  • Implementation programming languages and why they were selected
  • Covered variable types, global constraints, and search algorithms
  • Integration with LP/MIP/SAT tools
  • Integration with business rules, predictive analytics, and other decision making techniques
  • Real-world use: positive and negative experience
  • Standardization and future plans
If you an author of a CP solver, we ask you to fill out the following questionnaire (even if you do not plan to submit a presentation or attend the workshop). We plan to present a summary of all CP Solvers at this website before the start of the conference.

We also welcome application developers and researchers who use different CP tools and who are willing to share their practical experience.

A special focus will be on CP standardization efforts including:

  • Development of CP APIs for different programming environments
  • CP XML for interchange of constraint satisfaction/optimization problems
  • CP design patterns
  • Libraries of commonly used constraints
  • Collections of constraint satisfaction and optimization problems.

An expert panel discussion will be held at the end of this one-day workshop.

We hope that the workshop will help to improve communication between different CP vendors, between solver developers and their users, and will ultimately encourage a wider use of CP technology as a key component of the modern decision making applications.

Target Audience

  • Developers and users of different CP solvers
  • Business application developers who want to incorporate CP-based tools into their decision support systems
  • CP researchers.

Schedule
[To be defined]

Important Dates

  • Sunday, June 16 Presentation title and abstract submission
  • Tuesday, July 16 Acceptance notification
  • Friday, August 16 Complete presentation submission
  • Monday, September 16 Workshop

Organizing Committee

• Jacob Feldman, OpenRules, Monroe, NJ, USA jacobfeldman@openrules.com
• Helmut Simonis, 4C, Cork, Ireland h.simonis@4c.ucc.ie
• Hakan Kjellerstrand, Independent Researcher, Malmo, Sweden hakank@gmail.com

Submission
All abstracts and presentations must be submitted in PDF format using EasyChair. All accepted presentations will be made publicly available of the workshop’s website. At least one author of any accepted presentation must attend the event. An accepted presentation will be withdrawn if no such participation is secured with the payment of the workshop dues.

Please note that we invite authors of all CP solvers written using any languages to make brief presentations of their tools.

This is exciting, not only for the workshop itself (which is about my favorite areas in CP), but also because I'm a co-organizer (an honourable task). This will be very interesting. I hope to see you there!

April 22, 2013

SweConsNet Workshop 2013 - Second call for presentations and participation

Second call for presentations and participation: The 12th workshop of SweConsNet, the Network for Sweden-based researchers and practitioners of Constraint programming, Hosted at Lund University, Lund, Sweden, May 27th, 2013.
The 12th Workshop of the Network of Sweden-based researchers and practitioners of Constraint programming

SweConsNet is the Network for Sweden-based researchers and practitioners of Constraint programming.

Following the previous successful workshops, we would like to announce the 12th SweConsNet workshop, which will take place in Lund, Sweden on May 27th 2013. The purpose of this workshop is to learn about ongoing research in constraint programming, as well as existing projects and products. We will also discuss the further development of the network, such as a possible widening to other Nordic countries.

The workshop is open to everybody interested in the theory and practice of constraint programming, whether based in Sweden or elsewhere. The scope of the workshop spans all areas of Constraint Programming, and is open to presentations and discussions addressing topics related to both theory and application.

Please forward a link of this page to people who might be interested but are not yet on the SweConsNet mailing list. They can subscribe to it by sending a message to Justin.Pearson [at] it.uu.se.

We hope for your participation, and highly encourage you to submit a proposal for a presentation of your ongoing work, recent results, or of a relevant discussion topic. There are no paper submissions, reviews, or proceedings, hence recent conference/journal papers may also be presented.

To register, please fill your data in the registration form. If you want to propose a presentation, please send also the title and the abstract of your talk. In order to facilitate organization, please notify us of your intention to participate as soon as possible, and at the latest before May 10th, 2013. The workshop does not have a registration fee.

In the program so far

Participants will be presented continously

1. Jean-Noël Monette (Uppsala University): Towards solver-independent propagators

2. Håkan Kjellerstrand: What I (still) like about Constraint Programming

3. Mats Carlsson (SICS), TBD.

4. Christian Schulte (KTH), TBD.

5. Björn Regnell (LTH),A Scala DSL for Constraint-based Requirement Engeineering

6. Mehmet A. Arslan (LTH), Instructions Selection and Scheduling for DSP Kernels on Custom Architectures.
I just registered my own talk: What I (still) like about Constraint Programming. with the Presentation abstract:
This is a presentation about fascinating features in Constraint Programming: those I personally find very appealing and/or unique (e.g. compared to other programming paradigms/systems), especially regarding the modeling aspect.
I guess that many/most of the attendants know these "fascinating features" already, but all might not agree (I hope) that they are as important (or fascinating) as I find them.

April 11, 2013

The MiniZinc Challenge 2013 and other MiniZinc news

Here are some news from the G12 MiniZinc world.

MiniZinc main page: www.minizinc.org

The MiniZinc main page has changed to www.minizinc.org.

MiniZinc challenge

From MiniZinc Challenge 2013:
The aim of the MiniZinc Challenge is to start to compare various constraint solving technology on the same problems sets. The focus is on finite domain propagation solvers. An auxiliary aim is to build up a library of interesting problem models, which can be used to compare solvers and solving technologies.

Entrants to the challenge provide a FlatZinc solver and global constraint definitions specialized for their solver. Each solver is run on 100 MiniZinc model instances. We run the translator mzn2fzn on the MiniZinc model and instance using the provided global constraint definitions to create a FlatZinc file. The FlatZinc file is input to the provided solver. Points are awarded for solving problems, speed of solution, and goodness of solutions (for optimization problems).

Registration opens: Wed, 1 May 2013.
Problem submission deadline: Fri, 14 June 2013.
Initial submission round begins: Mon, 1 July 2013.
Initial submission round ends: Fri, 19 July 2013.
Final submissions: Fri, 2 August 2013.
Announcement of results at CP2013: 17 - 20 September 2013.


For details of the competition see:

http://www.minizinc.org/challenge2013/challenge.html

Note that the scoring system has slightly changed this year, so that solvers that obtain indistiguishable results in quality of solution split the points inversely proportional to the time taken

To register for the challenge please email

mzn-challenge@minizinc.org

Here is the Call for Problem Submission:
The MiniZinc Challenge is an annual solver competition in the Constraint Programming (CP) community held before the International Conference on Principles and Practice of Constraint Programming. The MiniZinc Challenge 2013 is seeking interesting problem sets on which various constraint solving technologies should be compared on this year. Everyone is allowed to submit problems regardless of whether they are an entrant in the challenge.

Important dates and deadlines:

Problem submission open: now
Problem submission deadline: Fri, 14 June 2013

Problem submission

Send an email with the subject line “[MZNC13] benchmark” to mzn-challenge 'at' minizinc.org

There are no restrictions on the kind of problems, but ideally they should be of interesting nature such as practice-related problems and puzzles etc. Problem submissions with real-world instances are welcome warmly. Models for the 2013 challenge can only use integer and Boolean variables.

The problem submitter provides a MiniZinc model of the problem and 20 instances ranging from easy-to-solve to hard-to-solve for an “ordinary” CP system. It is strongly encouraged to make use of the global constraint definitions provided in the MiniZinc 1.6 distribution. Please, follow the links below for submission instructions and requirements.
MiniZinc Challenge 2013
Also see: MiniZinc Challenge Medals 2008-2012

MiniZinc forum

Also just released is The MiniZinc forums with three forums:
  • Beginners: All beginner-level questions about MiniZinc.
  • Users: General discussion about MiniZinc. For beginners' questions please use the dedicated Beginners' Forum.
  • Developers: Discussions about developing the MiniZinc system and solvers that interface with MiniZinc.

March 14, 2013

Gecode version 4.0.0 released

Gecode version 4.0.0 has been released. Congrats to the developers!

From the Changelog:
Changes in Version 4.0.0 (2013-03-14)

This release adds a multitude of new features, fixes many bugs, and offers a number of performance improvements. There are too many major improvements to even summarize them here all, so here are just some highlights: LDSB as automatic symmetry breaking during search; restart-based search; complete redesign and reimplementation of branching enhancing the expressiveness massively (AFC with decay, activity, user-defined variable and value selection, tie-break control, better randomization, ...); half-reification; addition of floating point constraints.

It is recommended to read the new Chapter in MPG on branching as the changes are substantial and require you to change your programs, see also the full list of changes below.

As the interfaces has changed, please consult How to Change to Gecode 4.0.0.

  • Kernel
    • Additions
      • The random seeds for variable and value branching options can now be initialized from a hardware random number generator (see MPG for details). (minor)
      • All ArgArrays now accept STL vectors and input iterators for construction. (minor)
      • The kernel now can record the activity of variables. The activity of a variable is defined as how often the domain of a variable has been pruned during search. For details, see "Modeling and Programming with Gecode". (major)
    • Other changes
      • The default constrain() function for best-solution search now does by default nothing (it used to throw an exception). (minor)
      • The entire infrastructure for variable-value branchers has been reimplemented from scratch. The new design makes a much better compromise between code size, efficiency, and expressiveness: the efficiency is about the same (for examples with no propagation and just branching one can note a slowdown of 2-4%) while code size shrinks drastically (the overall code size for integer variables shrinks by 20%) and the architecture is much more expressive (in particular, it supports tie-break limits, see MPG). (major)
      • Throw exception when the user-defined copy constructor of a class that inherits from Space does not call the Space copy constructor. (minor)
    • Performance improvements
      • Fixed a bug in the main memory allocation routine: now heap block sizes are decreased dynamically as they should be. Also changed the memory configuration parameters as explained in: Zandra Norman, Memory Management for Gecode. KTH Royal Institute of Technology, Sweden, Bachelor thesis, TRITA-ICT-EX-2012:143, 2012. (major, thanks to Zandra Norman)
  • Search engines
    • Additions
      • Added support for restart-based search, see MPG for details. (major)
    • Other changes
      • Variable selection for branching used the quotient of size divided by degree, accumulated failure count, or activity. They now use the inverse. That is, for example, it is not any longer INT_VAR_SIZE_DEGREE_MIN() but INT_VAR_DEGREE_SIZE_MAX() (that is, largest degree divided by size). (major) That looks like an annoying change but is in fact essential: the strategies using accumulated failure count and activity now could have run into division by zero issues. And just changing the implementation is not good enough because the values of these measures can now be exposed during tie-breaking.
      • The restart best solution search engine has been removed (it is subsumed by the new restart-based meta search engine RBS). (major)
    • Performance improvements
      • The search engines now do not allocate memory on the search stack for the rightmost branch of each node. This means that the search tree depth is now computed differently. It now represents the actual peak depth required at any one time, taking into account that rightmost branches reuse the stack entry of their parents. (minor)
  • Finite domain integers
    • Additions
      • Gecode now supports Lightweight Dynamic Symmetry Breaking (LDSB), see MPG for details. (major , contributed by Christopher Mears)
      • Added value selection strategies for branching INT_VAL_NEAR_MIN(), INT_VAL_NEAR_MAX(), INT_VAL_NEAR_INC(), and INT_VAL_NEAR_DEC(). They can take a previous assignment to the variables to branch on and try to choose values which are near (see MPG for details). (major, thanks to Manuel Loth)
      • Added domain constraint that constrains a variable (or an array) according to the domain of another variable. (minor)
      • Added variants of dom that copy the domain from one variable to another. (minor)
      • The nooverlap constraint now allows sharing of unassigned variables in its argument arrays. (minor)
      • Added half-reification for reified constraints (see Modeling and Programming with Gecode for details). (major)
      • Added pow and nroot constraints. (major)
      • The binpacking constraint now also accepts items of size zero. (minor, thanks to Kathrin Dannmann, Roberto Castañeda Lozano)
      • Added activity-based branching strategies for integer and Boolean variables: INT_VAR_ACTIVITY_MIN, INT_VAR_ACTIVITY_MAX, INT_VAR_ACTIVITY_SIZE__MIN, INT_VAR_ACTIVITY_SIZE_MAX. For details, see "Modeling and Programming with Gecode". (major)
    • Other changes
      • The coefficients for linear constraints are now divided by their greatest common divisor. That means that some equations can be handled now that previously threw an OutOfLimits exception, and some equations can be handled with the more efficient integer precision propagators that previously required double precision. (minor)
      • Generalized definition of no-overlap propagators for better reuse. (minor, thanks to Roberto Castañeda Lozano)
      • The interface for branching on integer and Boolean variables has changed considerably (supporting user-defined variable and value selection, tie-break limit functions, handlers to created branchers, and more). In order to change, you have to add () to all variants of INT_VAR, INT_VAL, and INT_ASSIGN. For example, INT_VAR_SIZE_MIN becomes the function call INT_VAR_SIZE_MIN() and INT_VAL_MIN_MIN becomes the function call INT_VAL_MIN_MIN(). Some of these functions expect additional arguments and can take also optional arguments (this replaces the VarBranchOptions and ValBranchOptions). Please read the new "Branching" chapter in MPG. (major)
      • Respect IntConLevel argument for reified linear constraints with a single integer variable. (minor)
    • Bug fixes
      • Fixed precede constraint with less than two values. (minor, thanks to Roberto Castañeda Lozano)
      • Fixed a bug where bounds consistent distinct reported subsumption instead of failure in certain cases. (major, thanks to Lin Yong)
      • Fixed potential rounding issues in sqr and sqrt constraints. (minor)
      • Fixed copying of tuple sets in extensional constraints and IntSets in sequence constraints (could lead to crashes when using parallel search). (major, thanks to Manuel Baclet)
      • Added missing propagation for nary min/max constraint. (minor, thanks to Jean-Noël Monette)
      • Make extensional constraints work with empty tuple sets. (minor, thanks to Peter Nightingale)
      • Fix count (global cardinality constraint) for multiple occurrences of the same value in the cover array. (minor, thanks to Peter Nightingale)
    • Performance improvements
      • Arithmetic, linear, and cumulative constraints now resort to internal operations using "long long int" rather than "double". This improves performance but also extends the range over integer coefficients that can be handled by linear constraints. (major)
  • Finite integer sets
    • Additions
      • Gecode now supports Lightweight Dynamic Symmetry Breaking (LDSB), see MPG for details. (major , contributed by Christopher Mears)
      • Added domain constraint that constrains a variable (or an array) according to the domain of another variable. (minor)
      • Added domain constraints for arrays of set variables. (minor)
      • Added half-reification for reified constraints (see Modeling and Programming with Gecode for details). (major)
      • Added activity-based branching strategies for set variables: SET_VAR_ACTIVITY_MIN, SET_VAR_ACTIVITY_MAX, SET_VAR_ACTIVITY_SIZE_MIN, SET_VAR_ACTIVITY_SIZE_MAX. For details, see "Modeling and Programming with Gecode". (major)
      • Added channeling constraint between arrays of set variables. (major , contributed by Denys Duchier)
    • Other changes
      • The interface for branching on integer and Boolean variables has changed considerably (supporting user-defined variable and value selection, tie-break limit functions, handlers to created branchers, and more). In order to change, you have to add () to all variants of SET_VAR, SET_VAL, and SET_ASSIGN. For example, SET_VAR_SIZE_MIN becomes the function call SET_VAR_SIZE_MIN() and SET_VAL_MIN_INC becomes the function call SET_VAL_MIN_INC(). Some of these functions expect additional arguments and can take also optional arguments (this replaces the VarBranchOptions and ValBranchOptions). Please read the new "Branching" chapter in MPG. (major)
    • Bug fixes
      • Fixed precede constraint with less than two values. (minor, thanks to Roberto Castañeda Lozano)
  • Floats
    • Additions
      • Added support for float variables. (major , contributed by Vincent Barichard)
  • Minimal modeling support
    • Additions
      • Added pow and nroot expressions for integer variables. (minor)
    • Other changes
      • Made implementations of MiniModel expressions private, so that the MiniModel headers do not have to include propagator headers like gecode/int/linear.hh any longer. (minor)
  • Script commandline driver
    • Additions
      • Added commandline options to control restart-based search, see MPG for details. (major)
      • Decay values can now be passed on the command line using the switch -decay. (minor)
      • Added options -file-sol and -file-stat for writing solutions and statistics to arbitrary files and streams. (minor, thanks to Andrea Pretto)
      • The command line -print-last configures whether only the last solution found is printed. (minor, thanks to Josef Eisl)
    • Other changes
      • Boolean options (BoolOption) can now be given a false or true argument and hence are in-line with all other option types. (minor)
  • Range and value iterators
    • Documentation fixes
      • Clarified for several iterators that when using the assignment operator both iterators must be allocated from the very same region. (minor)
  • Support algorithms and datastructures
    • Bug fixes
      • Fixed a concurrency problem that caused an exception to be thrown at the end of a multi-threaded search on some platforms. (minor)
      • Fixed a bug in the allocation of very large bitsets. (minor, thanks to Max Ostrowski)
  • Example scripts
    • Additions
      • New example: Colored matrix without monochromatic rectangles. (minor)
  • Gist
    • Additions
      • Added option to invoke move cursors during the automatic search. (minor)
    • Other changes
      • Updated to compile with Qt version 5.0 (still works with Qt >= 4.3 as well). (minor)
  • Gecode/FlatZinc
    • Additions
      • Added support for more search annotations (defined in gecode.mzn), and for the restart and decay command line options. (minor)
      • Added native support for lex_less_bool and lex_lesseq_bool. (minor)
      • Gecode/FlatZinc now supports float constraints and variables. (major)
      • The FlatZinc interpreter now supports comparing of nodes in Gist. (major, thanks to Gabriel Hjort Blindell)
      • Added native support for the inverse_set constraint. (minor)
    • Other changes
      • Renamed the FlatZinc executable to fzn-gecode, to better distinguish it when installed alongside other FlatZinc implementations. (minor)
      • The FlatZinc interpreter no longer performs a complete search on variables annotated as var_is_introduced, but tries to extend a solution on the model variables to a solution that includes the introduced variables. Each solution on the model variables is therefore only reported once. (major)
    • Bug fixes
      • The mzn-gecode shell script now passes arguments correctly to the FlatZinc interpreter. (minor)
      • Removed spurious debug output for among constraint. (minor, thanks to Simon Ekvy)
      • Exported registry and helper functions so that users can add constraint handlers to the FlatZinc interpreter. (minor, thanks to Jean-Noël Monette)
  • General
    • Additions
      • Added CMake build script for Gecode (CMakeLists.txt). (minor, thanks to Victor Zverovich)
      • Variable selection using AFC now supports decay. Read more in MPG. (major)
    • Other changes
      • Compiles with MSVC 2012. (minor)
Also see:

March 10, 2013

A first look at B-Prolog

First, here's my B-Prolog page with a lot of CLP models.

B-Prolog is a Prolog implementation that, besides extensions such as CLP(FD), CLP(Set), and CLP(Bool), also shines with the following extensions: B-Prolog also has built in support for memoization (table) which make dynamic programming easier (see some examples here). It also has an almost seamless support for changing between CLP(FD), LP/MIP, and SAT solver.

However, here I have almost exclusively concentrated on the CLP(FD) extensions and with heavily use of foreach loops, list comprehensions, and arrays/matrices (since this is how I tend to think when modeling these kind of combinatorial problems). Most problems has been implemented in other C(L)P systems before, see Common constraint programming problems.

More info about B-Prolog

First model: SEND+MORE=MONEY

Model: send_more_money.pl

Let's start with one of the standard problems just to get a feeling for the syntax of B-Prolog
sendmore(Digits) :-
    Digits = [S,E,N,D,M,O,R,Y],
    Digits :: 0..9,
    alldifferent(Digits),
    S #> 0, M #> 0,
                 1000*S + 100*E + 10*N + D
    +            1000*M + 100*O + 10*R + E
    #= 10000*M + 1000*O + 100*N + 10*E + Y,       
    labeling(Digits).
This is no different from most CLP(FD) systems. Note that there is no need to load a specific clpfd module since everything is loaded already (and B-Prolog currently don't support modules).

Here's a short explanation:
  • Digits :: 0..9: This means that all the elements in the list Digits must be in the domain between 0..9.
  • The specific CLP(FD) operators starts with #, e.g. #= and #>.
  • labeling(Digits): starts the search of the solution.

N-Queens: introducing list comprehensions

Model: queens.pl

Tthis N-Queens model show more of the differences between B-Prolog and standard Prolog with CLP(FD) support, namely it's use of list comprehensions.
queens2(N, Q) :-
        length(Q, N),
        Q :: 1..N,
        Q2 @= [Q[I]+I : I in 1..N],
        Q3 @= [Q[I]-I : I in 1..N],
        alldifferent(Q),
        alldifferent(Q2),
        alldifferent(Q3),       
        labeling([ff],Q).
The extraction the two diagonals is done via list comprehensions (Q2 and Q3), i.e.
  Q2 @= [Q[I]+I : I in 1..N],
  alldifferent(Q2),
This works since the special operator V @= [....] extracts the elements Q[I] (note the use of array index here).

Here is a small benchmark using the above encoding (predicate queens2 in the file). queens/2 is the same as the above but use alldistinct instead of alldifferent:
Both take very long time for N=500, but is much faster for N=499 and N=501. As we see, using alldifferent is faster than using alldistinct. The latter use a stronger consistency checking, but that don't help in this encoding:
  For N=400:
    queens2/2: 0.62s 10 backtracks
    queens5/2: 0.71s 10 backtracks
    queens/2:  2.16s 1 backtrack
  For N=499:
    queens2/2: 0.76 1 backtracks
    queens5/2: 1.1s  1 backtracks
    queens/2:  4.168 0 backtracks
  For N=500: too slow 
  For N=501:
    queens5/2: 1.1s 1 backtracks
    queens2/2: 3.14s 1 backtrack
    queens/2:  3.524s 2 backtracks
  For N=1000:
    queens5/2: 8.9s 2 backtracks
    queens2/2: 24.2s 2 backtracks
    queens/2:  34.146s 0 backtracks

[I don't understand why N=500 is so hard when 499 and 501 is solved quite fast. No other CP solver/system I've tested show this behaviour.]

B-Prolog is not the only Prolog based system using foreach loops. See below for some discussion of the differences between B-Prolog and ECliPSe CLP's do-loop construct (also used in SICStus Prolog).

alphametic.pl: a fairly general alphametic solver

Model: alphametic.pl

Using list comprehensions, foreach loops and arrays makes it quite easy to implement a fairly general solver for this kind of alphametic problems. It's not completely general since it (still) use Prolog's feature of handling variables.
go :-
    L = [[_S,E,N,_D],[M,O,_R,E],[M,O,N,E,_Y]],
    alphametic(L, Base, Res),
    writeln(Res).

alphametic(L,Base, Vars) :- 
    reverse(L,Rev),
    Rev = [Last|Sums],

    term_variables(L, Vars),
    Vars :: 0..Base-1,

    alldifferent(Vars),
    Vals #= sum([Val : S in Sums,[Val],calc(S,Base,Val)]),
    calc(Last,Base,Vals),
    foreach(S in Sums,S[1]#>0),

    labeling([ff,split], Vars).

calc(X,Base,Y) :-
    length(X,Len),
    Y #= sum([X[I]*Base**(Len-I) : I in 1..Len]).
The main work here is done with term_variables/2 which extracts the variables used, the sum/1 which sums all the terms, and calc that is really a special case of scalar product.

Sudoku solver: more lists/arrays

Model: sudoku.pl

Here is a Sudoku solver in B-Prolog:
go :-
   time(solve(1)).

solve(ProblemName) :-
   problem(ProblemName, Board),
   print_board(Board),
   sudoku(3, Board),
   print_board(Board).

print_board(Board) :-
   N @= Board^length,
   foreach(I in 1..N, 
      (foreach(J in 1..N, [X],
         (X @= Board[I,J],
         (var(X) -> write('  _')
           ;
          format('  ~q', [X]))
         )),
      nl)),
    nl.

problem(1, [](
    [](_, _, 2, _, _, 5, _, 7, 9),
    [](1, _, 5, _, _, 3, _, _, _),
    [](_, _, _, _, _, _, 6, _, _),
    [](_, 1, _, 4, _, _, 9, _, _),
    [](_, 9, _, _, _, _, _, 8, _),
    [](_, _, 4, _, _, 9, _, 1, _),
    [](_, _, 9, _, _, _, _, _, _),
    [](_, _, _, 1, _, _, 3, _, 6),
    [](6, 8, _, 3, _, _, 4, _, _))).

alldifferent_matrix(Board) :-
   Rows @= Board^rows,
   foreach(Row in Rows, alldifferent(Row)),
   Columns @= Board^columns,
   foreach(Column in Columns, alldifferent(Column)).

sudoku(N, Board) :-
   N2 is N*N,
   array_to_list(Board,BoardVar),
   BoardVar :: 1..N2,

   alldifferent_matrix(Board),
   foreach(I in 1..N..N2, J in 1..N..N2, 
          [SubSquare],
          (SubSquare @= [Board[I+K,J+L] : 
                        K in 0..N-1, L in 0..N-1],
          alldifferent(SubSquare))
   ),
   labeling([ff,down], BoardVar).
One of the most interesting things here is the code for the sub squares (SubSquare): (SubSquare @= [Board[I+K,J+L] :
K in 0..N-1, L in 0..N-1]

Unlike most Prolog implementations, it works to access the entries in the matrix with I+K and J+L. However this works only when the indices (I, J, K, L) are ground integers. If any of the indices would be decision variables, then one have to use element/3 (or perhaps nth1/3) to obtain the same thing. See below for more about this.

Running this models yield the following result:
  _  _  2  _  _  5  _  7  9
  1  _  5  _  _  3  _  _  _
  _  _  _  _  _  _  6  _  _
  _  1  _  4  _  _  9  _  _
  _  9  _  _  _  _  _  8  _
  _  _  4  _  _  9  _  1  _
  _  _  9  _  _  _  _  _  _
  _  _  _  1  _  _  3  _  6
  6  8  _  3  _  _  4  _  _

  3  6  2  8  4  5  1  7  9
  1  7  5  9  6  3  2  4  8
  9  4  8  2  1  7  6  3  5
  7  1  3  4  5  8  9  6  2
  2  9  6  7  3  1  5  8  4
  8  5  4  6  2  9  7  1  3
  4  3  9  5  7  6  8  2  1
  5  2  7  1  8  4  3  9  6
  6  8  1  3  9  2  4  5  7
Time and backtracks: Since there is no built-in predicate in B-Prolog for getting both time and number of backtracks (failures etc), let's add this:
time2(Goal):-
   cputime(Start),
   statistics(backtracks, Backtracks1),
   call(Goal),
   statistics(backtracks, Backtracks2),
   cputime(End),
   T is (End-Start)/1000,
   Backtracks is Backtracks2 - Backtracks1,
   format('CPU time ~w seconds. Backtracks: ~d\n', [T, Backtracks]).
Running this on the command line:
 $ time bp -g "[sudoku], time2(solve(1)),halt"
writes the following after the solution, i.e. that it's a 0 backtrack problem.
CPU time 0.0 seconds. Backtracks: 0
In the model sudoku.pl there is a predicate go3/0 which runs all the 13 problem instances and shows the statistics (time and backtracks). The len:1 in the output is for ensuring that the solution is unique (a requirement on traditional Sudoku problems). This check caught two problem instances that was either typed in erroneously by me or by the source I got them from (and thus I removed these two problems from this model).
go3 :-
   foreach(P in 1..13,
      [L,Len],
      (writeln(problem:P),
      time2(findall(P,solve2(P),L)),
      length(L,Len),
      writeln(len:Len),
      (Len > 1 ->
         writeln('This has more than one solution!') 
        ; 
      true
      ), nl)).
The result is:
problem:1
CPU time 0.004 seconds. Backtracks: 0
len:1

....

problem:13
CPU time 0.04 seconds. Backtracks: 0
len:1

What you can - and cannot - do with list comprehensions

When using @= it works to get a list comprehension (provided that there's no problem with array access etc). If one want to use it directly in a (global) constraint, then the requirement is that it must be in an arithmetic context (I first missed that in the documentation).

The following works since sum/1 is a special function in an arithmetic context:
  Sum #= sum([X[I] : I in 1..N])
However, using comprehensions in global constraints such as alldifferent don't work since it's not in an arithmetic context:
  % this don't work
  alldifferent([X[I]+I : I in 1..N])
The following works (as we saw above in the N-Queens model) since we extract the elements to a list using @= before using it.
  % this works
  Q1 @= [X[I]+I : I in 1..N],
  alldifferent(Q1),
  % ...
As mentioned above, array indexing don't work when the indices are decision variables. Then one must use element/3 (or nth/3). See more about element below.

foreach loops

The foreach loop extension i B-Prolog is quite intuitive. They are a often easier to use than the do-loops in ECLiPSe CLP (and SICStus Prolog) since in B-Prolog one declare the local variables in the loop (i.e. "global by default"), whereas in ECLiPSe do-loops one declares the global variables to be used ("local by default") which perhaps is not as intuitive. Both these systems have helpful warnings where a local/global variable is used out of context.

Note that B-Prolog's foreach construct don't have all features found in ECLiPSe's do-loop so certain things might be easier to state in ECLiPSe CLP and SICStus Prolog than in B-Prolog.

In B-Prolog there is also support for accumulators via ac(Var, StartValue) (or ac1/2 which I have not used much), which collects the local variables in the loop to a global variable (here Var).

An example of a foreach loop which use ac is in photo_problem.pl
preferences(1, 7, [[1,5],
                   [1,6],
                   [2,1],
                   [2,5],
                   [4,6],
                   [4,3],
                   [7,4],
                   [7,3]]).

foreach([Pref1,Pref2] in Preferences,
        ac(Diffs,[]), [P1,P2,Diff],
        (
            element(Pref1,Positions,P1),
            element(Pref2,Positions,P2),
            Diff #= (abs(P1-P2) #= 1),
            Diffs^1 = [Diff|Diffs^0]
        )),
Here the Diff list collects the differences of the positions (from the local Diff variable). The local declarations [P1,P2,Diff] is needed here, otherwise they would be considered global variables in the model (with disastrous result).

Also note that the foreach loop handles the list of lists in Preferences, so the foreach is not limited to integer ranges that is shown in a couple of the other examples here.

More about foreach loops is found in the manual, section Declarative Loops and List Comprehensions.

new_array and lists

Creating an array (of "any" dimension) in B-Prolog is done with new_array(Var,Dimensions):
   N = 3,
   new_array(X,[N,N]),
where Dimensions is a list of the dimensions (of "any" size; I don't know if there is any limitations of the number of dimensions).

The result of new_array is an array structure such as
  | ?- new_array(X,[3,3])
  X = []([](_7a8,_7b0,_7b8),[](_7c8,_7d0,_7d8),[](_7e8,_7f0,_7f8))
Converting an array structure to a list is done with array_to_list(Array,List):
| ?- new_array(X,[3,3]), array_to_list(X,List)
X = []([](_8e0,_8e8,_8f0),[](_900,_908,_910),[](_920,_928,_930))
List = [_8e0,_8e8,_8f0,_900,_908,_910,_920,_928,_930]
Setting the domains for the variables in an array must be done via the converted list (i.e. not directly on the array structure):
   N = 3,
   new_array(X, [N,N]),
   array_to_list(X, Vars),
   Vars :: 1..N*N,
   % ...
After that conversion, one can freely use constraints on either the array structure (e.g. as a matrix) or on the list representation, such as alldifferent(Vars). This "dual representation" sometimes simplifies modeling much. Note that labeling must be done via the list representation, or by using term_variables/2.

Reifications: alldifferent_except_0

Model: alldifferent_except_0.pl

Using reifications (reasoning about satisfing constraints using boolean decision variables) is quite direct, using #= (equality), #=> (implication) and #<=> (equivalence). Here is an decomposition of the global constraint alldifferent_except_0.pl:
alldifferent_except_0(Xs) :-
   Len @= Xs^length,
   foreach(I in 1..Len, J in 1..Len,
      (I #\=J #/\ Xs[I] #\= 0 #/\ Xs[J] #\= 0)
       #=> 
      (Xs[I] #\= Xs[J])
     ).
One thing I noticed when playing with reifications was that foreach don't seems be in boolean context. Example: this don't work as I expected (or hoped), i.e. that if not all X[I] are larger than 0 then B is 0 (and vice versa):
  % don't work
  foreach(I in 1..N, X[I] #> 0) #<=> (B #= 1)

Table constraint

Model: hidato_table.pl

The table constraint is used in hidato_table.pl and is quite easy to use.

First, define the valid connections that can be used. This is - of course - done via a list comprehension:
Connections
   @= [(I1,J1,I2,J2) :
       I1 in 1..N, J1 in 1..N, 
       I2 in 1..N, J2 in 1..N,
       (abs(I1-I2) =< 1,
       abs(J1-J2) =< 1,
       (I1 \=I2; J1 \= J2)
       )],
Then place all the numbers 1..N*N in the grid where the places are restriced by the connections in Connections. Note that since we are using decision variables for the indices (I1,J1,I2,J2) of the grid (X), we cannot use array extraction. My solution of this is to use the XVar list (which we must have for the labeling anyway), and calculate the corresponding position in this list for each (I,J) postition in the grid.
XVar @= [X[I,J] : I in 1..N, J in 1..N],
XVar :: 1..N*N,

% ....

% place all integers from 1..N*N
alldifferent(XVar),
foreach(K in 1..(N*N)-1,
   [I1,J1,I2,J2,K2,Offset1,Offset2],
   [ac(AllConn,[]),ac(Offsets,[])],
   (
     K2 is K+1,
     [I1,J1,I2,J2] :: 1..N,
     % [(I1,J1,I2,J2)] in Connections,
     [Offset1,Offset2] :: 1..N*N,
     Offset1 #= (I1-1)*N+J1,
     element(Offset1,XVar,K),
     Offset2 #= (I2-1)*N+J2,
     element(Offset2,XVar,K2),
     AllConn^1 = [(I1,J1,I2,J2)|AllConn^0],
     Offsets^1 = [[Offset1,Offset2]|Offsets^0]
    )
   ),

% the table constraint
AllConn in Connections,
...
The table constraint is used by simply putting all the variables in a list of parenthesis structure (I1,J1,I2,J2) and then checking all these using AllConn in Connections.

Also, note that both AllConn (the collection of selected connections) as well as the offsets (collected in the Offsets list) is included in the labeling to get faster results.
% ...
term_variables([Offsets,XVar,AllConn],Vars),
labeling([ff],Vars),
% ...
In my experiments with this model, it seems to be faster to put Offsets before XVar and AllConn in the labeling.

This model is not blazingly fast, though it's much faster than the model without the table constraint (the model hidato.pl). For example, problem instance #6 takes 6.5 seconds without the table constraint, and 0.17 seconds with (both versions have 0 backtracks).

Note: B-Prolog also have a powerful built-in memoisation feature called table. Please don't confuse these two usages of "table".

Element

As usual, when porting models from my MiniZinc models, I got the most problem with the element constraint. (Porting to B-Prolog has not been the worst case in this matter, though.)

B-Prolog's support for arrays with decision variables is not as good as compared with the ECLiPSe CLP system, and both have quite a way to go before it's as nice as MiniZinc's and Comet's support (where element is encoded very natural). It's especially when using element in a matrix where I had to stop in my "porting flow" (often the port was quite "flowy") and then use element/nth1 constraints and often a few temporary variables.

When there are much matrices with decision variable indices, I tend to use these two predicates instead (and skipping B-Prolog's arrays):
matrix_element(X, I, J, Val) :-
   element(I, X, Row),
   element(J, Row, Val).
 
matrix(_, []) :- !.
matrix(L, [Dim|Dims]) :-
   length(L, Dim),
   foreach(X in L, matrix(X, Dims)).
(The latter predicate was suggested by Mats Carlsson when I implemented a lot of SICStus Prolog models some years ago.)

Here is an example in the stable marriage model (stable_marriage.pl).

In MiniZinc one can code element within decision variables like this (where both husband and wife are lists of decision variables). Here's a snippet from the MiniZinc model stable_marriage.mzn:
forall(m in 1..num_men) ( 
  husband[wife[m]] = m 
)
In B-Prolog, I use the following (using the same overall approach):
foreach(M in 1..NumMen,[WifeM,HusbandWifeM],
   (element(M,Wife,WifeM),
     element(WifeM,Husband,HusbandWifeM),
     HusbandWifeM #= M )),
Another example is the Five element problem (from Charles W. Trigg): five_elements.pl

The problem statement:
Charles W. Trigg, PI MU EPSILON JOURNAL, Valume 6, Fall 1977, Number 5
"""
From the following square array of the first 25 positive integers, choose five, no two of the same row or column, so that the maximum of the five elements is as small as possible.

2 13 16 11 23
15 1 9 7 10
14 12 21 24 8
3 25 22 18 4
20 19 6 5 17


Ensuring the unicity of rows and columns is simple:
foreach(I in 1..N, 
       (sum([X[I,J] : J in 1..N]) #= 1,
        sum([X[J,I] : J in 1..N]) #= 1
        ))
However, we also want to find the specific numbers in the matrix for which X[I,J] #= 1. The following way do not work:
% This don't work
foreach(J in 1..N, [I],ac(Is,[]),
   (I :: 1..N,
    1 #= X[I,J],
    Y[J] #= Matrix[I,J]
   ))
If we - still - want to use this matrix approach, then freeze/2 can be used. However, we then have to collect the I indices in an accumulator list Is to be used in the labeling:
% Find the specific row I for which X[I,J] is 1.
foreach(J in 1..N, [I],ac(Is,[]),
    (I :: 1..N,
    freeze(I, 1 #= X[I,J]),
    freeze(I, Y[J] #= Matrix[I,J]),
    Is^1 = [I|Is^0])
    ),

MaxY #= max(Y),

term_variables([XVar,Y,MaxY,Is], Vars),
minof(labeling([ff], Vars),MaxY),
labeling(Vars),
% ....
Using freeze/2 is not ideal, but it makes the code more intuitive than with a lot of element/3 or nth1/3, if that even work.

MIP/SAT

Model: coins_grid.pl
As mentioned in the introduction above, B-Prolog also have support for LP/MIP problems (using GLPK as the solver) and an interface to a SAT solver.

Here I just show the MIP solver by one of my standard problems for which CP solvers tend to be worse than MIP solvers, namely coins_grid.pl. The model also implements a CLP(FD) and a cp_solve.

Some differences between the other CLP(FD) models shown here:
  • The CP, MIP, and SAT solvers has a little different syntax than the CLP(FD) solver:
    • The numeric constraints use $= instead of #= (i.e. "$" instead of "#") to mark that it's a CLP constraint.
    • The labeling is different: cp_solve, lp_solve, ip_solve, and sat_solve.
  • There are just a few global constraint that is supported using this: $alldifferent and $element, and the usual arithmetic sum/1, min/1, max/1, min/2, max/2. The CLP(FD) solver has support for many more global constraints.
coins(N, C) :-
   % N = 10, % 31 the grid size
   % C = 6,  % 14, number of coins per row/column
   
   new_array(X, [N,N]),
   array_to_list(X, Vars),
   Vars :: 0..1,

   Sum $>= 0,
   foreach(I in 1..N, 
       (C $= sum([T : J in 1..N, [T], T @= X[I,J]]), % rows
        C $= sum([T : J in 1..N, [T], T @= X[J,I]]) % columns
       )),

   % quadratic horizontal distance
   Sum $= sum([
               T : I in 1..N, J in 1..N, [T],
               T @= (X[I,J] * abs(I-J)*abs(I-J))
              ]),

   ip_solve([min(Sum),ff,reverse_split], Vars),
   % cp_solve([min(Sum),ff,reverse_split], Vars),
   % sat_solve([min(Sum),ff,reverse_split], Vars),
   writeln(sum:Sum),
   pretty_print(X).
By changing ip_solve to cp_solve (or sat_solve) we use the CP solver (or SAT solver). This is quite nifty.

And as usual the MIP solver solves this problem immediately, whereas CP solvers tend to be much slower.

Things not tested or mentioned

Here are some other things that I have not mentioned above:
  • Action rules and events. These are the used to implement propagators and more effective constraints. However, I have not played with these much. Also, see Programming Constraint Propagators.
  • B-Prolog is not an open source project, i.e. the free distribution just contains the executable, documentation and examples. (This was a little unfortunately since then I had not opportunity to study certain features, e.g. how the global constraints where implemented in Action rules.) For individual, academic and non-commercial use, B-Prolog is free to use. There is commercial licenses where source code is included. See more here: Licenses.
  • And then there are other features that I have not mentioned. See the Manual for detailed descriptions about these.

Summary

I like B-Prolog, especially the nice support for list comprehensions, array access and foreach loops. They are a nodge neater than the one used in ECLiPSe CLP and SICStus Prolog, though not as good as in MiniZinc (or Comet).

It was quite easy to port my ECLiPSe and SICStus Prolog models to B-Prolog, mostly because these already used the do-loop constructs, and it was mostly easy to port directly from my MiniZinc models, except when using matrices with decision variables as indices. Right now I think that B-Prolog's approach is often neater to use than the other Prolog's, especially list comprehensions.

Picat

Finally, I must mention Picat (Predicates, Imperative, Constraints, Actors, and Tabling). Picat is a C(L)P language also created by B-Prolog's creator Neng-Fa Zhou (together with Jonathan Fruhman), which is inspired by Prolog (especially B-Prolog). From the Picat site:
Picat is a general-purpose hybrid language that incorporates many declarative language features for better productivity of software development, including explicit non-determinism, explicit unification, functions, constraints, and tabling. Picat also provides imperative language constructs for programming everyday things. The Picat system will be used for not only symbolic computations, such as knowledge engineering, NLP, and search problems, but also for scripting tasks for the Web, games, and mobile applications.

....

The Picat implementation will be based on the B-Prolog engine and the first version that has the basic functionality is expected to be released by May, 2013. The project is open to anybody and you are welcome to join, as a developer, a sponsor, a user, or a reviewer. Please contact picat@picat-lang.org .
This sounds very interesting, and I will definitely give it a try when it's released (and perhaps blog about it as well).

My B-Prolog models/programs

Here are my public B-Prolog encodings. As of writing it's over 200, most using CLP(FD), some use CLP(Set), and just a few are non-CP Prolog + foreach/list comprehension.

February 05, 2013

SweConsNet Workshop 2013 (Call for speakers)

The SweConsNet Workshop 2013 will take place in Lund, Sweden on May 27th 2013.

From the site:
The 12th Workshop of the Network of Sweden-based researchers and practitioners of Constraint programming

SweConsNet is the Network for Sweden-based researchers and practitioners of Constraint programming.

Following the previous successful workshops, we would like to announce the 12th SweConsNet workshop, which will take place in Lund, Sweden on May 27th 2013. The purpose of this workshop is to learn about ongoing research in constraint programming, as well as existing projects and products. We will also discuss the further development of the network, such as a possible widening to other Nordic countries.

The workshop is open to everybody interested in the theory and practice of constraint programming, whether based in Sweden or elsewhere. The scope of the workshop spans all areas of Constraint Programming, and is open to presentations and discussions addressing topics related to both theory and application.

...

We hope for your participation, and highly encourage you to submit a proposal for a presentation of your ongoing work, recent results, or of a relevant discussion topic. There are no paper submissions, reviews, or proceedings, hence recent conference/journal papers may also be presented.
Here's the first and preliminary program (the site will be updated continuously):
  • Jean-Noël Monette (Uppsala University): Towards solver-independent propagators
  • Håkan Kjellerstrand: What I like about Constraint Programming
  • Mats Carlsson (SICS), TBD.
  • Christian Schulte (KTH), TBD.
  • Krzysztof Kuchcinski (LTH), TBD.
Krzysztof Kuchcinski is the organizer this time.

My own talk will probably be titles What I (still) like about Constraint Programming - or on the same theme: Why I'm (still) fascinated by Constraint Programming. It will be a talk about things that is so great about CP; i.e. no ground breaking research stuff (unless ...).

Also see: SweConsNet.

January 23, 2013

CP2013: Organization and Call for Papers

The site of CP2013 (The 19th International Conference on Principles and Practice of Constraint Programming, September 16-20, 2013, Uppsala, Sweden) has been updated with the following:
  • Organization: now has information about the full program committees for both the technical and the application track.
  • Call for Workshop Proposals:
    The CP 2013 Workshop Chair invites proposals for the Workshops immediately preceding the main conference in Uppsala.

    The CP workshops offer an informal venue where participants are given the opportunity to present discuss and brainstorm on new ideas, technical topics, exciting new application areas and cross-fertilization with other domains. The forums are meant as a petri dish for new ideas and emerging topics in the field of constraint programming. The topics can overspread many areas ranging from modeling, tools, techniques, algorithms, methodology, discrete and continuous optimization as well as complete and incomplete methods. Relevant areas showcasing or contributing to CP such as cloud computing, cryptography, energy, sustainability, databases, machine learning or data mining — to name just a few — are all equally encouraged.

    All workshops will take place on September 16, 2013 at the site of the main conference. Workshops can follow a half-day or a full-day format. The details of the organization of each workshop are left to its organizers
  • Call for Tutorials:
    The CP 2013 Tutorial Chair invites proposals for tutorials in Uppsala.

    Tutorials are expected to give an in-depth presentation of emerging and exciting topics that are relevant to a broad swath of the constraint programming community. Past CP conferences featured tutorials on numeral CSPs, global constraints, languages, Disaster Management, Decision Diagrams and connection with mathematical programming. Topics currently at the fore-front of research activities with successes, major advances and significant impact are particularly welcome.

    The tutorials will take place during the main technical program.

December 03, 2012

Administratrivialities: Technorati claim

Sorry about this administrative post, but Technorati wants me to post this to claim this blog. Well, here is the code: NSQNSF9S9TMW

November 23, 2012

A first look at AIMMS+CP (AIMMS with Constraint Programming)

In the Summer of 2011 I had the opportunity to test an early beta version of AIMMS+CP (AIMMS with Constraint Programming), and then did a second test round in September 2012 (with a late beta version). Here are some of my comments of my experiences with AIMMS+CP during these tests. A little later, in October 2012, Paragon released version 13.1 to the public including AIMMS+CP.

My AIMMS+CP page links to both .aim files (which shows the textual representation of parameters, variables and constraints) and the .aimmspack file (a binary file containing the full model project including the GUI part and other settings). As usual I have implemented many of my "starting/learning" models to be able to compare them with other CP systems. I would like to thank especially Chris Kuip and Gertjan de Lange from Paragon for great support, suggestions and inspirations during these tests.

First a little about Paragon and their commercial product AIMMS, from the Overview:
AIMMS offers an all-round development environment for the creation of high-performance decision support and advanced planning applications to optimize strategic operations. It allows organizations to rapidly improve the quality, service, profitability, and responsiveness of their operations. The AIMMS development environment possesses a unique combination of advanced features and design tools, such as the graphical model explorer, which allow you to build and maintain complex decision support applications and advanced planning systems in a fraction of the time required by conventional programming tools.
One distinct feature of AIMMS is the integrated GUI where one both define the parameters, variable and constraints as well as the graphical input/output of the model. I should note that this is the first time in my CP experience that I've worked with this kind of tight integrated tool, which might explain some of the comments below.

AIMMS GUI tool was (and still is AFAIK) only for Windows, so I used VirtualBox under my Linux Ubuntu 12.04 when testing. Also, before the test, I have not used AIMMS at all.

Documentation, examples

There is a lot of documentations of how AIMMS work (PDF files available from the Help menu):
  • AIMMS Getting Started
  • AIMMS User's Guide
  • AIMMS Language Reference
  • AIMMS Optimization Modeling
  • AIMMS Function Reference
  • AIMMS Tutorial
  • etc
The documentation of the CP related features has been incorporated in these documents, especially AIMMS Language Reference, chapter 21 ("Constraint Programming") including a short introduction to CP and a discussion of the different variables types (Variable, Element Variable) used in CP modeling.

For a person that knows AIMMS well and also know how CP works, the documentation is probably enough. But for someone like me that didn't know AIMMS before or someone who know AIMMS but not CP, the documentation is a little thin, especially since the examples are quite advanced to get started. I missed some of the standard CP examples such as N-queens, Send More Money, Sudoku, etc and examples of the basic stuff, such as how handle single variables, comparisons etc. Hopefully my AIMMS+CP implementations might be of some help.

The documentation don't say much about the CP solver and what options it has (and what they mean); though the is some documentation available with the Help button for the options. It is great that there are good support for scheduling and the example models are interesting, but - again - too complicated to start learning from.

I should mention that I have not read the complete documentation of AIMMS. Instead I started to code in AIMMS almost directly. This might have been a bad decision since I got stumped a couple of times with some of AIMMS basic concepts.

I later realized that AIMMS Blog contains tips and documentation regarding certain AIMMS features.

Modeling in AIMMS

Here I will focus on the modeling part. I have actually done very little extra with the graphics: it's just a Solve button, input fields and output fields/tables, i.e. nothing fancy at all. The models that is distributed with AIMMS is, on the other hand, much more elaborated and tasty and shows a huge number of general different possibilities in AIMMS; though - as mentioned above - there are not many CP specific models. In part, I wrote some of the detailed comments below with a hope to help newcomers in AIMMS+CP.

Below I will try to explain CP modeling in AIMMS+CP as well as some personal comments during my tests. So, let's start with the standard example: SEND+MORE=MONEY (or perhaps Sudoku is more standard nowadays?).

A word of caution: These models are tested with a beta version of AIMMS+CP (albeit a late beta), so some constraints/features might have been changed in the current version.

SEND + MORE = MONEY: Some concepts

Model: SendMoreMoney2.aim

Compared to other CP systems, AIMMS use a little different concepts and approach when modeling, and here I will show this using the SEND+MORE=MONEY problem, where the object - of course - is to assign each letter to an integer so that the equation holds.

In this problem we define the array x with the index domain i (defined as a subset of Integers with the values {1,2,3,4,5,6,7,8}. Then all the parameters (constants) S,E,N,D,M,O,R,Y are defined to be able to be index in x, e.g. such as 1000*x(S)+ 100*x(E)+ 10*x(N)+x(D) (defining SEND) etc.

All these definitions are done via AIMMS' GUI, the Model Explorer. Here is a picture how it looks like; the graphical I/O is shown to the right (the Page Manager):


AIMMS SEND+MORE=MONEY


Below is the full definition of the model except for the graphical part (compare with the .aim file SendMoreMoney2.aim). Note that one very important feature in AIMMS is that one define the set of the indices to be used in an array: here the index i is defined via the set ii (the name of the set is not so important except for documentation purposes). When defining the array (x) the size is defined by the range of the index. So we define the array x(i) (identifier: x, index domain: (i)) and makes it a Variable with the range of {0..9} (i.e. the domain of the values in x).

Then we define the traditional constraints:
  • The values of S and M must be > 0: x(S) > 0 and x(M) > 0
  • The main constraint SEND+MORE=MONEY is defined as usual:
    (1000*x(S) + 100*x(E)+ 10*x(N) + x(D) +
    1000*x(M) + 100*x(O)+ 10*x(R) + x(E)) =
    (10000*x(M) + 1000*x(O) + 100*x(N) + 10*x(E) + x(Y))
And here are most of the definitions (slightly edited). A text representation of the model is available via the GUI: View, Text Representation, All.
DECLARATION SECTION 
    SET:
       identifier   :  ii
       subset of    :  Integers
       index        :  i
       definition   :  {1,2,3,4,5,6,7,8} ;

    CONSTRAINT:
       identifier   :  SendMoreMoney
       definition   :  (1000*x(S) + 100*x(E)+ 10*x(N) + x(D) +
                        1000*x(M) + 100*x(O)+ 10*x(R) + x(E)) =
            (10000*x(M) + 1000*x(O) + 100*x(N) + 10*x(E) + x(Y)) ;

    MATHEMATICAL PROGRAM:
       identifier   :  SendMoreMoney2Plan
       direction    :  minimize
       constraints  :  AllConstraints
       variables    :  AllVariables
       type         :  CSP ;

    CONSTRAINT:
       identifier   :  SM
       definition   :  x(S) > 0 and x(M) > 0  ;

    VARIABLE:
       identifier   :  x
       index domain :  (i)
       range        :  {0..9} ;

    PARAMETER:
       identifier   :  S
       definition   :  1 ;

    PARAMETER:
       identifier   :  E
       definition   :  2 ;

    PARAMETER:
       identifier   :  N
       definition   :  3 ;

    PARAMETER:
       identifier   :  D
       definition   :  4 ;

    PARAMETER:
       identifier   :  M
       definition   :  5 ;

    PARAMETER:
       identifier   :  O
       definition   :  6 ;

    PARAMETER:
       identifier   :  R
       definition   :  7 ;

    PARAMETER:
       identifier   :  Y
       definition   :  8 ;

    CONSTRAINT:
       identifier   :  AllDiff
       definition   :  cp::AllDifferent(i, x(i)) ;

  ENDSECTION  ;

  PROCEDURE
    identifier :  MainInitialization

  ENDPROCEDURE  ;

  PROCEDURE
    identifier :  MainExecution
    body       :  
      ShowProgressWindow;
      solve SendMoreMoney2Plan;

  ENDPROCEDURE  ;

ENDMODEL Main_SendMoreMoney2 ;
The call cp::AllDifferent(i, x(i)) works like this: The first parameter i is the "loop index" which is used to loop through the second argument x(i), i.e. it states that all the elements in x should be distinct. This is how for-loops are done in AIMMS and is a very common idiom.

The procedure MainExecution is where the program is started and is essential to get things working. Here we just do the following:
  • ShowProgressWindow: the Progress window shows how the model progress as well as the time, number of failures, etc.
  • solve SendMoreMoney2Plan which actuall start the solving process. This must be defined for all models. SendMoreMoney2Plan is of type mathematical program (select this type of identifier via type options labeled "..."). For Constraint Satisfaction models like this, select Type: CSP, and let Direction be whatever (minimize or maximize). For optimization models, the type should be COP (Constraint OPtimization), and state the objective variable, and the direction. (Note: The objective variable must be Free for some reason.)
In the Page Manager, the Solve button is then connected to the action running Main Execution (not shown in the listing above since it belongs to the GUI.)

NQueens

The first naive version of the N-queens problem is NQueens.aim, but is slow for larger N:
CONSTRAINT:
   identifier   :  C1
   index domain :  (i,j)
   definition   :  (i < j) and x(i) <> x(j)   ;

CONSTRAINT:
   identifier   :  C2
   index domain :  (i,j)
   definition   :  (i < j) and x(i) + i <> x(j) + j ;

CONSTRAINT:
   identifier   :  C3
   index domain :  (i,j)
   definition   :  (i < j) and x(i) - i <> x(j) - j ;

CONSTRAINT:
   identifier   :  AllDiff
   definition   :  cp::AllDifferent(i, x(i)) ;
The more modern - and faster - version is shown in NQueens2.aim which use three alldifferent constraints:
CONSTRAINT:
  identifier   :  alldiff1
  definition   :  cp::AllDifferent(i, x(i)) ;

CONSTRAINT:
  identifier   :  alldiff2
  definition   :  cp::AllDifferent(i, x(i)-i) ;

CONSTRAINT:
  identifier   :  alldiff3
  definition   :  cp::AllDifferent(i, x(i)+i) ;
To see the number of solutions of a model, just add this line last in MainExecution:
DialogMessage(GMP::Solution::Count('ProjectPlan'));
together with a large enough value of Solution storage limit in Setting, Project Settings, Specific Solvers, CPoptimizer 12.4, General.

It would be nice to have an easy way to actually showing all solutions, but I'm often quite happy with this feature.

One could note that AIMMS - with CPoptimizer as solver - shows the first solution of N=1000 in 3 seconds (422 failures).
My system setup for this benchmark: Running AIMMS in a Virtual Box running Windows 7, allotted 2Gb RAM, under a Linux Ubuntu 12.04, 64-bit with 12Gb RAM and 8 core Intel 930@2.80GHz.

CoinsGrid

Model: CoinsGridCP.aim
Model: CoinsGridCPMIP.aim

This is originally a MIP problem but I use it to see how a CP solver handles the problem (often not very good so I'm yet to be surprised). I originally thought of doing two versions of this, one CP version and one MIP version. But it's so easy to change to MIP version so I first settled with just one project, hence the name CoinsGridCP.

Note: Chris Kuip was kind enought to later add a way to select between CP and MIP, see CoinsGridCPMIP.aim.

Map, Map2

Model: Map.aim
Model: Map2.aim

This is a simple Map coloring problem, with two variants: Map and Map2.

For the standard settings the model Map.aim shows this solution:
   Country     Colors
   ------------------
   Belgium     2 
   Denmark     1 
   France      4 
   Germany     3 
   Netherlands 1 
   Luxembourg  1
which is perfectly fine. Without any symmetry breaking there are 144 solutions.

Symmetry breaking
Here is a simple symmetry breaking, where we state that Belgium has color 1 (whatever that color represents) with a restriction in the Index domain:
     Index domain: c1 | c1 = "Belgium"
     Colors(c1) = 1
The solution is now:
   Country     Colors
   ------------------
   Belgium     1
   Denmark     1 
   France      4 
   Germany     3 
   Netherlands 2 
   Luxembourg  2
which is also a correct solution.

Since that worked quite well, I also tried another version of Map (Map2.aim) that use real color names instead of integers, and also use another representation of the connections between the countries. This is perhaps more in the spirit of AIMMS.

The set Colors is defined as:
data {red, blue, green, yellow}
It was also very easy to do the direct representation of the connections between the countries. AIMMS converts automatically to a boolean connection matrix (a nice feature):

DATA { (Belgium, [France, Germany, Netherlands, Luxembourg]),
       (Denmark, [Germany]),
       (France, [Belgium, Germany, Netherlands, Luxembourg]),
       (Germany, [Belgium, Denmark, France, Netherlands, Luxembourg]),
       (Netherlands, [Belgium, France, Germany]),
       (Luxembourg, [Belgium, Germany]) }
However, it was a little bit harder to define the "DifferentColor" constraint using the color names, but after changing CountryColors to a ElementVariable and Range: Colors it worked as expected.
SET:
   identifier   :  Countries
   indices      :  c1, c2
   definition   :  data {Belgium, Denmark, France, Germany, Netherlands, Luxembourg} ;

SET:
   identifier   :  Colors
   index        :  c
   initial data :  data {red, blue, green, yellow} ;

ELEMENT VARIABLE:
   identifier   :  CountryColor
   index domain :  (c1)
   range        :  Colors ;

CONSTRAINT:
   identifier   :  DifferentColors
   index domain :  (c1,c2)
   definition   :  if (c1 <> c2 and Connections(c1, c2) = 1) then
                       CountryColor(c1) <> CountryColor(c2)
                   endif  ;
And the solution:
   Solution:
     Belgium     blue
     Denmark     red
     France      yellow
     Germany     gree
     Netherlands red
     Luxembourg  red

Minesweeper

Model: Minesweeper.aim

As I have mentioned before, I'm always amazed how easy it is to state this problem in a CP system (cudos to these high level programming languages). Here is the problem specification (from Gecode's Minesweeper model):
A specification is a square matrix of characters. Alphanumeric 
characters represent the number of mines adjacent to that field. 
Dots represent fields with an unknown number of mines adjacent to 
it (or an actual mine).

E.g.
     ..2.3.
     2.....
     ..24.3
     1.34..
     .....3
     .3.3..
The main constraint states that the number in "this" cell (if > 0) is the sum of the number of mines surrounding this cell. The indices i and j are defined as sets 1..#rows and 1..#cols, respectively. The four ifs in the Sum constraint restricts the value of i+a and j+b to be inside the matrix.
CONSTRAINT:
identifier   :  C1
index domain :  (i,j)
definition   :
   if (Problem(i,j) > 0) then
       Sum[(a,b), x(i+a, j+b) |
           (i+a > 0) and
           (j+b > 0) and
           (i+a <= R) and
           (j+b <= C)] =
       Problem(i,j)
   endif;
However, this constraint is not enough since it don't rule out that a hint cell can contain a mine (or if a cell contains a hint, it cannot contain a mine). So we must add either of these two constraints
CONSTRAINT:
identifier   :  C2
index domain :  (i,j)
definition   :
   if (Problem(i,j) >= 0) then
       x(i,j) = 0
   endif
comment      :
   "If a cell contains a hint (>= 0) then there can be no mine.
    Either C2 or C3 must be active." ;

CONSTRAINT:
identifier   :  C3
index domain :  (i,j)
definition   :
   if (x(i,j) = 1) then
      Problem(i,j) = -1
   endif
comment      :
    "If this cell contains a mine, then there can be no hint
     (i.e. >= 0). Either C2 or C3 must be active." ;
I tend to prefer constraint C2.

Here's the solution to the problem shown above, where a "1" marks where the mines are.
1 0 0 0 0 1
0 1 0 1 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 1 1 1 0 0
1 0 0 0 1 1
(A more artistic modeler than me would show the result in a nicer way.)

Sudoku

Model: Sudoku2.aim

Here is the way to fill the given hints:
CONSTRAINT:
   identifier   :  FillData
   index domain :  (i,j)
   definition   :  if (Problem(i,j) > 0) then
                      x(i,j) = Problem(i,j)
                   endif  ;
Note that this can also be written without the if clause, which more show the advantage of AIMMS modeling principle:
   index domain: (i,j) | Problem(i,j) > 0
   definition: x(i,j) = Problem(i,j)
The Latin Square requirements are very easy to state, using two alldifferent constraints:
  index: i
  cp::alldifferent(i, x(i,j))
and
  index: j
  cp::alldifferent(i, x(i,j))
However the block constraint is a little more tricky (as in all CP systems). In AIMMS one has (as I understand it) to define a special parameter, Blocks to be used in the constraint:
PARAMETER:
   identifier   :  Blocks
   index domain :  (i,j)
   definition   :  1+N*Div(i-1,N)+Div(j-1,n) ;

CONSTRAINT:
   identifier   :  C3
   index domain :  k
   definition   :  cp::AllDifferent( (i,j) | Blocks(i,j) = k, x(i,j) ) ;
The unique solution to the problem instance is
7 9 5 1 4 6 8 2 3 
6 4 3 8 2 5 7 9 1 
2 1 8 3 9 7 4 6 5 
5 2 7 9 6 1 3 8 4 
8 6 4 7 5 3 2 1 9 
1 3 9 2 8 4 6 5 7 
4 5 1 6 7 2 9 3 8 
9 7 6 5 3 8 1 4 2 
3 8 2 4 1 9 5 7 6 
To ensure that this is a unique solution, simply counts the number of solutions: any value larger than 1 means that the model is wrong in some way. Here's to do it:
  • Increase the number of Solution storage limit in Setting, Project Settings, Specific Solvers, CPoptimizer 12.4, General to 2 (the default is 1).
  • Show the number of solutions with this code in MainExecution: DialogMessage(GMP::Solution::Count('Sudoku2Plan') + " solutions");
When running the model, it shows "1 solutions" which indicates a unique solution.

AllDifferentExcept0

Model: AllDifferentExcept0.aim

AIMMS has excellent support for reification and I'm (happily) surprised that it worked as I expected. This is the constraint CAllDifferentExcept0 which states that all values in x that are not 0 (zero) must be distinct (hence the name of the global constraint AllDifferentExcept0).
   if (i < j and x(i) <> 0 and x(j) <> 0) then
     x(i) <> x(j)
   endif;
I also added an increasing constraint, CIncreasing:
   if (ord(i) > 1) then
      x(i-1) <= x(i)
   endif;
Though it might be more clear to write it as:
    index domain :  i | ord(i) > 1
    definition   :  x(i-1) <= x(i)

WhoKilledAgatha: reification and Element variables

Model:WhoKilledAgatha.aim

This is a standard benchmark for theorem proving and I use it for testing how well a CP system supports boolean decision variables and reifications. The way I usually model this problem yields 8 solutions, all indicating the same murder (guess who).

This AIMMS model also yields 8 solutions, and the tables for Hates and Richer are valid so I conclude that this model is correct (or rather: as correct as my other versions of this problem).
Here is the problem:
Someone in Dreadsbury Mansion killed Aunt Agatha. Agatha, the butler, and Charles live in Dreadsbury Mansion, and are the only ones to live there. A killer always hates, and is no richer than his victim. Charles hates noone that Agatha hates. Agatha hates everybody except the butler. The butler hates everyone not richer than Aunt Agatha. The butler hates everyone whom Agatha hates. Noone hates everyone. Who killed Agatha?
This was not as hard as I first thought it should be, though I had to experiment a little with Element Variables to get it to work.
Some comments:
  • The two decision variables Hates and Richer are set to Element Variables to be able to handle Element constraints such as
      Hates(TheKiller, TheVictim) = 1
      Richer(TheKiller, TheVictim) = 0
    
    Note that TheKiller is a decision variable.

    It's great that AIMMS support these kind of "matrix element constraint", even though one have to declare the variable as a special type.

  • I like that AIMMS has the same syntax for if-then else whether or not decision variables or parameters are involved in the if clause. This makes creating constraints much easier.

  • When using other CP systems I will certainly miss AIMMS elegant ways of creating certain constraints.
The way the constraints are stated in AIMMS is shown below, where we also show how a matrix is defined. As usual the size and indices of the matrix (Hates) are are defined via the set (ij), defining the indices and their domains (i and j).
PARAMETER:
       identifier   :  N
       definition   :  3 ;

SET:
       identifier   :  ij
       subset of    :  Integers
       indices      :  i, j
       definition   :  {1..N} ;

VARIABLE:
       identifier   :  Hates
       index domain :  (i,j)
       range        :  binary ;

CONSTRAINT:
       identifier   :  KillerHatesAVictim
       definition   :  hates(TheKiller, TheVictim) = 1 ;

CONSTRAINT:
       identifier   :  ButlerHaveEveryoneWhomAgataHates
       index domain :  i
       definition   :  if (Hates(Agatha, i) = 1) then
                         Hates(Butler, i) = 1
                       endif ;
(Sometimes I don't like to have to name all constraints in the model, but right now when writing about them it's is quite useful.)

DivisibleBy9Through1

Model: DivisibleBy9Through1.aim

This problem is mainly used to test a CP system regarding two things:
  • the modulo constraint, which is quite essential for some recreational mathematics problems. AIMMS has support for this (otherwise I would have tried to implement it).
  • how large integers can be handled
    AIMMS can manage up to base 10 (which is quite normal). I have seen solutions of this problem for base 12 and 14 (found by the ECLiPSe CP system). Here are the solutions for N <= 10 (the AIMMS model just show one of the alternative solutions):
    2: [1]
    4: [1, 2, 3] 
       [3, 2, 1]
    6: [1, 4, 3, 2, 5] 
       [5, 4, 3, 2, 1]
    8: [3, 2, 5, 4, 1, 6, 7]
       [5, 2, 3, 4, 7, 6, 1]
       [5, 6, 7, 4, 3, 2, 1]
    10: [3, 8, 1, 6, 5, 4, 7, 2, 9]
    
Chris Kuip suggested the following addition to MainExecution procedure which saves the variables for the first solution to a file:
write AllVariables to file "DivisibleBy9Through1.wrt";

FurnitureMoving: simple scheduling problem

File: FurnitureMoving.aim

This is a simple scheduling problem from Kim Marriott & Peter Stuckey: "Programming with constraints", page 112f, where the object is to optimize the tasks of moving some furnitures. In AIMMS the ParallelSchedule constraint is used, which is much like the traditional cumulative constraint:
cp::ParallelSchedule(
       upperLimit,
       jobDomain,
       jobStart,
       jobDuration,
       jobEnd,
       jobHeight
    )
Here are the specific values used in the model:
   UpperLimit: 4           (resources, i.e. persons)
   UpperLimit2: 120        (minutes)
   jobDomain: j            (index for domain Jobs: {1..UpperLimit2})
   jobStart: Start         (minutes, variable)
   jobDuration: Duration   (minutes, may involve variables)
   jobEnd:  End            (minutes, variable)
   jobHeight: Resources    (persons, may involve variables)
The only trouble I had here was how to define jobDomain, but after reading the definition a couple of times it's quite clear that UpperLimit, and jobHeight should have the same unit (i.e. resources), while the other are time (in minutes); that is, for this specific model.

It seems that we can assume that the End job requirement is automatically ensured by the cp::ParallelSchedule constraint, e.g. this constraint:
jobEnd(i) = jobStart(i) + jobDuration(i) 
(In many other CP systems one have to ensure this explicitly.)

This is a optimization model where MaxEndTime is to be minimized, stated in the mathematical program (here called FurnitureMovingPlan).

In some variants of cumulative (e.g. some of MiniZinc's solvers) I've seen that the total number of required resources can be a decision variable as well (and thus can be an objective variable), but this variant is not supported in AIMMS.

Later note: The AIMMS Blog's blog post Scheduling example: Narrowing time window for smaller jobs explains a little how to use scheduling with AIMMS+CP.

Langford number problem: indices

Langford.aim

Problem statement:
Langford's number problem (CSP lib problem 24)
Arrange 2 sets of positive integers 1..k to a sequence, such that, following the first occurence of an integer i, each subsequent occurrence of i, appears i+1 indices later than the last.
For example, for k=4, a solution would be 41312432
In this model I had some problems understanding how AIMMS' indices works, which emphasize that they don't work exactly as the "array based" indices that I'm used to from other CP systems.

In the constraints pos1 and pos3 shown below, it's important to restrict the index j so it don't go "over the edge" of the position array, which is interpreted by AIMMS as an error in the model, i.e. it throws an UNSAT when this happens. [Or perhaps it's the solver CPLEX CP Optimizer that does this interpretation.] Using the traditional "array based" for-loops this would have been easier, at least for me using a traditional for-loop. So beware of this gotcha. (Note: When writing this now much later, this behaviour actually makes much more sense than when I did the model.)
CONSTRAINT:
  identifier   :  pos1
  index domain :  j |j <= k
  definition   :  position(j) + j+1 = position(j+k)
  comment      :  "Note the index domain." ;

CONSTRAINT:
  identifier   :  pos2
  index domain :  (i)
  definition   :  solution(position(i)) = i ;

CONSTRAINT:
  identifier   :  pos3
  index domain :  j |j <= k
  definition   :  solution(position(k+j)) = j
  comment      :  "Note the index domain." ;
A similar case is in the AllInterval where one of the constraints is to restrict the index i to not be the last value of the Set i1 set (defined as the range 1..N), so it restricts i in the DiffsK constraint to not be N.
SET:
  identifier   :  i1
  subset of    :  Integers
  index        :  i
  definition   :  {1..N} ;

...

CONSTRAINT:
 identifier   :  DiffsK
 index domain :  i | i <> last( i1 )
 definition   :  diffs(i) = Abs(x(i)-x(i+1))
 comment      :  "Note the special handling of the index domain for this constraint." ;
These kind of behaviour (different to what I'm used to) have caused some long debugging sessions.

Fortunately Chris Kuip was kind enough to explain all this to me. And today he also wrote the blog post What is the element after the last? explaining this in some detail.

Magic Square and Magic Square Water Retention problem

Model: MagicSquare.aim
Model: MagicSquareWaterRetention.aim

The plain MagicSquare model is not so interesting, except perhaps that in the GUI one can select which symmetry breaking constraints to use. This is done via the four binary variables UseSymmetry1 ... UseSymmetry4.

Magic Square Water Retention problem
More interesting is MagicSquareWaterRetention.aim which is one of few model where I have tested with different search heuristics and other settings (see below for a little more about these). The object is to create a magic square where the numbers represents heights and retains as much water as possible in the "cavaties" that is created. More info about this problem is in Wikipedia article Water retention on mathematical surfaces. This AIMMS model also use the Frénicle standard form for symmetry breaking.

It seems that the big win is to use Search Type::Restart instead of Automatic. Using this option solves the problem for N=4 in about 3 seconds (with 168662 failures) compared to 20 seconds (663751 failures) when using Search Type: Automatic.

Trying with N=5, my small allotted 2Gb for the VirtualBox Windows 7 was probably not enough since AIMMS unfortunately crashed. (Chris Kuip mentioned that this crasch is not reproducible in the released version of AIMMS+CP.)

[My best shot of this problem has so far been with a MiniZinc model where Gecode/fz solves N=4 in 0.8 seconds (48619 failures) using the heuristics "most_constrained"/"indomain_random".]

In this model we see some of the benefits and drawbacks of the AIMMS approach (as I perceive them):
  • benefit: It's quite easy and descriptive to state the water retention constraint (first part). There is no explicit for-loop, just using the defined indices and adjust for the border cases (1 and N).
       (i,j) | i > 1 and j > 1 and i < N and j < N
       water(i,j) = Max(x(i,j), Min(water(i-1,j), water(i,j-1),
                                water(i+1,j), water(i,j+1)))
       
  • drawback: When defining the ranges (domains) - which in this model are 1..N, 1..N*N, and 1..N*N*N, it must be done with two extra help parameters (N2, N*N, and N3, N*N*N) since the Range Wizard for the variable cannot calculate formulas for the upper bound.
  • drawback: Defining the optimization problem the objective (z) must be declared as a Free Range variable (-inf .. inf) and not using the Range domain (1..N3). Intuitively this seems to be a too large domain for the solver to handle, but perhaps the solver is intelligent in calculating the bounds.

Some other comments

Here are some more asorted comments about AIMMS+CP and my way of using it.

Number of solutions

One of the drawback in AIMMS is that it's not easy to generate all the solutions. It is possible but I have not done that. However, it's easy to count the number of solutions using the following:
  • Change Settings, Project Options... select Specific solvers, CPoptimizer 12.4, General and change Solution storage limit to a higher value, e.g. 1000.
  • Add this code to the MainExecution procedure: DialogMessage("It was " + GMP::Solution::Count('ProjectPlan') + " solution(s).");

Data instances, data files

Many of models contain some data (as a parameter that might be changed when running the project). There is in principle two approaches for using data files in AIMMS:
  • enter the data via the Parameter definition and keep it there.
  • define a couple of data files and load the appropriate via Data, Load Case, as active
I have used both principles in the models, though with the second approach one of the data instances is loaded automatically via Settings, Project, Startup & authorization, Startup case.

Automatically saving .aim files

Since I often want to look in other models when implementing a new (mostly done with the .aim files), I tend to set the projects to save the .aim file when closing the project: Settings, Autosave & Backups, Project, Create an AIM file at Project Close.
There seems to be no way to set this option globaly, i.e. for all new projects created.

Heuristics

I like that there is a lot of different heuristics, though I have not explored them as much. They are defined in Settings, Project Option, Specific solvers, CPoptimizer 12.4, Search
  • Variable selection:
    • Automatic
    • Random
    • Smallest domain size
    • Largest domain size
    • Smallest maximum domain value
    • Largest maximum domain value
    • Smallest minimum domain value
    • Largest minimum domain value
    • Smallest impact
    • Largest impact
    • Smallest impact last branch
    • Largest impact last branch
    • Smallest local impact
    • Largest local impact
    • Smallest success rate
    • Largest success rate
  • Value selection:
    • Automatic
    • Smallest impact
    • Largest success rate
    • Smallest value
    • Largest value
Note that these search heuristics are globally on the model. I have found no way to select the specific variable(s) to branch on.

Procedures

One drawback in AIMMS is that there is no way (I know of) to implement a user-defined "procedure" that is easy accessible in different models/projects. Instead one has to copy the constraint verbatim. I have mostly copied the definitions from the saved .aim files. There is also a way of viewing the textual representation in the current model (presented much like the .aim files). This is done via View, Text Representational, All when in the Model Explorer.

Later note: Guido Diepen (Paragon) blogged about this a year ago Exporting a section and importing it in another AIMMS project, though I didn't now that until very recently.

Some tips

Stop a calculation: Ctrl-Shift-S

Don't forget to set Set ii to a subset of integers.

Pros / Cons: A kind of summary

And finally, here is a subjective list of pros/cons about AIMMS (as I have understood it). Pros
  • AIMMS has a very nice GUI to create and checking constraints and the related data. The online checking of constraints, indices, lengths etc is very handy.
  • Certain constructs are nice and powerful, e.g. that there is no syntactic difference between "if" on plain boolean variables/conditions and on decision variables.
  • Another nice thing is that some loops can be written quite naturally without "for" just via the index (i,j etc).
  • Using a GUI makes it easy to connect different parts of the model, especially between data/variables and the output.
Cons
  • For an "integer array based" constraint programmer like me it took some time to get used to the "items based" approach that is AIMMS' forte. Example: Some intuitions from "integer index based" modelling don't apply directly to AIMMS; e.g. see the dicussion about the Langford model above.
  • Also, the focus on defining indices and their connection with arrays was a little uncommon for me, and took some time from the rest of the modeling.
  • It's not very easy to generate and show all solutions to a problem. Though it's very easy to generate the number of solutions (see NQueens etc).
  • Using a GUI as the main modeling is a bit strange to me since I'm almost always use a texteditor (Emacs) and then run via command line (under Linux). There are ways to use textfiles directly but since this is Windows I'm not very confortable which that.
  • I used Windows 7 in VirtualBox under Ubuntu 12.04 and some things didn't work, for example copying backup files from my Linux box to the Windows' AIMMS' directory. This was - of course - not AIMMS' fault, but it made my experience sometimes a little frustrating...

My AIMMS+CP models

Here are some of my AIMMS+CP models, many originally written in the Summer 2011. Around mid-September 2012, I re-checked (and re-modelled) these with AIMMS version 3.13 (beta) and also added a few new. Thanks to Chris Kuip (Paragon) for comments, suggestions and improvements on many of these models.

October 20, 2012

Beldiceanu and Simonis: A Model Seeker

Nicolas Beldiceanu and Helmut Simonis has written a very interesting paper about A Model Seeker, a system that finds the problem given a solution. Or more to the truth: suggests the appropriate global constraints given positive data instances (solution(s) to a certain problem). It was presented at the technical track of CP2012 (18th International Conference on Principles and Practice of Constraint Programming).

The system (A Model Seeker) is described in the paper: A Model Seeker: Extracting Global Constraint Models From Positive Examples (also: Presentation and Poster from the CP2012 conference).

From the Abstract:
We describe a system which generates finite domain constraint models from positive example solutions, for highly structured problems. The system is based on the global constraint catalog, providing the library of constraints that can be used in modeling, and the Constraint Seeker tool, which finds a ranked list of matching constraints given one or more sample call patterns.
We have tested the modeler with 230 examples, ranging from 4 to 6,500 variables, using between 1 and 7,000 samples. These examples come from a variety of domains, including puzzles, sports-scheduling, packing & placement, and design theory. When comparing against manually specified “canonical” models for the examples, we achieve a hit rate of 50%, processing the complete benchmark set in less than one hour on a laptop. Surprisingly, in many cases the system finds usable candidate lists even when working with a single, positive example.
A companion technical report presents the details of the 230 tested examples: A Model Seeker Description and Detailed Results (over 1400 pages).

This is a system I really would like to test...

October 16, 2012

CP2013 (Constraint Programming Conference) will be held in Uppsala, 16 - 20 September 2013

Just a short note about the next Constraint Programming Conference (CP2013). It will be in Uppsala, Sweden. From SweConsNet:
CP'13, the 19th International Conference on the Principles and Practice of Constraint Programming, will be held at Uppsala University on 16 - 20 September 2013.
More details will come.

I'm quite excited about this since it's in my home country which makes everything easier. At last I will have a chance to meet all the nice, smart and interesting people that I have read and read about (and in some case had mail conversation with).

See a list of the former CP conferences: International Conference on Principles and Practice of Constraint Programming. The last one finished some days ago: CP2012.

October 14, 2012

Results MiniZinc Challenge 2012

The result from MiniZinc Challenge 2012 was presented this Friday (the last day of CP2012, 18th International Conference on Principles and Practice of Constraint Programming ).

The official contestants (solvers) this year was: Of these solvers, the only one I haven't tested (yet) is izplus.

Official results

The official results are:
  • Fixed search:
    • Gold medal: Gecode
    • Silver medal: Jacop
    • Bronze medal: OR-Tools
  • Free search:
    • Gold medal: Gecode
    • Silver medal: Fzn2smt
    • Bronze medal: izplus
  • Parallel search:
    • Gold medal: Gecode
    • Silver medal: Fzn2smt
    • Bronze medal: izplus
Congratutations to all!

Result including all solvers

It can be interesting to see the results for all solvers in the Challenge, including the G12's internal solvers such as Chuffed and CPX (which "are not eligible for prizes, but do modify the scoring results"). For a short description of these non-eligible solvers, see the short description at the result page.

I took the results from the "Selection" section of the result page and for each categories selected "Select all problems", "Compute results" and then sorted on the points (most is best). The result is quite interesting since it shows that Chuffed and G12 CPX got most points in all the three categories, and G12 Lazy FD also got good places.

Note: The mixing in the categories is explained by the management: entries in the FD search category were automatically included in the free search category, while entries in the free search category (including promoted FD entries) were automatically included in the parallel search category. The official winners (gold, silver, bronze) has been embolded.
  • Fixed search ("FD category solvers")
    chuffed-fd1136
    g12_cpx-fd1060
    gecode-fd881
    g12_lazyfd-fd783
    jacop-fd548
    g12_fd-fd525
    or_tools-fd488
    choco-fd430
    bprolog-fd265

  • Free category ("Free category solvers")
    chuffed-free2359
    g12_cpx-free1915
    g12_lazyfd-free1782
    gecode-free1620
    fzn2smt-free1522
    gurobi-free1481
    izplus-free1413
    cplex-free1367
    jacop-free1326
    bprolog-free1203
    mistral-free1199
    g12_fd-free998
    choco-free805
    or_tools-free692
    minisatid-free648
    cbc-free222

  • Par category ("Par category solvers")
    chuffed-free2341
    g12_cpx-free1897
    gecode-par1846
    g12_lazyfd-free1758
    fzn2smt-free1504
    gurobi-par1499
    izplus-free1380
    cplex-par1351
    jacop-free1293
    bprolog-free1178
    mistral-free1173
    g12_fd-free974
    or_tools-par810
    choco-free789
    minisatid-free627
    cbc-free222

Note that all the problem instances are available for download from the Result page (mznc12-problems.tar.gz).

Also see: MiniZinc Challenge Medals 2008-2012

August 02, 2012

A first look at OscaR (Scala in OR), former Scampi

OscaR - (Scala in OR) is a constraint solver for Scala (former called Scampi). The source is here (Bitbucket).

From the Wiki:
OscaR (Scala in OR) is a Scala toolkit to solve Operations Research problems. The techniques currently available in OscaR are:
The part I have focused on is Constraint Programming which is presented in these links: Pierre Schaus (and his blog Constraint Programming ) should be mentioned here as well, since he is the creator of much of the CP support in OscaR. Thanks Pierre for a great system and for all your help.

Modeling in OscaR

OscaR should be seen as a high level CP modeling language, since it has a lot of operator overloaded, see example of this below. (About the only thing I miss regarding this is a "sugared" version of element, i.e. x(y) where y is a decision variable. More about that later on...).

I should perhaps mention that this project has been both learning OscaR and learning more about Scala. Scala is a very nice programming language with suite me quite well since it supports both imperative object oriented way of thinking as well as pure functional approach (though I have to confess that in some models this is not apparent at all).

Most examples shown in this blog post are from my OscaR page. There are other OscaR examples in the repo here.

First model: SEND+MORE=MONEY

Here is the full model of SEND+MORE=MONEY problem (it's also available at SendMoreMoney.scala, and - as mentioned - also in the OscaR repo, see below):
package oscar.examples.cp.hakank
import oscar.cp.modeling._
import oscar.cp.search._
import oscar.cp.core._

object SendMoreMoney {
  def main(args: Array[String]) {
    val cp = CPSolver()
    val S = CPVarInt(cp, 0 to 9)
    val E = CPVarInt(cp, 0 to 9)
    val N = CPVarInt(cp, 0 to 9)
    val D = CPVarInt(cp, 0 to 9)
    val M = CPVarInt(cp, 0 to 9)
    val O = CPVarInt(cp, 0 to 9)
    val R = CPVarInt(cp, 0 to 9)
    val Y = CPVarInt(cp, 0 to 9)
    val all = Array(S,E,N,D,M,O,R,Y)

    cp.solveAll() subjectTo {
      cp.add(       S*1000 + E*100 + N*10 + D +
                    M*1000 + O*100 + R*10 + E ==
          M*10000 + O*1000 + N*100 + E*10 + Y)
      cp.add(S > 0)
      cp.add(M > 0)
      cp.add(alldifferent(all), Strong)

    } exploration {
      cp.binaryFirstFail(all)
      println(all.mkString(""))
    }
    println()
    cp.printStats()
  }
}
The output is:
 9 5 6 7 1 0 8 2

(time(ms),36)
(#bkts,5)
(time in fix point(ms),18)
(time in trail restore(ms),0)
(max trail size,587)
Some things to note:
  • OscaR is quite influenced by the way Comet (and OPL) separate the constraint part (cp.solveAll() subjectTo) and the search (branching) and output part (exploration). See below for a little more about search, and for a optimization example.
  • The arithmetic operators (*,+,==, and many more) are nicely overloaded which simplifies much of the modeling. I comment more about this below.
  • Additions of the constraint are done with cp.add(constraint).
A neater encoding of this problem is the following, using Scala's ability to extract variables from an Array (what is called "pattern matching"). This requires that the variables must be lower case.
// ...
val all = Array.fill(8)(CPVarInt(cp, 0 to 9))
val Array(s,e,n,d,m,o,r,y) = all

cp.solveAll() subjectTo {

  // constraints
  cp.add(       s*1000 + e*100 + n*10 + d +
                m*1000 + o*100 + r*10 + e =
      m*10000 + o*1000 + n*100 + e*10 + y)
  cp.add(s > 0)
  cp.add(m > 0)
  cp.add(alldifferent(all), Strong)
} exploration {
// ...
}
Another example is Minesweeper.scala which is an example of how to use yield to collect variables.
// ...
val mines = Array.fill(r)(Array.fill(c)(CPVarInt(cp, 0 to 1)))
cp.solveAll subjectTo {
  val tmp = List(-1,0,1)
  for(i <- 0 until r) {
     for(j <- 0 until c
       if game(i)(j) >= 0) {
          cp.add(sum(
             for{ a <- tmp; b <- tmp 
              if ((i+a >= 0) && (j+b  >= 0) &&
                 (i+a <  r)  && (j+b <  c)) 
              } yield mines(i+a)(j+b))
               == game(i)(j)
             ) // end sum

        // redundant constraint
        if (game(i)(j) > X) {
          cp.add(mines(i)(j) == 0)
        }
  }
}
// ...

Running OscaR

Running OscaR requires - of course - the OscaR distribution and Scala. Compiling it from source also requires the sbt tool. Obtaining a working version of OscaR can be done in two ways:
  • Get the distribution from the bitbucket.org repo. A JAR file is available here.
  • Or use Mercurial to do things manually, which basically consists of the following:
    (ht clone), hg pull, hg update, sbt assembly, sbt test

Running OscaR models

Note that models that are in Scala packages - such as the models in the distribution and my own models - must first be compiled with scala/fsc, i.e. they cannot be run as Scala scripts (at least using the current Scala version). Here is how I run a OscaR model under Linux:
$ fsc -J"-Xmx2000m" -deprecation -cp /path/to/oscar/oscar.jar -P:continuations:enable oscar/examples/cp/hakank/SendMoreMoney.scala

$ time scala -J"-Xmx2000m" -cp /path/to/oscar/oscar.jar -P:continuations:enable oscar.examples.cp.hakank.SendMoreMoney

Defining constraints (decompositions)

To define a constraint (decomposition) there are two variants depending on the return value. For "simple" constraints which returns a single value, e.g. CPVarInt, a Constraint, or CPVarBool then it can be used quite "seam less" in the model as cp.add(myConstraint(x)). An example from DeBruijn.scala is the constraint toNum which channels between an array of CPVarInt's and a CPVarInt (e.g. the Array (4,2,3,1) is channeled with the number 4231):
def toNum(t: Array[CPVarInt], base: Int=10) = sum(
    Array.tabulate(t.length)(i=> t(i)*pow(base, t.length-i-1).toInt))

  // ...

  cp.solveAll subjectTo {

    // ...
    // Usage: 
    cp.add(x(i) == toNum(t, base))
    // ...

  } // ...


For other constraints which don't return a single value, then one have to use a slightly different approach and add the CPSolver as a parameter to the function. Here is an example of defining the inverse, used in Marathon.scala and PhotoProblem.scala for presenting the result in a more appropriate manner:
def inverse(cp: CPSolver,
            x: Array[CPVarInt],
            y: Array[CPVarInt]) {
   val len = x.length
   for(i <- 0 until len;
       j <- 0 until len) {
         cp.add( (y(j) === i) == (x(i) === j) )
      }
   }

// ...

cp.maximize(z) subjectTo {

   // Usage: Channeling positions <=> places
   inverse(cp, positions, places)

} // ...
Here are some other defined decompositions (many not at all advanced, but never the less nice to have): More advanced advices regarding user-defined constraints are mentioned in the Wiki page Implement your own constraint.

Reification: Alldifferent except 0

Here is a simple decomposition of the global constraint alldifferent expcept 0 to show how reifications are done in OscaR.
def alldifferent_except_0(cp: CPSolver, y: Array[CPVarInt]) = {
  for(i <- 0 until y.length; j <- 0 until i) {
    cp.add( ((y(i) !== 0) && (y(j) !== 0)) ==> (y(i) !== y(j)) )
  }
}
I.e.: if both y(i) and y(j) are != 0, then they should be different.

OscaR use the following operators when using boolean operators and reifications:
  A >  B is reified with A >>= B
  A >= B is reified with A >== B                                                                                          
  A  < B is reified with A <<= B
  A <= B is reified with A <== B
  A == B is reified with A === B
(Note the trailing = for the reified variant.)

Also, b1 ==> b2 represents the implication: b1 implies b2 (i.e. if b1 is true, then b2 is true). And !A is the negation of A.

An example that use a lot of reifications is WhoKilledAgatha.scala. Here's an extract:
//  ...
//  Charles hates noone that Agatha hates.
NRANGE.foreach(i=>
  cp.add((hates(agatha)(i)) ==>
         (!hates(charles)(i))))

//  The butler hates everyone not richer than Aunt Agatha.
NRANGE.foreach(i=>
  cp.add(!richer(i)(agatha) ==>
         hates(butler)(i)))

Always put the CPVarInt at the left in mixed expressions

This is a gotcha when using OscaR, and I mentioned a similar problem regarding JaCoPInScala in my blog post A first look at scalaJaCoP (Scala wrapper for JaCoP).

When an expression (constraint, reification) has both an Int and an CPVarInt variable, then OscaR/Scala is picky about where to put the terms. For example, the above equation SEND+MORE=MONEY must be written with the CPVarInt at the left, i.e. as S * 1000 + .. (rather than 1000 * S + ...), and this is a consequence how Scala's overloading works: Int's don't know about constraints etc, but CPVarInt's knows everything...

If the equation would have been stated as cp.add(1000*S... then the following error is thrown which can be confusing; and I mention it here so you might remember it when starting to use OscaR on you own. (Perhaps more seasoned Scala users understands this immediately and feel offended by this friendly advice.)
SendMoreMoney.scala:57: error: overloaded method value * with alternatives:
  (x: Double)Double 
  (x: Float)Float 
  (x: Long)Long 
  (x: Int)Int 
  (x: Char)Int 
  (x: Short)Int 
  (x: Byte)Int
 cannot be applied to (oscar.cp.core.CPVarInt)
        cp.add(       1000*S + E*100 + N*10 + D +
                           ^

Optimization

OscaR supports - of course - optimization. Here's a simple diet problem (Diet2.scala), where the object is to minimize the total cost with the restrictions that the nutritions have minimum limits. Note the nice feature that a decision variable (here cost) can be defined directly using a constraint (val cost = weightedSum(price, x)).

The way to indicate optimization of a variable is cp.minimize(cost) (and cp.minimize(z)):
val cp = CPSolver()
val n = 4
val price  = Array( 50, 20, 30, 80)
// minumum requirements for each nutrition
val limits = Array(500,  6, 10,  8)
// nutritions for each product
val calories  = Array(400, 200, 150, 500)
val chocolate = Array(3,2,0,0)
val sugar     = Array(2,2,4,4)
val fat       = Array(2,4,1,5)
val all = Array(calories, chocolate, sugar, fat)

// variables
val x = Array.fill(n)(CPVarInt(cp, 0 to 10))
val cost = weightedSum(price, x)

cp.minimize(cost) subjectTo {
  // handle the nutrition requirements
  for(i <- 0 until n) (
      cp.add(weightedSum(all(i), x) >= limits(i))
  )
} exploration { 
   cp.binaryFirstFail(x)
   println(x.mkString(" "))
}
The result shows that the minimum cost is 90 using 3 units of item 2.
 0  3  0  1
objective tighten to 140
 0  3  1  0
objective tighten to 90

(time(ms),31)
(#bkts,5)
(time in fix point(ms),6)
(time in trail restore(ms),0)
(max trail size,446)

Element: Langford

Since I'm a little obsessed with how the element constraint is written in a CP system, it must be mentioned here as well. Example: element constraints in used in Langford.scala:
for(i <- 1 to k) {
   cp.add(position(i+k-1) == (position(i-1) + i+1))
   cp.add(element(solution, position(i-1)) == i)
   cp.add(element(solution, position(k+i-1)) == i)
}
And this is similar to most CP systems which are hosted in a programming language.

In a very high level CP system, such as MiniZinc (langford2.mzn), it is stated a little more simple (and - in my book - more natural) as:
forall(i in 1..to) (
  position[i+k-1] = position[i-1] + i+1 /\
  solution[position[i-1]]   == i        /\
  solution[position[k+i-1]] == i
)  

Search (labeling/branching)

This principle of search (labeling, branching) in OscaR is inspired by Comet which means that you have building blocks that can be put together to do quite advanced things. The basic approach is defined in OscaR's Wiki search. In OscaR's main CP example directory, there are many example how to do advanced search.

Here I will just mention some of the basic search methods (which I tend to use first). Let us here assume that x is an Array of CPVarInt, then OscaR support these utility functions:
  • cp.binary(x)
  • cp.binaryFirstFail(x)
  • cp.binaryMaxDegree(x)
Quite recently some other variants was added (after my request; post hoc ergo propter hoc). From the answer:
I [Pierre Schaus] have adapted binary to let you add custom variable/value heuristics.

binary(vars: Array[CPVarInt], varHeuris: (CPVarInt => Int) = minVar, valHeuris: (CPVarInt => Int) = minVal)

So if you want a min dom heuristic, taking the max value you would do

cp.binary(x,_.size,_.max)

If you want a max degree one you can do

cp.binary(x,-_.constraintDegree,_.max)
The available attributes (of a CPVarInt) that can be used directly in this manner is:
  • size
  • min
  • max
  • constraintDegree
  • randomValue (for value selection)
  • an combinations such as (v => v.max-v.min), etc.
As a simple example of the latter, see the CalvinPuzzleTable.scala where the search is defined thus:
// ...
cp.binary(x_flat,-_.constraintDegree,_.randomValue)
// ...

Scheduling

Very recently support for scheduling was added to OscaR by Renaud Hartert. See the Wiki entry Scheduling with CP for more information. I haven't used it very much so I just point to the examples.

Some end notes

It's fun modeling in OscaR since it's so high level, and extra fun since Scala is a very nice programming language.

As indicated in the introduction, OscaR has more features besides support for Constraint Programming, such as Constraint Based Local Search (former Asteroid), Linear Programming, and Discrete Event Simulation, as well as Scheduling in CP (mentioned above). Also there is support for visualization. These features has not been tested but I hope to test some of them in the future.

Most of my own OscaR models where converted from either my JaCoP/Scala models or my or-tools/C# models; and this probably shows in some of them.

My OscaR models

Here are some of my OscaR models.

All these models (or at least the majority) is also be available from the OsacaR repo: https://bitbucket.org/oscarlib/oscar/src/tip/src/main/scala/oscar/examples/cp/hakank. Thanks to Pierre Schaus for improving several of these models, either directly or indirectly by adding functions (or syntactic sugar).

May 16, 2012

SweConsNet Workshop 2012 - including my presentation "Comparison of >= 14 CP systems - and counting"

This Monday/Tuesday I visited Örebro (Sweden) attending the SweConsNet Workshop 2012, Monday) (co-located with Swedish Artificial Intelligence Society Workshop 2012, program, Monday and Tuesday). SweConsNet is the Network for Sweden-based researchers and practitioners of Constraint programming and is a Special Interest Group of SAIS.

SweConsNet Workshop 2012

One of the greatest joy attending these workshops is to meet and talk to all the clever and nice CP guys in Sweden/Denmark/Norway. But of course, the talks are also very interesting and they yield much inspiration and/or thoughts. Here's the program (the page SweConsNet Workshop 2012 have links to most presentations):
  • Mats Carlsson, SICS. On the Reification of Global Constraints.
    Joint Work with: Nicolas Beldiceanu (EMN, Nantes, France), Pierre Flener and Justin Pearson (Uppsala University).
  • Federico Pecora: Constraint reasoning and motion planning in the SAUNA project (This is a joint talk with SAIS).
  • Uwe Köckemann, Federico Pecora and Lars Karlsson. Towards Planning With Very Expressive Languages via Problem Decomposition Into Multiple CSPs (This is a joint talk with SAIS).
  • Invited talk: Associate professor Rune Møller Jensen from the IT University of Copenhagen will talk about AI and CP methods for optimizing liner shipping operations. (This is a joint talk with SAIS).
  • Krzysztof Kuchcinski, Lund University. Operation Scheduling, Binding and Data Routing for Run-Time Reconfigurable Architecture.
  • Håkan Kjellerstrand. Comparison of >= 14 CP systems - and counting.
  • Stefano Di Alesio, Simula School of Research and Innovation AS, Norway. Testing Deadline Misses for Real-Time Systems Using Constraint Optimization Techniques.
  • SAIS Masters Thesis Award Winner Rodrigo Gumucio. (This is a joint talk with SAIS).
  • Maria Andreina Francisco Rodriguez, Uppsala University. Consistency of Automaton-Induced Constraint Decompositions.
    Joint work with: Pierre Flener and Justin Pearson (Uppsala University).
  • Roberto Castañeda Lozano, SICS & KTH - ICT. Code Generation is a Constraint Problem.
    Joint work with: Mats Carlsson (SICS), Frej Drejhammar (SICS), Christian Schulte (KTH - ICT & SICS).
The two talks that I liked most this year was:
  • Mats Carlsson's talk about "On the Reification of Global Constraints" which will probably/hopefully have a deep impact on the CP field
  • and Roberto Castañeda Lozano about "Code Generation is a Constraint Problem", both for the interesting problem and the excellent presentation.
Thanks to Christian Schulte who together with the Federico Pecora and Lars Carlsson arranged these great days.

My SweConsNet talk: "Comparison of >= 14 CP systems - and counting"

My own talk at the workshop was Comparison of >= 14 CP systems - and counting (PowerPoint). The purpose of it was twofold:
  • Point out that my models - and especially the page Common constraint programming problems - could be used to compare different CP systems since quite a few implements the same problem using the same ("as same as possible") approach. As of now there are:
    • 276 problems that is implemented in >= 2 systems (in total 1260 implemented models)
    • 73 problems in >= 6 systems
    • 44 problems in >= 8 systems
    • 15 problems in >= 10 systems
  • Mention some strengths/weaknesses - or rather: my likes/dislikes - about these 14 tested systems, especially for a person learning the CP system or learning CP in general. One of my running theme is that the syntax for the most common things in modeling (e.g. the Element constraint and reifications) should be as easy as possible. The links are to my model pages for each system:
After the "Thanks" slide (which concluded the talk), there are some more slides for the Q/A session or as reserves.

Note: This is kind of an extension of my SweConsNet Workshop 2009 talk where I presented my take on the then tested 6 CP systems. See Report from SweConsNet2009, including my presentation.

Manufacturing Cell Design Problem (MCDP): My first Constraint Programming related academic papers

Some days ago I was told that the journal paper I have co-authored about Manufacturing Cell Design Problem (MCDP, see below) has been accepted for publication in a journal. Also, some weeks ago a short conference paper about the same topic was accepted. My part in both papers was that I created a couple of MiniZinc models (first the standard formulation and then some other using different approaches) and running a large number of benchmarks on a couple of FlatZinc solvers. This is really fun, since these papers are my first academic papers related to Constraint Programming.

Since the papers are not yet published/presented, I cannot reveal much more than the following. After the publications, I will blog more.

The journal paper

The journal paper is

Ricardo Soto, Hakan Kjellerstrand, Orlando Durán, Broderick Crawford, Eric Monfroy, Fernando Paredes: Cell formation in group technology using constraint programming and Boolean satisfiability

Published in the journal Expert Systems with Applications (ScienceDirect page, "In Press, Corrected Proof")

Abstract:
Cell formation consists in organizing a plant as a set of cells, each of them containing machines that process similar types or families of parts. The idea is to minimize the part flow among cells in order to reduce costs and increase productivity. The literature presents different approaches devoted to solve this problem, which are mainly based on mathematical programming and on evolutionary computing. Mathematical programming can guarantee a global optimal solution, however at a higher computational cost than an evolutionary algorithm, which can assure a good enough optimum in a fixed amount of time. In this paper, we model and solve this problem by using state-of-the-art constraint programming (CP) techniques and Boolean satisfiability (SAT) technology. We present different experimental results that demonstrate the efficiency of the proposed optimization models. Indeed, CP and SAT implementations are able to reach the global optima in all tested instances and in competitive runtime.

Keywords:
Manufacturing cells; Machine grouping; Constraint programming; Boolean satisfiability

Conference paper

The short conference paper is the following (with almost the same authors as the journal paper)

Ricardo Soto, Hakan Kjellerstrand, Juan Gutiérrez, Alexis López, Broderick Crawford, and Eric Monfroy: Solving Manufacturing Cell Design Problems using Constraint Programming

for the conference IEA/AIE 2012 (International Conference on Industrial, Engineering and Other Applications. of Applied Intelligent Systems, 2012 Dalian, China )

Abstract:
A manufacturing cell design problem (MCDP) consists in creating an optimal production plant layout. The production plant is composed of cells which in turn are composed of machines that process part families of products. The goal is to minimize part flow among cells in order to reduce production costs and increase productivity. In this paper, we focus on modeling and solving the MCDP by using state-of-the-art constraint programming (CP) techniques. We implement different optimization models and we solve it by using two solving engines. Our preliminary results demonstrate the efficiency of the proposed implementations, indeed the global optima is reached in all instances and in competitive runtime.

More about MCDP

Manufacturing Cell Design Problem is a kind of clustering problem where the object is to cluster machines that belongs to the same part (families) as good as possible. For a little more about the problem, see the following (Powerpoint) presentation by My Mingang Fu, Lin Ben, and Kuowei Chen Manufacturing Cell Design - Problem Formulation.

April 20, 2012

G12 MiniZinc version 1.5.1 released

G12 MiniZinc version 1.5.1 has been released. It can be downloaded here.

From the NEWS:
G12 MiniZinc Distribution 1.5.1
-------------------------------

* We have added the following variants of the count/3 constraint to the MiniZinc library:

count_eq (synonym for count)
count_geq
count_gt
count_leq
count_lt
count_neq


Bugs fixed in this release:

* mzn2fzn now correctly flattens the built-in functions xorall/1 and iffall/1 when they appear in reified contexts with at least two variables and at least one literal "true" in their array argument. [Bug #340]

* A bug in mzn2fzn that caused models that were satisfiable under the relational semantics to be incorrectly flattened into unsatisfiable FlatZinc instances has been fixed. [Bug #337]

* A bug that caused mzn2fzn to infer incorrect bounds for arrays of set variables has been fixed. [Bug #341]

April 16, 2012

JaCoP version 3.2 released (bug fixes and Scala interface)

From JaCoP version 3.2 released :
Dear users, We have just released JaCoP 3.2. This is a release that fixes few bugs as well as provides an interface from Scala to JaCoP. Examples of using Scala are provided in ExamplesScala package. Additional discussion and examples are also available at

JaCoP/Scala and at Hakan Kjellerstand blog at A first look at scalaJaCoP (Scala wrapper for JaCoP)

best regards,

Core Developer Team
The latest version of JaCoP can be downloaded from Sourceforge jacop-solver. Also, see my JaCoP page.

April 04, 2012

MiniZinc Challenge 2012 is now underway

The MiniZinc Challenge 2012 is now underway:
The Challenge

The aim of the challenge is to start to compare various constraint solving technology on the same problems sets. The focus is on finite domain propagation solvers. An auxiliary aim is to build up a library of interesting problem models, which can be used to compare solvers and solving technologies.

Entrants to the challenge provide a FlatZinc solver and global constraint definitions specialized for their solver. Each solver is run on 100 MiniZinc model instances. We run the translator mzn2fzn on the MiniZinc model and instance using the provided global constraint definitions to create a FlatZinc file. The FlatZinc file is input to the provided solver. Points are awarded for solving problems, speed of solution, and goodness of solutions (for optimization problems).

...

Dates
  • Registration opens: 1 May 2012.
  • Problem submission deadline: 12 July 2012.
  • Initial submission round begins: 1 August 2012.
  • Initial submission round ends: 20 August 2012.
  • Final submissions: 1 September 2012.
  • Announcement of results at CP2012: 8-12 October 2012.
For more about the result of the last year MiniZinc Challenge: MiniZinc Challenge 2011 Results.

March 31, 2012

Gecode version 3.7.3 released

Gecode version 3.7.3 has been released.

From the ChangeLog:
This release fixes some small bugs in the FlatZinc interpreter and library.
  • Gecode/FlatZinc
    • Additions
      • Added mzn-gecode scripts for conveniently solving MiniZinc models using the Gecode FlatZinc interpreter. (minor)
    • Other changes
      • Removed the print command line option. Instead, for optimization problems, using -a will print all solutions, while not using -a will only print the last one. This is consistent with the G12 FlatZinc command line interface. (minor)
    • Bug fixes
      • Fixed "largest" variable selection strategy for set variables. (minor, thanks to Marco Correia)
      • Fixed the parser for set literals. (minor, thanks to Thibaut Feydy)
      • Integer variables with empty domains result in unsatisfiable models instead of an error message. (minor)
      • Support 0-length array declarations. (minor)

March 26, 2012

My talk about Constraint Programming at Google (Paris)

The presentation can be downloaded here: google_talk_20120323.ppt.

In late January this year, I was invited by Laurent Perron - head of the or-tools group - to talk about my view on Constraint Programming and my experience with the or-tools system (I have done quite a few models using the Python, Java, and C# interfaces).

The talk was this Friday (March 23) at the Google's Paris office. It was a lovely day but unfortunately I got a common cold the day before so it was little hard to enjoy all the things Paris can offer.

Friday started with Laurent and me just talking about CP in general, and or-tools in particular and it was really fun and interesting. Later on we where joined by two other guests: Charles Proud'Homme and Nicolas Beldiceanu, both from Ecole des Mines de Nantes and it was great talking with them as well and, above all, listen when they discussed various CP things.

The Google office in Paris was very impressive, very high ceilings and seemed to be build to get lost easily (though neither of us quests got completely lost).

At 1400 I started the talk in front of an audience of about 20 engineers at the Google office (+ the two guests from Ecole des Mines de Nantes) and I think it went quite well considering the cold and all. It was recorded for internal use at Google. I don't know how public it will be but I will blog about this when it has been edited etc. After the 50 minutes talk there was a little Q/A session.

Thanks Laurent for the invitation and a memorable day.

Little more about the talk

The talk was aimed for programmers that don't know very much about Constraint Programming and I especially wanted to convey my own fascination about CP by using this agenda:
  • Introducing the principles of CP (very simplified)
  • Showing the declarativeness of CP by some code in the high level G12 MiniZinc and then in or-tools Python, C#, and sometimes Java.
  • The basic principle of propagation of constraints and domains is shown via a very simple 4x4 Sudoku problem.
  • After that, some of - IMHO - the most fascinating concepts in modeling CP where presented:
    • Global constraints
    • Element constraint
    • Reification
    • Bi-directedness
      Note: After the talk Nicolas Beldiceanu commented that this is more known as "reversibility" in the Prolog world.
    • 1/N/All solutions
    • Symmetry breaking
Here is the talk: google_talk_20120323.ppt.

I would like to thank the following for various degrees of comments, suggestions, and encouragement regarding the presentation:
  • Magnus Bodin
  • Carl Mäsak
  • Mikael Lagerkvist
  • Christian Schulte
  • Laurent Perron
  • Alastair Andrew
And a special thanks to Nikolaj van Omme for his very detailed comments.

March 16, 2012

G12 MiniZinc version 1.5 released

MiniZinc version 1.5 has been released. It can be downloaded here.

From the NEWS:
G12 MiniZinc Distribution 1.5
-----------------------------

* G12/CPX solver

We have added the solver G12/CPX (Constraint Programming with eXplanations) to the distribution. G12/CPX is the successor to the LazyFD solver. The FlatZinc interface to G12/CPX is named fzn_cpx and MiniZinc models can be solved with G12/CPX using mzn-g12cpx, for example to solve the model foo.mzn using G12/CPX, do

$ mzn-g12cpx foo.mzn

The existing LazyFD solver is now deprecated and will be removed in a future release.

Changes to the MiniZinc language:

* We have added some new built-in functions to assist with formatting complex output: show_int/2, show_float/3, join/2 and concat/1.

* We have added two new built-in functions, show_int/2 and show_float/3, to assist with formatting complex output.

* The built-in annotation is_output/0 is no longer supported.

* The built-in functions sum/1, product/1, forall/1, exists/1, xorall/1 and iffall/1 now also work with multi-dimensional arrays.


Changes to the FlatZinc language:

* We have added two new FlatZinc built-ins: bool_lin_eq/3 and bool_lin_le/3.


Other changes in this release:

* The following new global constraints have been added to the MiniZinc library:
    circuit
    subcircuit

Bugs fixed in this release:

* mzn2fzn now supports flattening expressions containing the built-in operation abort/1.

* mzn2fzn no longer turns optimisation problems that have a fixed objective into satisfaction problems. [Bug #277]

* The FlatZinc interpreter's MIP backend no longer aborts in the presence of a constant assignment to the objective variable. [Bug #319]

* The FlatZinc interpreter's FD backend no longer erroneously reports unsatisfiability in the presence of a constant assignment to the objective variable. [Bug #319]

* mzn2fzn now correctly reports that the built-in fix operation has aborted if given an argument that is not fixed. [Bug #158]

* A bug in mzn2fzn that caused it to not completely flatten array expressions in var array lookups has been fixed. [Bug #318]

* A bug that caused the FlatZinc interpreter to not indicate that search was complete for optimization problems has been fixed.
Quite a few of my MiniZinc models contain is_output (now not supported). I will update to them to the current version as soon as possible.

March 14, 2012

Tom Schrijvers, Guido Tack et.al: Search Combinators - paper and implementation

A paper and an implementation of Search Combinators - a framework to define application-tailored search strategies - has been available.

Paper

The paper is:
Tom Schrijvers, Guido Tack, Pieter Wuille, Horst Samulowitz, Peter J. Stuckey: Search Combinators (ArXiv). Abstract:
The ability to model search in a constraint solver can be an essential asset for solving combinatorial problems. However, existing infrastructure for defining search heuristics is often inadequate. Either modeling capabilities are extremely limited or users are faced with a general-purpose programming language whose features are not tailored towards writing search heuristics. As a result, major improvements in performance may remain unexplored. This article introduces search combinators, a lightweight and solver-independent method that bridges the gap between a conceptually simple modeling language for search (high-level, functional and naturally compositional) and an efficient implementation (low-level, imperative and highly non-modular). By allowing the user to define application-tailored search strategies from a small set of primitives, search combinators effectively provide a rich domain-specific language (DSL) for modeling search to the user. Remarkably, this DSL comes at a low implementation cost to the developer of a constraint solver.
The article discusses two modular implementation approaches and shows, by empirical evaluation, that search combinators can be implemented without overhead compared to a native, direct implementation in a constraint solver.

Implementation

An implementation using MiniZinc and Gecode is available from Gecode's FlatZinc page. The README file describes the tools as:
These two tools [minizinc-to-minizinc pre-compiler and FlatZinc interpreter], together with the G12 mzn2fzn translator, comprise a complete toolchain for solving MiniZinc models using search combinators. The pre-compiler translates a slightly extended version of MiniZinc to standards-compliant MiniZinc. The FlatZinc interpreter was modified to understand search combinators expressed as annotations.

In order to use the tools, you will need the standard mzn2fzn compiler from the G12 MiniZinc distribution, which can be downloaded at http://www.g12.cs.mu.oz.au/minizinc/download.html

Example

Two examples are included in the distribution: golomb.mzn and radiation.mzn. The golomb.mzn is shown here, where the specific changes has been marked:
include "globals.mzn";
include "searchcombinators.mzn";

int: m;
int: n = m*m;

array[1..m] of var 0..n: mark;
array[1..(m*(m-1)) div 2] of var 0..n: differences =
    [ mark[j] - mark[i] | i in 1..m, j in i+1..m];

constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
constraint alldifferent(differences);

% Symmetry breaking
constraint differences[1] < differences[(m*(m-1)) div 2];

solve :: dicho(print(mark,int_search(mark,input_order,assign_lb)),
            mark[m],
            0,200)
            satisfy;
The result using the included data file golomb-10.dzn (m=10) is
{0, 1, 3, 7, 12, 20, 30, 44, 65, 80}
{0, 1, 3, 11, 17, 29, 36, 51, 56, 60}
{0, 1, 6, 10, 23, 26, 34, 41, 53, 55}
I have just started to experiment with this and might return with a longer report.

March 09, 2012

JSR-331 is now an official standard

Jacob Feldman wrote in JSR-331 is now an official standard!:
JSR-331 successfully passed the Final Approval Ballot. The JCP Executive Committee that includes representatives of IBM, RedHat, Fujitsu, Intel, SAP, Eclipse, HP, and others voted “Yes” on the Final Release that we submitted in January. Nobody voted “No” or “Abstained”. I even received personal emails from representatives of Oracle and Twitter who apologized for missing the voting deadline – they congratulated us and wrote they would vote “Yes” too.

...

We currently have 3 working JSR-331 implementations based on these open-sourced CP solvers: Choco, JaCoP, and Constrainer. Several more CP vendors expressed their intention to provide JSR-331 implementations too. I expect that this year we will receive and make publicly available implementations from these teams:

IBM CP Optimizer (Jean-Francois Puget and Paul Shaw)
Cream (Naoyuki Tamura)
JSetL (Federico Bergenti)
JOpt (Nick Coleman).
Congratulations!

Also see: I tested a beta version of JSR-331 a while ago and implemented my standard "learning models". I like this framework, but I haven't yet adapted all my models to the final version so it's a forthcoming project to blog about it in more details. (Two of my models are included in the distribution: YoungTableaux.java and WhoKilledAgatha.java.)

March 07, 2012

SweConsNet'12 (Örebro, Sweden, May 14th 2012)

From the announcement of SweConsNet'12 - The Eleventh SweConsNet Workshop:
SweConsNet is the Network for Sweden-based researchers and practitioners of Constraint technology.

Following the previous successful workshops, we would like to announce the 11th SweConsNet workshop, which will take place in Örebro, Sweden on May 14th 2012. The workshop is organized in collocation with the 27th annual workshop of the Swedish Artificial Intelligence Society (SAIS).

The purpose of this workshop is to learn about ongoing research in constraint programming, as well as existing projects and products. We will also discuss the further development of the network, such as a possible widening to other Nordic countries.

The workshop is open to everybody interested in the theory and practice of constraint programming, whether based in Sweden or elsewhere. The scope of the workshop spans all areas of Constraint Programming, and is open to presentations and discussions addressing topics related to both theory and application.

Please forward a link of this page to people who might be interested but are not yet on the SweConsNet mailing list. They can subscribe to it by sending a message to Justin.Pearson at it.uu.se .

We hope for your participation, and highly encourage you to submit a proposal for a presentation of your ongoing work, recent results, or of a relevant discussion topic. There are no paper submissions, reviews, or proceedings, hence recent conference/journal papers may also be presented.

To register, please send a brief statement of intent, and desirably the title and abstract of your talk, to Christian Schulte (cschulte at kth.se). In order to facilitate organization, please notify us of your intention to participate as soon as possible, and at the latest before April 30th, 2012. The workshop does not have a registration fee.

Preliminary list of speakers

  • Mats Carlsson, SICS. On the Reification of Global Constraints. Joint Work with: Nicolas Beldiceanu (EMN, Nantes, France), Pierre Flener and Justin Pearson (Uppsala University).
  • Roberto Castañeda Lozano, SICS & KTH - ICT. Code Generation is a Constraint Problem. Joint work with: Mats Carlsson (SICS), Frej Drejhammar (SICS), Christian Schulte (KTH - ICT, SICS).
  • Maria Andreina Francisco Rodriguez, Uppsala University. Consistency of Automaton-Induced Constraint Decompositions. Joint work with: Pierre Flener and Justin Pearson (Uppsala University).
  • Håkan Kjellerstrand. Comparison of >= 14 CP systems - and counting.
  • Krzysztof Kuchcinski, Lund University. TBD.
  • Federico Pecora, Örebro University. Constraint-based methods for multiple non-holonomic vehicle scheduling and control.
As you see, I plan to compare different CP systems, which will be the systems listed in Common CP Problems. Perhaps also some not yet on that list, candidates are Numberjack, JSR-331, and Scampi.

For a taste of earlier workshops, see SweConsNet:Workshops, and general information about SweConsNet.

March 04, 2012

Talk at Google, Paris (France): My view on Constraint Programming

I'm very honored to announce that I have been invited by Laurent Perron (Google or-tools) to talk about my view on Constraint Programming at Google, Paris later this month.

The talk will be about Constraint Programming and what is so fascinating about it, including - of course - examples in or-tools (which I have tested and modeled in for the Python, Java - and now lately - C# interfaces). There will also be more general views about CP and perhaps comparisons between different CP systems. The audience will be the engineers at Google (Paris) which makes it an extra challenge (and fun). It will also be really great to meet the or-tools group.

After the event I will blog about the details, including publishing the slides.

Also see: My or-tools page.

March 03, 2012

Some newer models (most in MiniZinc, some in or-tools/C#)

For a time I have not blogged about all models I've created, instead just tweeted about them (I'm hakankj at Twitter). And sometimes not even than, just published them directly on my <CP system> pages without any noise.

Well, here I have collect some of these newer and unblogged models in - roughly - time order. Most are in MiniZinc (since I often use MiniZinc for prototyping) but there are also some in other systems. (See Constraint Programming for a list of these CP systems pages.)

  • xkcd_among_diff_0.mzn: Xkcd problem using among_diff_0
    This is another approach of the Xkcd "knapsack problem" where the object is to order dishes for an amount of exactly 15.05.
    This version where inspired by a comment in Helmut Simonis presentation Acquiring Global Constraint Models (page 3), where he use the global constraint among_diff_0 ("Count how many variables are different from 0")
    However, my implementation differs in some ways:
    • it use integers instead of floats.
    • it implements a slightly more general approach
    For more about the global constraint among_diff_0: see my MiniZinc model among_diff_0.mzn. Also see xkcd.mzn, my first approach of the problem.

  • monorail.mzn: Monorail puzzle
    From Aaron Iba's Blog Users of my iOS Game Teach Me a Lesson MIT Didn't:
    The object of Monorail puzzles is to complete a closed-circuit loop through all the stations (dots) by drawing rails. The loop must pass through each station exactly once and close back on itself, like an actual monorail system might in a city.
    Problem:
    
        .   .   .   .       1  2  3  4
    
        .   .___.   .       5  6  7  8
            |
        .   .   .   .       9 10 11 12
    
        .   .___.   .      13 14 15 16
     
    Solution:
        .__.___.___.
        |          |
        .  .___.___.
        |  | 
        .  .___.___.
        |          |
        .__.___.___.
    
    
    Also see
    Problem instances:

  • dennys_menu.mzn
    From Mind Your Decisions (about game theory and personal finance) Denny's math commercial:
    So there’s the question: how many different price combinations will total $10 when menu items priced at $2, $4, $6, and $8?

  • Some Rosetta Code implementations of various knapsack problems


  • Newspaper problem (job-shop)
    Implementations:
    Problem statement from Snehal Patel's CS course
    There are four students: Algy, Bertie, Charlie and Digby, who share a flat. Four newspapers are delivered to the house: the Financial Times, the Guardian, the Daily Express and the Sun. Each of the students reads all of the newspapers, in particular order and for a specified amount of time (see below). Question: Given that Algy gets up at 8:30, Bertie and Charlie at 8:45 and Digby at 9:30, what is the earliest that they can all set off for college?
         Algy           Bertie        Charlie      Digby
    1st  FT       60    Guardian 75   Express  5   Sun      90
    2nd  Guardian 30    Express   3   Guardian 15  FT        1
    3rd  Express   2    FT       25   FT       10  Guardian  1
    4th  Sun       3    Sun      10   Sun      30  Express   1
    
    Extra requirements: All reads the newspaper in a specific order:
    - Algy order   : - FT, Guardian, Express, Sun
    - Bertie order : - Guardian, Express, FT, Sun
    - Charlie order: - Express, Guardian, FT, Sun
    - Digby order  : - Sun, FT, Guardian, Express
    
    This origin of this problem is from S. French: "Sequencing and Scheduling : an introduction to the mathematics of the job-shop", Ellis Horwood Limited, 1982.

    Tim Duncan wrote about it in his paper "Scheduling Problems and Constraint Logic Programming: A Simple Example and its Solution", AIAI-TR-120, 1990, page 5. The paper also includes a program in CHIP solving the problem.)

    Two versions differs by that the first (newpaper0.mzn) is not loaded with so much output stuff as the latter (newpaper.mzn).

  • schedule2.mzn
    Problem from Dennis E. Sasha's book "Puzzles for Programmers and Pros", page 131f:
    In which order do you schedule the tasks starting from current
    day 0?:
    Task  T1 takes 4 days with deadline on day 45
    Task  T2 takes 4 days with deadline on day 48
    Task  T3 takes 5 days with deadline on day 25
    Task  T4 takes 2 days with deadline on day 49
    Task  T5 takes 5 days with deadline on day 36
    Task  T6 takes 2 days with deadline on day 31
    Task  T7 takes 7 days with deadline on day 9
    Task  T8 takes 5 days with deadline on day 39
    Task  T9 takes 4 days with deadline on day 13
    Task T10 takes 6 days with deadline on day 17
    Task T11 takes 4 days with deadline on day 29
    Task T12 takes 1 days with deadline on day 19
    


  • Some Project Euler problems
    Whenever I learn a new programming language, I tend to solve at least the first - say - 20 Project Euler problems. Unfortunately many of the problems requires arbitrary precision or recursive approaches, and neither has good support in MiniZinc. Here are some of the problems:

  • hitting_set.mzn
    From MathWorld: VertexCover
    Let S be a collection of subsets of a finite set X. A subset Y of X that meets every member of S is called the vertex cover, or hitting set. The smallest possible such subset for a given graph G is known as a minimum vertex cover (Skiena 1990, p. 218), and its size is called the vertex cover number, denoted tau(G).
    This model some different problem instances, for example those from the cited article above but also from other sources

    By the way, this model was implemented after I read the paper There is no 16-Clue Sudoku: Solving the Sudoku Minimum Number of Clues Problem by Gary McGuire, Bastian Tugemann, and Gilles Civario. The abstract states: We apply our new hitting set enumeration algorithm to solve the sudoku minimum number of clues problem, which is the following question: What is the smallest number of clues (givens) that a sudoku puzzle may have? [...]
  • maximal_independent_sets.mzn
    From Wikipedia: Maximal independent set:
    In graph theory, a maximal independent set or maximal stable set is an independent set that is not a subset of any other independent set. That is, it is a set S such that every edge of the graph has at least one endpoint not in S and every vertex not in S has at least one neighbor in S. A maximal independent set is also a dominating set in the graph, and every dominating set that is independent must be maximal independent, so maximal independent sets are also called independent dominating sets.

    A graph may have many maximal independent sets of widely varying sizes; a largest maximal independent set is called a maximum independent set.
    The model contains a few problem instances, e.g. those from the above cited Wikipedia article.
    Also see Wikipedia Independent set (graph theory), and compare with the MiniZinc model misp.mzn which use another representation and approach (inspired from GLPK:s model).

  • magic_square_frenicle_form.mzn
    From Wikipedia Frénicle standard form
    A magic square is in Frénicle standard form, named for Bernard Frénicle de Bessy, if the following two conditions apply:
    - the element at position [1,1] (top left corner) is the smallest of the four corner elements; and
    - the element at position [1,2] (top edge, second from left) is smaller than the element in [2,1].
    Activating all these constraints we get the "standard" way of counting the number of solutions:
    (1), 0, 1, 880, 275305224
    
    which is the sequence A006052 from the excellent Online Encyclopedia of Integer Sequence

    Without these symmetry constraints the number of solutions are:
    N  #solutions
    -------------
    1     1
    2     0
    3     8
    4  7040
    5  many...
    
    (Counting the number of the solutions of a CP model is a very good way of ensuring that the model is correct, or rather: if the number of the solutions are not the expected, then the model is wrong.)

  • scheduling_with_assignments.mzn
    This was done directly after I've done the newspaper.mzn (see above). It then struck me that most examples I've seen of scheduling in Constraint Programming (especially when demonstrated the works of cumulative), just showed the times of the jobs not the assignments of the workers.
    In this model, both the job assignments and the worker assignments are shown in different way. For example the solution of one of my own standard problem furniture_moving.mzn (from Marriott and Stuckey: "Programming with constraints", page 112f) is shown as
    earliest_end_time: 60
    num_jobs   : 4
    num_workers: 4
    start_time : [0, 0, 30, 45]
    duration   : [30, 10, 15, 15]
    end_time   : [30, 10, 45, 60]
    resource   : [3, 1, 3, 2]
    allow_idle : true
    collect_workers : false
    do_precendences: false
    
    Assignment matrix (jobs/workers):
    Job1: 1 0 1 1
    Job2: 0 1 0 0
    Job3: 1 0 1 1
    Job4: 1 1 0 0
    
    Assignment matrix (workers/jobs):
    Worker1: 1 0 1 1
    Worker2: 0 1 0 1
    Worker3: 1 0 1 0
    Worker4: 1 0 1 0
    
    Time range for the jobs and the assigned worker(s):
    Job1(0..30): 1 3 4 
    Job2(0..10): 2 
    Job3(30..45): 1 3 4 
    Job4(45..60): 1 2 
    
    ....
    
    Schedule: worker(job), timeline: (earliest_end_time: 60)
    Worker: 1:    1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4 
    Worker: 2:    2  2  2  2  2  2  2  2  2  2  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4 
    Worker: 3:    1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
    Worker: 4:    1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
    
    Time:         0  1  2  3  4  5  6  7  8  9  10 1  2  3  4  5  6  7  8  9  20 1  2  3  4  5  6  7  8  9  30 1  2  3  4  5  6  7  8  9  40 1  2  3  4  5  6  7  8  9  50 1  2  3  4  5  6  7  8  9  
    
    The model presents:
    • start time, duration, and end time for all jobs
    • assignment matrix jobs/workers
    • assignment matrix workers/jobs
    • jobs with time range, and the assigned workers
    • schedule (time line in time units) for the jobs, showing the assigned worker
    • schedule (time line) for the workers, showing the time the workers work
    • and last, a Gantt like schedule showing which job each worker is scheduled to to in each time.

    The model also have some other "bells & whistles" such as
    • handling precedences
    • modeling as a bin pack problem
    • "collecting workers", which may be useful for certain problem, such as perfect square placements

    The two last "features" shows that the job scheduling problem has a family resemblance with bin pack and perfect square placement problem. Unfortunately these are not very fast in this model.

    Well, since I plan to blog about this more, including a benchmark, I leave it for now.

    Here are the problems instances. They has been taken from various sources:

  • equal_sized_groups.mzn
    This is a problem from or-exchange (where many from the area of Operations Research hang out): dividing into roughly equal sized groups, with a sorted list
    I have a problem, and it seems like it should be something that someone has studied before. I have a sorted list of N elements, and I want to divide them into K groups, by choosing K-1 split points between them. There may be elements with the same value, and we want to have items with same value in the same group. Find K groups as close in size to round(N/K) as possible.

    For example, divide these 32 elements in to 4 groups of size 8:
     1 1 1 1 2 2 3 3 3 3 3 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 7 8 9 10 10
    
    One solution would be these 3 break points:
     
     1 1 1 1 2 2 | 3 3 3 3 3 3 3 3 | 4 4 4 4 5 5 5 5 5 | 6 6 6 6 7 8 9 10 10
    [            6                 14                 23                    ]
    [    6 elts      8 elts               9 elts              9 elts          ]
     
     1 1 1 1 2 2         = 6 elements,  error = abs(8-6)=2
     3 3 3 3 3 3 3 3     = 8 elements,  error = abs(8-8)=0
     4 4 4 4 5 5 5 5 5     = 9 elements,  error = abs(8-9)=1
     6 6 6 6 7 8 9 10 10 = 9 elements,  error = abs(8-9)=1
     
     total error = 4
    
    Does this look familiar to anyone? I'd like an approximation algorithm if possible.

    Thanks, Craig Schmidt
    The model contains some examples and results.

  • houses.mzn
    Problem from a Kanren example: houses.scm
    Taken from _Algebra 1_, Glencoe/McGraw-Hill, New York, New York, 1998 pg. 411, Problem 56

    There are 8 houses on McArthur St, all in a row. These houses are numbered from 1 to 8.

    Allison, whose house number is greater than 2, lives next door to her best friend, Adrienne. Belinda, whose house number is greater than 5, lives 2 doors away from her boyfriend, Benito. Cheri, whose house number is greater than Benito's, lives three doors away from her piano teacher, Mr. Crawford. Daryl, whose house number is less than 4, lives 4 doors from his teammate, Don. Who lives in each house?
    One thing to note is the use of the global constraint inverse for channeling the each person to the houses and vice versa.

  • Finding an optimal wedding seating chart
    This problem has been implemented in both MiniZinc and or-tools/C#:
    The problem is from Meghan L. Bellows and J. D. Luc Peterson Finding an optimal seating chart for a wedding (PDF), via Improbable Research Finding an optimal seating chart for a wedding:
    Every year, millions of brides (not to mention their mothers, future mothers-in-law, and occasionally grooms) struggle with one of the most daunting tasks during the wedding-planning process: the seating chart. The guest responses are in, banquet hall is booked, menu choices have been made. You think the hard parts are over, but you have yet to embark upon the biggest headache of them all. In order to make this process easier, we present a mathematical formulation that models the seating chart problem. This model can be solved to find the optimal arrangement of guests at tables. At the very least, it can provide a starting point and hopefully minimize stress and arguments…
    As mentioned before (e.g. in A matching problem, a related seating problem, and some other seating problems) I'm quite fascinated by this type of seating problems.

    And I'm not the only one. After I tweeted about my MiniZinc implementation (wedding_optimal_chart.mzn), Erwin Kalvehagen (with the excellent blog Yet Another Math Programming Consultant showed a GAMS (MIP) model in Weddings and optimal seating . (He also found a bug in my model which was fixed quite easily. Thanks Erwin.)
  • grime_puzzle.mzn
    This problem was taken from the blog Travels in a mathematical world A puzzle from James Grime about abcdef:
    Today James Grime tweeted this question/puzzle:

    Is there a six digit number abcdef such that the following all hold?

    a+b+c+d+e+f = y
    ab+cd+ef=10y
    abc+def=100y


    If not, show why not.

    A little tweeting back and forth verified that "ab" means 10a+b not a×b.

  • balanced_brackets.mzn
    This model generates balanced brackets of size m*2. The number of generated solutions for m:
     m        #
     ----------
     1       1
     2       2
     3       5
     4      14
     5      42
     6     132
     7     429
     8    1430
     9    4862
    10   16796
    11   58786
    12  208012
    13  742900
    
    Which - of course - is the Catalan numbers. See OEIS: 1,2,5,14,42,132,429,1430,4862,16796,58786,208012, and the entry for Catalan numbers: A000108.

  • The "8809 = 6" puzzle
    This problem has been encoded in both MiniZinc and or-tools/C# (and was created yesterday):
    The problem seems to have been around for a couple of years, but it wasn't until I read about it in another excellent blog (Michael Lugo's God Plays Dice): A puzzle that I really tried it (and was lucky to solve it direct without any computational aid). The problem was stated thus:
     
    Here’s a puzzle.
    
    8809 = 6
    7662 = 2
    9312 = 1
    8193 = 3
    8096 = 5
    7756 = 1
    6855 = 3
    9881 = 5
    
    2581 = ?
    
    After a few days a mathematical solution came in the blog post: An answer to a puzzle, but then the problem had been expanded a little:
    8809 = 6
    7111 = 0
    2172 = 0
    6666 = 4
    1111 = 0
    3213 = 0
    7662 = 2
    9312 = 1
    0000 = 4
    2222 = 0
    3333 = 0
    5555 = 0
    8193 = 3
    8096 = 5
    7777 = 0
    9999 = 4
    7756 = 1
    6855 = 3
    9881 = 5
    5531 = 0
    
    2581 = ?
    
    The first version of the problem actually has two different solutions (of the unknown "?", represented as x in the models), since some of the variables are under defined. The second version has a unique solution of x, but there are 10 slightly different solutions since one of the variables is (still) under defined, i.e. the x is the same in all these solutions.

    The approach in my models was inspired by Michael Lugo's mathematical solution (as an equation system), though the or-tools/C# model implements another version using a matrix to represent the problem.

February 27, 2012

Gecode version 3.7.2 released

Gecode version 3.7.2 has been released. It can be downloaded here.

From the Changelog:
Changes in Version 3.7.2 (2012-02-27)

This release fixes several small bugs.

  • Kernel
    • Additions
      • Added Archive operators for floats and doubles. (minor)
  • Finite domain integers
    • Other changes
      • Throw exception of type OutOfLimits instead of Exception when numerical arguments to sequence constraint are out of range. (minor)
    • Bug fixes
      • Added missing pruning to cumulative edge finding propagator. (minor, thanks to Joseph Scott)
      • Fixed sorted constraint to accept zero-length arrays. (minor, thanks to Kish Shen)
      • Added some missing propagation when posting a channel constraint between an array of Boolean variables and an integer variable. (minor, thanks to Kish Shen)
    • Performance improvements
      • Posting a reified dom constraint on IntVars with an assigned control variable does not create propagators any more, but updates the domain immediately. (minor)
  • Finite integer sets
    • Bug fixes
      • The element constraint with SOT_UNION and IntSetArgs reported subsumption too early, resulting in incorrect propagation. (major, thanks to Denys Duchier)
  • Minimal modeling support
    • Bug fixes
      • The BoolExpr default constructor did not properly initialize its members, causing crashes. (minor)
  • Script commandline driver
    • Bug fixes
      • Fixed rounding for printing the runtime (for example, 1:60:56.157 could be printed...). (minor, thanks to Serge Le Huitouze)
      • Fixed time output for times with zero minutes but nonzero hours. (minor, thanks to Jan Kelbel)
  • Gecode/FlatZinc
    • Bug fixes
      • Export RTTI symbols for the FlatZinc AST so that it can be used by client code. (minor)
      • Do not crash when encountering undefined identifier as constraint argument. (minor, thanks to Nicholas Tung)
  • General
    • Additions
      • Gecode now compiles on NetBSD. (minor, thanks to Adam Russell)
      • Added a macro GECODE_VERSION_NUMBER that is defined as x*1000000+y*100+z for Gecode version x.y.z. (minor, thanks to Denys Duchier)

Recent comments

Twitter tweets

Powered by
Movable Type 3.2