Constraint programming in SWI-Prolog - prolog

I want to have a list L with three elements A,B, and C with the following constraint,
:- use_module(library(clpfd)).
L[A,B,C], L ins 1..3, A#=B+C.
But, it gives an error - Syntax error: Operator expected.

Just answering, so that the question goes off the list of unanswered questions:
The error could be also the (:-)/2, not only the missing (=)/2. So the following
session wurks:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.11)
Copyright (c) 1990-2014 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
% library(occurs) compiled into occurs 0.00 sec, 14 clauses
% library(apply_macros) compiled into apply_macros 0.01 sec, 51 clauses
% library(assoc) compiled into assoc 0.01 sec, 103 clauses
% library(clpfd) compiled into clpfd 0.12 sec, 2,694 clauses
true.
?- L=[A,B,C], L ins 1..3, A#=B+C.
L = [A, B, C],
A in 2..3,
B+C#=A,
B in 1..2,
C in 1..2.
In the above we only got as far as stating a problem including equations
and variable ranges. To enumerate solutions one has to use
the label/2 predicate as well:
?- L=[A,B,C], L ins 1..3, A#=B+C, label(L).
L = [2, 1, 1],
A = 2,
B = C, C = 1
L = [3, 1, 2],
A = 3,
B = 1,
C = 2
L = [3, 2, 1],
A = 3,
B = 2,
C = 1.
Bye

Related

Turn List into number, increment the number, and then turn the number into a list

I have my head stuck in this exercise in prolog, I ve been trying to do it on my own but it just won't work. Example: ?-succesor([1,9,9],X) -> X = [2,0,0]. Had tried first to reverse the list and increment it with 1 and then do a if %10 = 0 the next element should be incremented too. Thing is that I m too used with programming syntax and I can't get my head wrapped around this.Any help would be appreciated.
I have done this so far, but the output is false.
%[1,9,9] -> 199 +1 -> 200;
numbers_atoms([],[]).
numbers_atoms([X|Y],[C|K]) :-
atom_number(C, X),
numbers_atoms(Y,K).
%([1,2,3],X)
digits_number(Digits, Number) :-
numbers_atoms(Digits, Atoms),
number_codes(Number, Atoms).
number_tolist( 0, [] ).
number_tolist(N,[A|As]) :-
N1 is floor(N/10),
A is N mod 10,
number_tolist(N1, As).
addOne([X],[Y]):-
digits_number(X,Y1), %[1,9,9] -> 199
Y1 is Y1+1, % 199 -> 200
number_tolist(Y1,[Y]), % 200 -> [2,0,0]
!.
You can solve this problem similarly to how you would solve it manually: traverse the list of digits until you reach the rightmost digit; increment that digit and compute the carry-on digit, which must be recursively propagated to the left. At the end, prepend the carry-on digit if it is equal to 1 (otherwise, ignore it).
% successor(+Input, -Output)
successor([X0|Xs], L) :-
successor(Xs, X0, C, Ys),
( C = 1 % carry-on
-> L = [C|Ys]
; L = Ys ).
% helper predicate
successor([], X, C, [Y]) :-
Z is X + 1,
Y is Z mod 10,
C is Z div 10. % carry-on
successor([X1|Xs], X0, C, [Y|Ys]) :-
successor(Xs, X1, C0, Ys),
Z is X0 + C0,
Y is Z mod 10,
C is Z div 10. % carry-on
Examples:
?- successor([1,9,9], A).
A = [2, 0, 0].
?- successor([2,7],A), successor(A,B), successor(B,C), successor(C,D).
A = [2, 8],
B = [2, 9],
C = [3, 0],
D = [3, 1].
?- successor([7,9,9,8], A), successor(A, B).
A = [7, 9, 9, 9],
B = [8, 0, 0, 0].
?- successor([9,9,9,9], A), successor(A, B).
A = [1, 0, 0, 0, 0],
B = [1, 0, 0, 0, 1].
Here's a version which doesn't use is and can work both ways:
successor(ListIn, ListOut) :-
reverse(ListIn, ListInRev),
ripple_inc(ListInRev, ListOutRev),
reverse(ListOutRev, ListOut).
ripple_inc([], [1]).
ripple_inc([0|T], [1|T]).
ripple_inc([1|T], [2|T]).
ripple_inc([2|T], [3|T]).
ripple_inc([3|T], [4|T]).
ripple_inc([4|T], [5|T]).
ripple_inc([5|T], [6|T]).
ripple_inc([6|T], [7|T]).
ripple_inc([7|T], [8|T]).
ripple_inc([8|T], [9|T]).
ripple_inc([9|T], [0|Tnext]) :-
ripple_inc(T, Tnext).
e.g.
?- successor([1,9,9], X).
X = [2, 0, 0]
?- successor([1,9,9], [2,0,0]).
true
?- successor(X, [2,0,0]).
X = [1, 9, 9]
although it's nicely deterministic when run 'forwards', it's annoying that if run 'backwards' it finds an answer, then leaves a choicepoint and then infinite loops if that choicepoint is retried. I think what causes that is starting from the higher number then reverse(ListIn, ListInRev) has nothing to work on and starts generating longer and longer lists both filled with empty variables and never ends.
I can constrain the input and output to be same_length/2 but I can't think of a way to constrain them to be the same length or ListOut is one item longer ([9,9,9] -> [1,0,0,0]).
This answer tries to improve the previous answer by #TessellatingHacker, like so:
successor(ListIn, ListOut) :-
no_longer_than(ListIn, ListOut), % weaker than same_length/2
reverse(ListIn, ListInRev),
ripple_inc(ListInRev, ListOutRev),
reverse(ListOutRev, ListOut).
The definition of no_longer_than/2 follows. Note the similarity to same_length/2:
no_longer_than([],_). % same_length([],[]).
no_longer_than([_|Xs],[_|Ys]) :- % same_length([_|Xs],[_|Ys]) :-
no_longer_than(Xs,Ys). % same_length(Xs,Ys).
The following sample queries still succeed deterministically, as they did before:
?- successor([1,9,9], X).
X = [2,0,0].
?- successor([1,9,9], [2,0,0]).
true.
The "run backwards" use of successor/2 now also terminates universally:
?- successor(X, [2,0,0]).
X = [1,9,9]
; false.

How do I get the sum of all solutions to a predicate (given that the set of solutions is finite)?

modThreeModFive(X) :- X > 0, X < 1000, 0 is mod(X, 5) ; 0 is mod(X, 3).
I'm wondering what the simplest way would be to get the sum of values of X for which the statement is true, given that the number of solutions is finite.
Is this even possible in Prolog, or am I forced to fill a list with integers [1, 1000], and then test them individually?
Being so different from imperative languages, the easiest way is to use a library predicate:
?- [user].
|: modThreeModFive(X) :- X > 0, X < 1000, 0 is mod(X, 5) ; 0 is mod(X, 3).
|:
% user://1 compiled 0.05 sec, 1 clauses
true.
?- aggregate(sum(X),(between(1,1000,X),modThreeModFive(X)),Sum).
Sum = 266333.
Not every Prolog has such library, then the alternative would be to - as you already suggested - to first get the list of values, then sum them together:
?- findall(X,(between(1,1000,X),modThreeModFive(X)),L),sumlist(L,Sum).
L = [3, 5, 6, 9, 10, 12, 15, 15, 18|...],
Sum = 266333.
If your Prolog allows for non backtrackable assignment, you could implement by yourself some of the basic functionalities found in library(aggregate).
OT: the version summing a list shows a bug in your logic: 15 is a solution in both branches. Instead of disjunction, you should use an if/then/else construct. Like in
?- [user].
|: modThreeModFive(X) :- 0 is mod(X, 5) -> true ; 0 is mod(X, 3).
Warning: user://2:21:
Warning: Redefined static procedure modThreeModFive/1
Warning: Previously defined at user://1:8
|:
% user://2 compiled 0.00 sec, 1 clauses
true.
?- findall(X,(between(1,1000,X),modThreeModFive(X)),L),sumlist(L,Sum).
L = [3, 5, 6, 9, 10, 12, 15, 18, 20|...],
Sum = 234168.
or just a cut !/0 to commit the first outcome. It's an useful exercise to find out the right position in such simple predicate...

delete only middle elements except first and last element

Example; I have a list [1,2,3,a,f,s,h,u,4,5]. I want to delete 2,3,a,f,s,h,u,4 and final result will [1,5]. How do i write predicate in Prolog?
delete(A, [A|B], B).
delete(A, [B, C|D], [B|E]) :-
delete(A, [C|D], E).
A nice way to think of sequence based problems like this is with DCG (Definite Clause Grammar) which is a standard part of most of the common Prolog distributions, such as SWI and GNU:
first_last([First, Last]) --> [First], ..., [Last].
... --> [].
... --> [_], ... .
first_and_last(L, FirstLast) :-
phrase(first_last(FirstLast), L).
First, this should be a delete/2 predicate, not a delete/3.
The base clause should be a list that has only two members, while the recursive clause should drop the second element, and move on:
delete([A,B], [A,B]).
delete([A,_|R], X) :- delete([A|R], X).
Demo.
you can use append/3:
?- X=[1,2,3,a,f,s,h,u,4,5].
X = [1, 2, 3, a, f, s, h, u, 4|...].
?- append([F|_],[L],$X).
F = 1,
L = 5,
X = [1, 2, 3, a, f, s, h, u, 4|...] .
or append/2
?- append([[F],_,[L]],$X).
F = 1,
L = 5,
X = [1, 2, 3, a, f, s, h, u, 4|...] .
or even a more succint version of #lurker answer:
?- [user].
|: ... --> [] | ([_], ...).
|: ^D% user://1 compiled 0.01 sec, 1 clauses
true.
?- phrase(([F],...,[L]),$X).
F = 1,
L = 5,
X = [1, 2, 3, a, f, s, h, u, 4|...] ;
false.

Equivalent of nvalue/2 from SICStus in SWIProlog

The SICStus manual for the CLP(FD) library says:
nvalue(?N, +Variables) where Variables is a list of domain variables with finite bounds or integers, and N is an integer or a
domain variable. True if N is the number of distinct values taken by
Variables.
This is particularly useful when one wants to minimize the number of distinct values in the solution. For example, if one is trying to distribute stuff into bags of different sizes, and want to minimize the number of bags.
Is there an equivalent predicate (or way) for achieving the same in SWI Prolog?
After #jschimpf comment, I've rethought the algorithm.
nvalue(1, [_]).
nvalue(C, [V|Vs]) :-
count_equals(V, Vs, E),
E #= 0 #/\ C #= R+1 #\/ E #> 0 #/\ C #= R,
nvalue(R, Vs).
count_equals(_, [], 0).
count_equals(V, [U|Vs], E) :-
V #= U #/\ E #= E1+1 #\/ V #\= U #/\ E #= E1,
count_equals(V, Vs, E1).
further cleanup
again, after #jschimpf note, I've tweaked the code: now it's very compact, thanks to libraries apply and yall.
nvalue(1, [_]).
nvalue(C, [V|Vs]) :-
maplist({V}/[U,Eq]>>(Eq#<==>V#=U), Vs, Es),
sum(Es, #=, E),
E #= 0 #/\ C #= R+1 #\/ E #> 0 #/\ C #= R,
nvalue(R, Vs).
old answer, buggy
my naive attempt, based on reification:
% nvalue(?N, +Variables)
nvalue(N, Vs) :-
nvalues(Vs, [], VRs),
sum(VRs, #=, N).
nvalues([], Acc, Acc).
nvalues([V|Vs], Acc, VRs) :-
nvalues_(V, Vs, Acc, Upd),
nvalues(Vs, Upd, VRs).
nvalues_(_V, [], Acc, Acc).
nvalues_(V, [U|Vs], Acc, Upd) :-
V #\= U #<==> D,
nvalues_(V, Vs, [D|Acc], Upd).
running your example query:
?- length(Vs, 3), Vs ins 1..3, nvalue(2, Vs), label(Vs).
Vs = [1, 1, 2] ;
Vs = [1, 1, 3] ;
Vs = [1, 2, 1] ;
Vs = [1, 2, 2] ;
Vs = [1, 3, 1] ;
Vs = [1, 3, 3] ;
Vs = [2, 1, 1] ;
Vs = [2, 1, 2] ;
Vs = [2, 2, 1] ;
Vs = [2, 2, 3] ;
Vs = [2, 3, 2] ;
Vs = [2, 3, 3] ;
Vs = [3, 1, 1] ;
Vs = [3, 1, 3] ;
Vs = [3, 2, 2] ;
Vs = [3, 2, 3] ;
Vs = [3, 3, 1] ;
Vs = [3, 3, 2].
edit
my code was a bit pedantic, of course could be more compact (and clear ?):
nvalue(N, Vs) :-
bagof(D, X^H^T^V^(append(X, [H|T], Vs), member(V, T), V #\= H #<==> D), VRs),
sum(VRs, #=, N).
note that findall/3 will not work, since the copy of reified variable D would lose the posted constraints.

Evaluate a number in (a few) natural language

Assume a list, each element can be:
a) a number 1,2,...9
b) a number 10, 100, 10000, ... (numbers of the form 10^(2^n) with n>=0).
It is need a (as much simple as possible) rule that evaluates this list to one integer number. Examples of this evaluation are:
[1] => 1
[2] => 2
[10 1] => 11
[2 10 1] => 21
[2 100 1 10 4] => 214
[2 10 1 100 4] => 2104
[2 10 1 100 10000] => 21000000
In other words, numbers 10, 100, ... are the equivalent of tenths, hundreds, million, ... in english and the rule to evaluate is the usual in english and other languages: 10, 100 "multiplies" the values before them, numbers after them are added.
(I know this definition is not an exact one, but finding a good definition is part of the problem. Do not hesitate to requests for more examples if necessary).
Note than, in the same way than in natural language, the number zero is not necessary. Even, like initial languages, is not present in the grammar.
Addendum
The major difficulty in this problem is an expression like [2 10000 3 10] that can not be taken as (2*10000+3)*10, but as 2*10000+3*10. Another example is [2 10 1 10000 3 10] that is (2*10+1)*10000+3*10.
Proof of not homework: Interest on this numbering (and, in general, in natural language) is that, in some context, they are more error-safe than binary. By example, in a context of a supermarket prices, "two thousands blah" keeps some meaning, while 1001blah is totally undefined.
With ingenuity, I would start covering the patterns...
test :- forall(member(L=R, [
[1] = 1,
[2] = 2,
[10, 1] = 11,
[2, 10, 1] = 21,
[2, 100, 1, 10, 4] = 214,
[2, 10, 1, 100, 4] = 2104,
[2, 10, 1, 100, 10000] = 21000000
]), test(L, R)).
test(L, R) :-
pattern(L, E), R =:= E -> writeln(ok(L,R)) ; writeln(ko(L,R)).
pattern([A], A) :- dig(A).
pattern([A, B], A+B) :- ten(A), dig(B).
pattern([A, B, C], A*B+C) :- mul_ten(A, B), dig(C).
pattern([A, B, C, D, E], A*B + C*D + E) :- mul_ten(A,B), mul_ten(C,D), B > D, dig(E).
pattern([A, B, C, D, E], ((A*B+C)*D)+E) :- mul_ten(A,B), ten(D), dig(E). % doubt...
pattern([A, B, C, D, E], (A*B+C)*D*E) :- mul_ten(A,B), ten(D), ten(E). % doubt...
dig(D) :- between(1,9,D).
ten(T) :- between(0,10,E), T =:= 10^(2^E). % 10 -> inappropriate (too much zeroes ?)
mul_ten(M,T) :- between(1,9,M), ten(T). % 9 -> inappropriate ?
plain pattern matching. Running:
?- test.
ok([1],1)
ok([2],2)
ok([10,1],11)
ok([2,10,1],21)
ok([2,100,1,10,4],214)
ok([2,10,1,100,4],2104)
ok([2,10,1,100,10000],21000000)
true.
I think that there is little space for recursion, afaik idioms cover frequently used cases, but without 'smart' evaluation... Anyway, I cannot really find my way in (that is, I would never use) this pattern
[2 10 1 100 4] => 2104
edit now, with DCG and CLP(FD) :
:- use_module(library(clpfd)).
test :- forall(member(L=R, [
[1] = 1,
[2] = 2,
[10, 1] = 11,
[2, 10, 1] = 21,
[2, 100, 1, 10, 4] = 214,
[2, 10, 1, 100, 4] = 2104,
[2, 10, 1, 100, 10000] = 21000000
]), test(L, R)).
test(L, R) :-
phrase(pattern(E), L), R #= E -> writeln(ok(L,R)) ; writeln(ko(L,R)).
pattern(A) --> dig(A).
pattern(A+B) --> ten(A), dig(B).
pattern(A*B+C) --> mul_ten(A, B), dig(C).
pattern(A*B+C*D) --> mul_ten(A, B), mul_ten(C, D).
pattern(A*B + C*D + E) --> mul_ten(A,B), mul_ten(C,D), dig(E).
pattern(((A*B+C)*D)+E) --> mul_ten(A,B), [C], ten(D), dig(E). % doubt...
pattern((A*B+C)*D*E) --> mul_ten(A,B), [C], ten(D), ten(E). % doubt...
dig(D) --> [D], {D #>= 1, D #=< 9}.
ten(T) --> [T], {T #>= 1, T #= (10^(2^E)), E #> 0, E #=< 10}.
mul_ten(M,T) --> dig(M), ten(T).
edit I like the op/3 directive, also...
:- op(100,fx, dig).
:- op(100,fx, ten).
:- op(100,xfx, mul).
pattern(A) --> dig A.
pattern(A+B) --> ten A, dig B.
pattern(A*B+C) --> A mul B, dig(C).
pattern(A*B+C*D) --> A mul B, C mul D.
pattern(A*B+C*D+E) --> A mul B, C mul D, dig E.
pattern(((A*B+C)*D)+E) --> A mul B, [C], ten D, dig E. % doubt...
pattern((A*B+C)*D*E) --> A mul B, [C], ten D, ten E. % doubt...
dig D --> [D], {D #>= 1, D #=< 9}.
ten T --> [T], {T #>= 1, T #= (10^(2^E)), E #> 0, E #=< 10}.
M mul T --> dig M, ten T.

Resources