Edit: The slides of my invited talk at WLP 2009 on Monadic Constraint Programming are now available.
Abstract:
A constraint programming system combines two essential components: a constraint solver and a search engine. The constraint solver reasons about satisfiability of conjunctions of constraints, and the search engine controls the search for solutions by iteratively exploring a disjunctive search tree defined by the constraint program. In this paper we give a monadic definition of constraint programming where the solver is defined as a monad threaded through the monadic search tree. We are then able to define search and search strategies as first class objects that can themselves be built or extended by composable search transformers. Search transformers give a powerful and unifying approach to viewing search in constraint programming, and the resulting constraint programming system is first class and extremely flexible.
Let's briefly look at the n queens example from the paper. First, there is the nqueens model:
nqueens n = exist n $ \queens -> model queens n /\
enumerate queens
model queens n = queens ‘allin‘ (1,n) /\
alldifferent queens /\
diagonals queens
allin queens range = conj [q ‘in_domain‘ range | q <- queens ] alldifferent queens = conj [ qi @\= qj | qi:qjs <- tails queens, qj <- qjs ] diagonals queens = conj [ qi @\== (qj @+ d) /\ qj @\== (qi @+ d) | qi:qjs <- tails queens, (qj,d) <- zip qjs [1..]] conj = foldl (/\) true
The enumeration of possible values can be quite sophisticated, e.g.
enumerate = Lazy . (label firstfail middleout)
where firstfail selects the queen with the smallest
domain first, and middleout selects the middle values
in the domain first. You can easily write custom variable and
value selection strategies, or alternative enumeration functions.
To actually compute solutions, we have to solve the model:
> solve dfs it $ nqueens 4
[[2,4,1,3],[3,1,4,2]]
i.e. we yields these two solutions of 4 queens:


The search strategy used above is depth-first search (dfs) without
any additional search transformers (i.e. identity transformer it).
Here are three variations, using alternative search strategies:
> solve dfs (nb 100 :- db 25 :- bb newBound) $ nqueens 4
> solve bfs (db 25 :- nb 100 :- bb newBound) $ nqueens 4
> solve bfs (ld 10 :- nb 100 :- bb newBound) $ nqueens 4
where
- bfs is the breadth-first queueing strategy,
- nb n stops search after visiting n nodes in the search tree,
- dbn does not visit nodes below depth n in the search tree,
- ld n does not visit nodes that are more than n right branches from the root of the search tree (limited discrepancy), and
- bb newBound is branch-and-bound optimization (in this example the value of the last queen is minimized; makes more sense for other problems).
The :- operator combines the various (composable) search transformers. The purpose of these search transformers is of course to find (all, one, the best) solutions more quickly.
More
- Draft paper
- Prototype code (requires GHC >= 6.10)
Your feedback is appreciated.
7 comments:
I read your paper and it's very interesting, i'm looking at the code to grasp the details now.
By the way, is there also a darcs repo for the code?
U'm mainly interested since i'd like to write a flexible and complete dependency solver for cabal-install, it needs something equivalent to soft or valued constraints, but i guess those can be implemented with the branch and bound transformer.
Hi Saizan,
> I read your paper and it's very interesting, i'm looking at the code to
> grasp the details now.
Thanks!
> By the way, is there also a darcs repo for the code?
No. I'm willing to put it somewhere for interested people to extend. Is
there a Haskell code hosting service you can recommend?
> U'm mainly interested since i'd like to write a flexible and complete
> dependency solver for cabal-install, it needs something equivalent to
> soft or valued constraints, but i guess those can be implemented with
> the branch and bound transformer.
Can you tell me a bit about the this problem and the optimization aspect
involved?
Cheers,
Tom
For the repo you can ask for an account here http://community.haskell.org/
For the problem the description is too lengthy for this comment box so i've put it on hpaste :)
http://hpaste.org/13776
Hi Tom & his readers (heh),
This is an excellent draft, I really enjoyed reading it.
I had written (many months ago, on a computer which has gone of our world) a solver for the nqueens problem and that was not as elegant as your solution... Moreover, you describe a very interesting method.
I'll try to apply it during the upcoming days.
I really thank you for this article.
Thanks a lot for your interest, Alp.
Please let us (me and my readers ;-) know how it goes with your appplication.
Cheers,
Tom
Really nice piece of software. I enjoyed J. M. Spivey and S. Seres' "Embedding Prolog in Haskell" a lot and I always wondered if it could be extended to constraint programming. Now I just have the answer :)
On Page 1, ... its principal job _is_ to determine unsatisfiability of a conjunction.
Post a Comment