4 ms·
Constraint solvers are a great attraction of many Prolog systems, and in fact they are often an important reason for buying a fast commercial Prolog system. For
by triska 4y ago
Constraint solvers are a great attraction of many Prolog systems, and in fact they are often an important reason for buying a fast commercial Prolog system. For example, here is a solution of the first puzzle shown in the article, using Scryer Prolog and its CLP(ℤ) solver, i.e., constraint logic programming over integers:
:- use_module(library(clpz)).
solution(N) :-
N in 0..10_000,
N #= 13*_,
N #= 19*_,
N #= 37*_.
Note how seamlessly constraint programming blends into Prolog: We simply state these constraints as relations that must hold for logic variables, just as always in Prolog! In fact, plain Prolog can be regarded as a particular instance of constraint logic programming (CLP), namely as constraint logic programming over Herbrand terms, abbreviated as CLP(H).
Sample query and answer:
?- solution(N), indomain(N).
N = 0
; N = 9139.
We see from this answer that there are in fact two solutions to the puzzle: 0 and 9139. Prolog reports all solutions on backtracking.
A nice feature of the Scryer Prolog toplevel is that we can simply press "a" to enumerate all solutions. For example, if we increase the upper bound to 100_000 as mentioned in the course of the article, we get:
?- N in 0..100_000,
N #= 13*_, N #= 19*_, N #= 37*_,
indomain(N).
N = 0
; N = 9139
; N = 18278
; N = 27417
; N = 36556
; N = 45695
; N = 54834
; N = 63973
; N = 73112
; N = 82251
; N = 91390.
So, 11 solutions (not 10).
Hence, the sample code shown in the article should probably change:
model.NewIntVar(1, ...)
to
army = model.NewIntVar(0, ...)
in order to correctly model the equation shown before the code.
The knapsack problem shown in the article can also be easily expressed and solved:
?- Vs = [Bread,Meat,Beer],
Vs ins 0..sup,
Bread + 3*Meat + 7*Beer #=< 19,
Popularity #= 3*Bread + 10*Meat + 26*Beer,
labeling([max(Popularity)], Vs).
yielding solutions in decreasing order of popularity:
Vs = [2,1,2], Bread = 2, Meat = 1, Beer = 2, Popularity = 68
; Vs = [5,0,2], Bread = 5, Meat = 0, Beer = 2, Popularity = 67
; Vs = [0,4,1], Bread = 0, Meat = 4, Beer = 1, Popularity = 66
; Vs = [1,1,2], Bread = 1, Meat = 1, Beer = 2, Popularity = 65
; ... .
This answer shows that the optimal solution with popularity 68 is unique in this case. The program output in the article shows "3712 popularity", yet the text also mentions 68: The number 3712 stems from using 1_000 as the capacity.
It is notable how compactly and conveniently such tasks can be expressed and solved with Prolog.
- flobosg 4y ago> Hence, the sample code shown in the article should probably change (...) in order to correctly model the equation shown before the code. The equation should be 1 ≤ army ≤ 10000, since you cannot have an army of zero soldiers.