Skip to content
Constraint Logic Programming
step 1/4

Reading — step 1 of 4

Learn

~2 min readDCG, CLP, Meta-Programming

CLP(FD) (Constraint Logic Programming over Finite Domains) lets Prolog solve constraint problems — Sudoku, scheduling, puzzles. The constraint #= works in BOTH directions — "X + 3 = 7" can solve for X.

Not in GNU Prolog by default — SWI-Prolog has library(clpfd). We'll demo the concept.

Comparison

Standard Prolog arithmetic (is/2):

?- X is 5 + 3.
X = 8.

?- 8 is X + 3.       %% ERROR — X must be bound

CLP(FD) constraint (#=):

:- use_module(library(clpfd)).

?- X #= 5 + 3.
X = 8.

?- 8 #= X + 3.       %% works! X = 5.

?- X + Y #= 10, X #> 0, Y #> 0, label([X, Y]).
X = 1, Y = 9 ;
X = 2, Y = 8 ; ...   %% all valid pairs

Operators

  • #= — equal
  • #\= — not equal
  • #<, #>, #=<, #>= — comparison
  • #/\, #\/, #\ — boolean and/or/not
  • in/2 — domain: X in 1..10
  • ins/2 — multi-var domain: [X, Y, Z] ins 1..10
  • all_distinct/1 — all variables different
  • sum/3 — sum constraint
  • label/1 — search for solutions

Sudoku skeleton

:- use_module(library(clpfd)).

sudoku(Rows) :-
    length(Rows, 9),
    maplist(same_length(Rows), Rows),
    append(Rows, Vs),
    Vs ins 1..9,
    maplist(all_distinct, Rows),
    transpose(Rows, Cols),
    maplist(all_distinct, Cols),
    %% 3x3 boxes
    Rows = [As, Bs, Cs, Ds, Es, Fs, Gs, Hs, Is],
    blocks(As, Bs, Cs),
    blocks(Ds, Es, Fs),
    blocks(Gs, Hs, Is),
    maplist(label, Rows).

blocks([], [], []).
blocks([A,B,C|Bs1], [D,E,F|Bs2], [G,H,I|Bs3]) :-
    all_distinct([A,B,C,D,E,F,G,H,I]),
    blocks(Bs1, Bs2, Bs3).

This ~20 lines of CLP(FD) solves Sudoku. Without CLP(FD), you'd write a manual backtracking search — much longer.

SEND + MORE = MONEY

The classic crypto-arithmetic puzzle:

:- use_module(library(clpfd)).

puzzle :-
    Vars = [S, E, N, D, M, O, R, Y],
    Vars ins 0..9,
    all_distinct(Vars),
    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,
    label(Vars),
    format('~w + ~w = ~w~n',
           [[S,E,N,D], [M,O,R,E], [M,O,N,E,Y]]).

When CLP(FD) wins

  • Combinatorial puzzles
  • Scheduling and resource allocation
  • Constraint satisfaction (any CSP)
  • Mathematical reasoning where direction is unknown

Caveats

  • Need explicit label/1 to enumerate solutions
  • Performance can be wildly unpredictable
  • Only available in some Prologs (SWI, SICStus)

For real combinatorial work in Prolog, CLP(FD) is the right tool — modern, well-supported, and what most non-trivial Prolog applications use.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…