Title: Declarative Loops and List Comprehensions for Prolog
1Declarative Loops and List Comprehensions for
Prolog
- Neng-Fa Zhou
- Brooklyn College
- The City University of New York
- zhou_at_sci.brooklyn.cuny.edu
2Motivation
- Second ASP-solver Competition
- 38 problems were used
- The B-Prolog team was the only CLP(FD) team
- We had to develop solutions from scratch
- We desperately needed loop constructs
3One of the ProblemsMaze generation
- Conditions
- 1. There must be a path from the entrance to
every empty cell. - 2. There must be no 2x2 blocks of empty cells or
walls. - 3. No wall can be completely surrounded by empty
cells. -
4The Array Subscript Notation for Structures and
Lists in B-Prolog
- In arithmetic expressions
- In arithmetic constraints
- In calls to _at_ and _at_
- In any other context, XI1,,In is the same as
XI1,,In
S is X1X2X3
X1X2 X3
X1,2 _at_ 100X1,2 _at_ 100
5foreach(E1 in D1, . . ., En in Dn, Goal)
- Ei in Di
- Ei is a pattern (usually a variable but can be a
compound term) - Di is a collection (a list or a range of integers
l..u) - Semantics
- For each combination of values E1?D1, . . ., En ?
Dn, execute Goal
6Example-1
- Using foreach
- Using recursion
?- L1,2,3,foreach(X in L, write(X)).
- ?- L1,2,3,write_list(L).
- write_list().
- write_list(XT) - write(X), write_list(T).
7Example-2
- Using foreach
- Using recursion
?- foreach(X in 1..3, write(X)).
?- write_int_range(1,3). write_int_range(I,N)-IgtN
,!. write_int_range(I,N) - write(I), I1
is I1, write_int_range(I1,N).
8Example-3 (compound patterns)
- Using foreach
- Using recursion (matching clauses)
?-L(a,1),(b,2),foreach((A,I) in L,
writeln(AI)).
?- L(a,1),(b,2),write_pairs(L). write_pairs()
gt true. write_pairs((A,I)L) gt
writeln(AI), write_pairs(L).
9foreach(E1 in D1, . . ., En in Dn, LVars, Goal)
Variables in LVars are local to each iteration.
- Using foreach
- Using recursion
?-Sf(1,2,3), foreach(I in 1..Slengh,E, (E
_at_ SI, write(E))).
?-Sf(1,2,3),functor(S,_,N),write_args(S,1,N).wri
te_args(S,I,N)-IgtN,!.write_args(S,I,N)-
arg(I,S,E), write(E), I1 is I1,
write_args(S,I1,N).
10List Comprehension
T E1 in D1, . . ., En in Dn, LVars, Goal
- Calls to _at_/2
- Arithmetic constraints
?- L _at_ X X in 1..5.L1,2,3,4,5?-L _at_
(A,I) A in a,b, I in 1..2.L
(a,1),(a,2),(b,1),(b,2)
sum(AI,J I in 1..N, J in 1..N) NN
11foreach With Accumulators
L _at_ (A,I) A in a,b, I in 1..2 foreach(A
in a,b, I in 1..2, ac1(L,),
L0(A,I)L1)
12Application Examples
- Quick sort
- Permutations
- N-Queens
- Non-boolean constraints
- Boolean constraints
- Gaussian elimination
- No-Three-in-a-Line Problem
- Maze generation
13Quick Sort
qsort(,). qsort(HT,S)- L1 _at_ X X
in T, XltH, L2 _at_ X X in T, XgtH,
qsort(L1,S1), qsort(L2,S2),
append(S1,HS2,S).
14Permutations
perms(,). perms(XXs,Ps)-
perms(Xs,Ps1), Ps _at_ P P1 in Ps1, I in
0..Xslength,P,
insert(X,I,P1,P). insert(X,0,L,XL). insert(X
,I,YL1,YL)- Igt0, I1 is I-1,
insert(X,I1,L1,L).
15The N-Queens Problem
- Qi the number of the row for the ith queen.
- queens(N)-
- length(Qs,N),
- Qs 1..N,
- foreach(I in 1..N-1, J in I1..N,
- (QsI \ QsJ,
- abs(QsI-QsJ) \ J-I)),
- labeling(ff,Qs),
- writeln(Qs).
16The N-Queens Problem (Boolean Constraints)
- Qij1 iff the cell at (i,j) has a queen.
- bqueens(N)-
- new_array(Qs,N,N),
- Vars _at_ QsI,J I in 1..N, J in 1..N,
- Vars 0..1,
- foreach(I in 1..N,
- sum(QsI,J J in 1..N) 1),
- foreach(J in 1..N,
- sum(QsI,J I in 1..N) 1),
- foreach(K in 1-N..N-1,
- sum(QsI,J I in 1..N, J in 1..N,
I-JK) lt 1), - foreach(K in 2..2N,
- sum(QsI,J I in 1..N, J in 1..N,
IJK) lt 1), - labeling(Vars).
17Gaussian Elimination
18Gaussian Elimination
triangle_matrix(Matrix)- foreach(I in
1..Matrixlength-1, Row,J,
(select_nonzero_row
(I,I,Matrix,J)-gt (I\J-gt
(Row _at_ MatrixI,
MatrixI _at_ MatrixJ,
MatrixJ _at_ Row)
true ),
foreach(K in I1..Matrixlength,
trans_row(I,K,Matrix))
true ) ).
19No-Three-in-a-Line Problem
no3_build(N)- new_array(Board,N,N),
Vars _at_ BoardI,J I in 1..N, J in 1..N,
Vars 0..1, Sum sum(Vars), Sum lt
2N, foreach(X1 in 1..N, Y1 in 1..N, L,SL,
(L _at_ Slope X2 in 1..N, Y2 in
1..N, Slope,
(X2\X1,
Slope is (Y2-Y1)/(X2-X1)),
sort(L,SL), eliminate duplicates
foreach(Slope in SL,
sum(BoardX,Y X in
1..N, Y in 1..N,
(X\X1,Slope(Y-Y1)/(X-X1)))
lt 3))), foreach(X in 1..N, sum(BoardX,Y
Y in 1..N)lt3), labeling(SumVars),
outputBoard(Board,Sum,N).
20Maze generation
There must be no 2x2 blocks of empty cells or
walls foreach(I in 1..M-1, J in 1..N-1,
(MazeI,JMazeI,J1MazeI1,JMazeI1,J1gt
0, MazeI,JMazeI,J1MazeI1,JMazeI1
,J1lt4)),
21Demo
- B-Prolog version 7.4
- N-queens problem
- www.probp.com/examples.htm
22Conclusion
- Foreach and list comprehension constitute a
better alternative for writing loops - Recursion
- Failure-driven loops
- Higher-order predicates (e.g., findall,maplist)
- The do construct in ECLiPSe Prolog
- Very useful when used on arrays
- Significantly enhance the modeling power of
CLP(FD)