I'm trying to express a relation on transition from one element in a list-of-lists, to another element. What I want to be able to do, is to say that there should exist a certain difference between two arbitrary elements.
If we have the list
X=[X1,X2,X3,...Xn]
where all elements are lists of length Y.
I now want to express that there should a difference from Xa->Xb where all elements in Xa
is equal or less but one, and Xa and Xb is any given element of X (a!=b)
Ex: If Xa=[1,1,1,1] then Xb could be [1,1,1,2] since all elements are equal or decrease expect one, the last, which goes from 1->2.
I have written the following predicate to do this:
ensure_atleast_n_patterns( ListOfLists, DiffPattern, NoOfAtLeastEqualPatterns ) :-
(
%Loop through the list to set up the constraint between first
%element and the rest, move on to next element and and set
%up constraint from second element on on etc.
%Ex: if ListOfLists=[X1,X2,X3,X4], the following 'loops' will run:
%X1-X2, X1-X3,X1-4,X2-X3,X2-X4,X3,X4
fromto(ListOfLists, [This | Rest], Rest,[_]),
fromto(0,In1,Out1,PatternCount),
param([DiffPattern])
do
(
%Compare the difference between two elements:
foreach( X, Rest ),
fromto(0,In2,Out2,Sum2),
param([DiffPattern,This])
do
This=[X1,X2,X3,X4,X5],
X=[Y1,Y2,Y3,Y4,Y5],
DiffPattern=[P1,P2,P3,P4,P5],
X1 #< Y1 #<=> R1,
X2 #< Y2 #<=> R2,
X3 #< Y3 #<=> R3,
X4 #< Y4 #<=> R4,
X5 #< Y5 #<=> R5,
Result in 0..1,
(R1 #= P1) #/\ (R2 #= P2) #/\ (R3 #= P3) #/\ (R4 #= P4) #/\ (R5 #= P5) #<=> (Result #=1),
Out2 #= In2 + Result
),
Out1 #= In1 + Sum2
),
%Count up, and require that this pattern should at least be present
%NoOfAtLeastEqualPatterns times
PatternCount #>= NoOfAtLeastEqualPatterns.
This seams to work ok.
My problems occurs if I also try to use all_different() on the rows.
Ex: I would guess that a solution could be:
0,0,0,0,0
2,2,2,2,1
1,1,1,1,2
4,4,4,3,4
3,3,3,4,3
etc...
But labeling hangs 'forever'
Is my approach wrong? Any better way to solve this?
Test code:
mytest( X ):-
Tlen = 10,
Mind = 0,
Maxd = 20,
length( X1,Tlen),
length( X2,Tlen),
length( X3,Tlen),
length( X4,Tlen),
length( X5,Tlen),
domain(X1, Mind, Maxd),
domain(X2, Mind, Maxd),
domain(X3, Mind, Maxd),
domain(X4, Mind, Maxd),
domain(X5, Mind, Maxd),
all_different( X1 ),
all_different( X2 ),
all_different( X3 ),
all_different( X4 ),
all_different( X5 ),
X=[X1,X2,X3,X4,X5],
transpose( X, XT ),
ensure_atleast_n_patterns( XT, [0,0,0,0,1],1),
ensure_atleast_n_patterns( XT, [0,0,0,1,0],1),
ensure_atleast_n_patterns( XT, [0,0,1,0,0],1),
ensure_atleast_n_patterns( XT, [0,1,0,0,0],1),
ensure_atleast_n_patterns( XT, [1,0,0,0,0],1).
And I run it like this:
mytest(X),append(X, X_1), labeling( [], X_1 ).
There is one thing that makes me suspect that your code doesn't express what you have in mind. You say: "I now want to express that there should a difference from Xa->Xb where all elements in Xa is equal or less but one, and Xa and Xb is any given element of X (a!=b)". But in your code, you don't consider all pairs of elements. You only consider pairs where Xb is somewhere to the right of Xa (Xb is an element of Rest). This asymmetry likely makes it hard to find solutions.
Nevertheless, here's a solution with Tlen = Maxd = 5:
| ?- mytest([[0,3,4,1,2],[1,2,4,0,3],[1,4,2,0,3],[3,1,4,2,0],[3,4,1,2,0]]).
yes
But due to the asymmetry, the following fails:
| ?- mytest([[0,1,2,3,4],[1,0,3,2,4],[1,0,3,4,2],[3,2,0,1,4],[3,2,0,4,1]]).
no
If you fix your code so that it considers all pairs (Xa,Xb), then from any solution you could get another solution by permuting the elements of ListOfLists (the rows of XT). It's usually a good idea to reduce the search space by breaking this kind of solution symmetry. You can do that with:
lex_chain(XT),
By the way, I recommend all_distinct/1 instead of all_different/1.
Related
As a beginner, I am trying to solve a matrix problem, in which the solution is either the summation or the multiplication of the distinct digit in the matrix. For example,[[14,_,_,_],[15,_,_,_],[28,_,1,_]]. The predicate should generate the solution according to the matrix. However, I bumped into a problem that my combined predicate failed, but each of them succeeded independently.
I broke the problem down to summation and multiplication. Therefore, using clpfd library, and some predicates, for summation:
removeHead([Head|Tail],Tail).
get_head_element([],_).
get_head_element([Head|Rest],Head).
solve_sum(Row,RestRow):-
get_head_element(Row, Goal),
removeHead(Row,RestRow),
RestRow ins 1..9,
all_distinct(RestRow),
sum(RestRow, #=, Goal).
For multiplication:
multiply(List,Result):-
multiply(List,1,Result).
multiply([Element|RestList],PrevResult,Result):-
NextResult #= PrevResult * Element,
multiply(RestList,NextResult, Result).
multiply([], Result, Result).
solve_multiply(Row,RestRow):-
get_head_element(Row, Goal),
removeHead(Row,RestRow),
RestRow ins 1..9,
multiply(RestRow,Goal),
all_distinct(RestRow).
Both solve_sum and solve_multiply works for a single row, but here I combine these two predicates to:
solve_row_sum_or_multiply([],_).
solve_row_sum_or_multiply([HeadRow|Matrix],Solution):-
maplist(all_distinct,Matrix),
get_head_element(HeadRow,Goal),
( Goal >= 25
-> solve_multiply(HeadRow,Solution),
write(Solution)
; ( solve_sum(HeadRow,Solution),
write(Solution)
; solve_multiply(HeadRow,Solution),
write(Solution))
),solve_row_sum_or_multiply(Matrix,Solution).
When I use the solve_row_sum_or_multiply([[14,_,_,_],[15,_,_,_],[28,_,_,_]],X), it will give me the possible combinations. However, when solve_row_sum_or_multiply([[14,_,_,_],[15,_,_,_],[28,_,1,_]],X), it gave me false, but there's a solution possible there, such as [[14,7,2,1],[15,3,7,5],[28,4,1,7]].
I am wondering what could be wrong. Any help is highly appreciated!
EDIT
The problem is inside the combined predicate, and it's better to write the predicate which the answer suggests instead of a nested if-then-else predicate.
Let's review this code.
intro code
:- use_module(library(clpfd)).
% ---
% Make sure you see all the information in a list printed at the
% toplevel, i.e. tell the toplevel to not elide large lists (print
% them in full, don't use '...')
% ---
my_print :-
Depth=100,
Options=[quoted(true), portray(true), max_depth(Depth), attributes(portray)],
set_prolog_flag(answer_write_options,Options),
set_prolog_flag(debugger_write_options,Options).
:- my_print.
multiply/2
Recode the multiply/2 predicate so that it can be read more easily. Add test code to make sure it actually does what we think it does:
% ---
% Set up constraint: all the elements in List, multiplied
% together, must yield Result. If the List is empty, the
% Result must be 1.
% ---
multiply(Factors,Product):-
multiply_2(Factors,1,Product).
multiply_2([Factor|Factors],PartialProduct,Product):-
PartialProduct2 #= PartialProduct * Factor,
multiply_2(Factors,PartialProduct2,Product).
multiply_2([],Product,Product).
solve_multiply([Product|Factors]):-
Factors ins 1..9,
multiply(Factors,Product),
all_distinct(Factors).
% ---
% Testing
% ---
:- begin_tests(multiply).
test(1) :-
multiply([X,Y,Z],6),
[X,Y,Z] ins 1..9,
X #=< Y, Y #=< Z,
bagof([X,Y,Z],label([X,Y,Z]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1, 1, 6], [1, 2, 3]]).
test(2) :-
multiply([],Result),
assertion(Result == 1).
test(3) :-
multiply([X,Y],3),
[X,Y] ins 1..9,
X #=< Y,
bagof([X,Y],label([X,Y]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1,3]]).
test(4) :-
solve_multiply([6,X,Y,Z]),
bagof([X,Y,Z],label([X,Y,Z]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]).
test(5) :-
solve_multiply([362880,F1,F2,F3,F4,F5,F6,F7,F8,F9]),
F1 #=< F2,
F2 #=< F3,
F3 #=< F4,
F4 #=< F5,
F5 #=< F6,
F6 #=< F7,
F7 #=< F8,
F8 #=< F9,
bagof([F1,F2,F3,F4,F5,F6,F7,F8,F9],label([F1,F2,F3,F4,F5,F6,F7,F8,F9]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1,2,3,4,5,6,7,8,9]]).
test(6,fail) :-
solve_multiply([-1,X,Y,Z]).
:- end_tests(multiply).
solve_sum/1
For summation, after simplifying and re-coding to Prolog's "pattern matching" style instead of (for want of a better word) "Algol calling style" as is used in the original the question (which confused me greatly I have to say).
This looks ok too. Note that the predicate solve_sum/1 is quite different-in-argument-style from multiply/2 It is better - and easier on the reader (and oneself) - if one keeps the same calling conventions.
solve_sum([Sum|Terms]):-
Terms ins 1..9,
all_distinct(Terms),
sum(Terms, #=, Sum).
% ---
% Testing
% ---
:- begin_tests(sum).
test(0) :-
solve_sum([0]).
test(1) :-
solve_sum([6,X,Y,Z]),
X #=< Y, Y #=< Z,
bagof([X,Y,Z],label([X,Y,Z]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1, 2, 3]]).
test(2) :-
solve_sum([9,X,Y,Z]),
X #=< Y, Y #=< Z,
bagof([X,Y,Z],label([X,Y,Z]),Bag),
sort(Bag,BagS),
assertion(BagS == [[1,2,6],[1,3,5],[2,3,4]]).
test(3,fail) :-
solve_sum([1,_X,_Y,_Z]).
:- end_tests(sum).
A printing predicate to get nice results
Prolog makes it easy to construct arbitrary structures "on the fly", one just has to stipulate exactly how the structure shall look.
Our "solution" is:
A list
With each element of the list a "row" (standing for one of the expressions)
And the row a term: row(Result,Op,RowValues) where Result is the left-hand-side of an equation, Op is one of add or mult and RowValues is a list with the values found for the values in the equation.
print_solution([]).
print_solution([Labeling|Labelings]) :-
format("---~n"),
print_rows_of_solution(Labeling),
format("---~n"),
print_solution(Labelings).
print_rows_of_solution([]).
print_rows_of_solution([row(Result,Op,RowValues)|Rows]) :-
print_row(Result,RowValues,Op),
print_rows_of_solution(Rows).
print_row(Result,[RowEntry|RowEntries],Op) :-
format("~q = ~q",[Result,RowEntry]),
print_row_2(RowEntries,Op).
print_row_2([RowEntry|RowEntries],Op) :-
((Op == mult) -> OpChar = '*'
; (Op == add) -> OpChar = '+'
; OpChar = '?'),
format(" ~q ~q",[OpChar,RowEntry]),
print_row_2(RowEntries,Op).
print_row_2([],_) :-
format("~n").
solve_row_sum_or_multiply/2
This has been modified to also collect the operation selected in a second argument (a list).
Note that the "maplist-all-distinct over the matrix" is not done here because that seems wrong.
solve_row_sum_or_multiply([],[]).
solve_row_sum_or_multiply([Row|MoreRows],[mult|Ops]) :-
Row = [X|_Xs],
X >= 25,
solve_multiply(Row), % we now have imposed a product constraint on the current Row
solve_row_sum_or_multiply(MoreRows,Ops).
solve_row_sum_or_multiply([Row|MoreRows],[add|Ops]) :-
Row = [X|_Xs],
X < 25,
solve_sum(Row), % we now have imposed a sum constraint on the current Row
solve_row_sum_or_multiply(MoreRows,Ops).
solve_row_sum_or_multiply([Row|MoreRows],[mult|Ops]) :-
Row = [X|_Xs],
X < 25,
solve_multiply(Row), % alternatively, we now have imposed a product constraint on the current Row
solve_row_sum_or_multiply(MoreRows,Ops).
And finally a "main" predicate
In trial_run/1 we stipulate that all variables except X32 be distinct and that X32 be 1. If X32 were in the "distinct set", none of the variables could take on the value 1 - there is no solution in that case.
We also impose a sorting to get only a set of "canonical" solutions:
We collect all possible solutions for solving and labeling using bagof/3:
trial_run(Solutions) :-
all_distinct([X11,X12,X13,X21,X22,X23,X31,X33]),
X32=1,
X11 #=< X12, X12 #=< X13,
X21 #=< X22, X22 #=< X23,
X31 #=< X33,
% multiple solutions solving x labeling may exist; collect them all
bagof(
[
row(14,Op1,[X11,X12,X13]),
row(15,Op2,[X21,X22,X23]),
row(28,Op3,[X31,X32,X33])
],
(
solve_row_sum_or_multiply( [[14,X11,X12,X13],[15,X21,X22,X23],[28,X31,X32,X33]], [Op1,Op2,Op3] ),
label([X11,X12,X13,X21,X22,X23,X31,X32,X33])
),
Solutions).
Does it work?
Apparently yes, and there is only one solution:
?- trial_run(Solutions),print_solution(Solutions).
---
14 = 2 + 3 + 9
15 = 1 + 6 + 8
28 = 4 * 1 * 7
---
Solutions = [[row(14,add,[2,3,9]),row(15,add,[1,6,8]),row(28,mult,[4,1,7])]].
I have a list of numbers, I need to calculate the sum of the even numbers of the list and the product of the odd numbers of the same list. I'm new in Prolog, and my searches so far weren't successful. Can anyone help me solve it ?
l_odd_even([]).
l_odd_even([H|T], Odd, [H|Etail]) :-
H rem 2 =:=0,
split(T, Odd, Etail).
l_odd_even([H|T], [H|Otail], Even) :-
H rem 2 =:=1,
split(T, Otail, Even).
Here is a suggestion for the sum of the even numbers from a list:
even(X) :-
Y is mod(X,2), % using "is" to evaluate to number
Y =:= 0.
odd(X) :- % using even
Y is X + 1,
even(Y).
sum_even(0, []). % empty list has zero sum
sum_even(X, [H|T]) :-
even(H),
sum_even(Y, T),
X is Y+H.
sum_even(X, [H|T]) :-
odd(H),
sum_even(X, T). % ignore the odd numbers
Note: My Prolog has oxidized, so there might be better solutions. :-)
Note: Holy cow! There seems to be no Prolog support for syntax highlighting (see here), so I used Erlang syntax.
Ha, it really works. :-)
Running some queries in GNU Prolog, I get:
| ?- sum_even(X,[]).
X = 0 ?
yes
| ?- sum_even(X,[2]).
X = 2 ?
yes
| ?- sum_even(X,[3]).
X = 0 ?
yes
| ?- sum_even(X,[5,4,3,2,1,0]).
X = 6 ?
yes
The ideas applied here should enable you to come up with the needed product.
Use clpfd!
:- use_module(library(clpfd)).
Building on meta-predicate foldl/4, we only need to define what a single folding step is:
sumprod_(Z,S0,S) :-
M #= Z mod 2,
rem_sumprod_(M,Z,S0,S).
rem_sumprod_(0,Z,S0-P,S-P) :-
S0 + Z #= S.
rem_sumprod_(1,Z,S-P0,S-P) :-
P0 * Z #= P.
Let's fold sumprod_/3 over the list!
l_odd_even(Zs,ProductOfOdds,SumOfEvens) :-
foldl(sumprod_,Zs,0-1,SumOfEvens-ProductOfOdds).
Sample query:
?- l_odd_even([1,2,3,4,5,6,7],Odd,Even).
Odd = 105,
Even = 12.
Alternatively, we can define sumprod_/3 even more concisely by using if_/3 and zeven_t/3:
sumprod_(Z,S0-P0,S-P) :-
if_(zeven_t(Z), (S0+Z #= S, P0=P),
(P0*Z #= P, S0=S)).
untested!
sum_odd_product_even([], S, P, S, P).
sum_odd_product_even([H|T], S0, P0, S, P) :-
S1 is S0 + H,
sum_even_product_odd(T, S1, P0, S, P).
sum_even_product_odd([], S, P, S, P).
sum_even_product_odd([H|T], S0, P0, S, P) :-
P1 is P0 * H,
sum_odd_product_even(T, S0, P1, S, P).
sum_odd_product_even(L, S, P) :-
sum_odd_product_even(L, 0, 1, S, P).
sum_even_product_odd(L, S, P) :-
sum_even_product_odd(L, 0, 1, S, P).
It shouldn't get much simpler than
%
% invoke the worker predicate with the accumulators seeded appropriately.
%
odds_and_evens( [O] , P , S ) :- odds_and_evens( [] , O , 0 , P , S ) .
odds_and_evens( [O,E|Ns] , P , S ) :- odds_and_evens( Ns , O , E , P , S ) .
odds_and_evens( [] , P , S , P , S ) . % if the list is exhausted, we're done.
odds_and_evens( [O] , X , X , P , S ) :- % if it's a single element list, we've only an odd element...
P is X*O , % - compute it's product
. % - and we're done.
odds_and_evens( [O,E|Ns] , X , Y , P , S ) :- % if the list is at least two elements in length'e both an odd and an even:
X1 is X*O , % - increment the odd accumulator
Y1 is Y+E , % - increment the even accumulator
odds_and_evens( Ns , X1 , Y1 , P , S ) % - recurse down (until it coalesces into one of the two special cases)
. % Easy!
I try to implement efficient exclusive-or (XOR) in Prolog CLPFD. This should be simple predicate like:
xor(A, B, AxorB).
A, B, AxorB are natural numbers (with 0) and AxorB is a result of A xor B.
My main problem is with efficiency. Firstly, I wasn't able to find any way to XOR two number without breaking those numbers into separate parts that could be further processed/constrained, and the process of breaking those numbers (creating proper constraints and then resolving them) is taking some processing time. Secondly, I wans't able to come up with any efficient way to "simulate" XOR functions on natural numbers other than presented in the second code below.
Lets start from my first code. This is the most simple XOR implementation possible and it works only for 1 bit values (0 and 1):
xor_1bit_values(A, B, AxorB) :-
AxorB #= (A + B) mod 2.
To use it for numbers larger than 1, numbers must be broken into bits:
xor_number(A, B, Result, Bits) :-
Count is Bits - 1,
xor_number(A, B, Result, Count, 0).
xor_number(A, B, Result, 0, Sum) :-
xor_1bit_values(A, B, Xor),
Result #= Xor + Sum.
xor_number(A, B, Result, Count, Sum) :-
P is 2^Count,
X #= A / P,
Y #= B / P,
xor_1bit_values(X, Y, Tmp),
NewSum #= Sum + P*Tmp,
NewCount is Count - 1,
xor_number(A, B, Result, NewCount, NewSum).
Sample input and output:
?- time(xor_number(123456789, 987654321, R, 32)).
% 943 inferences, 0.000 CPU in 0.001 seconds (0% CPU, Infinite Lips)
R = 1032168868
Now, this is too slow for my purposes, as in my code I have sometimes need to guess A and B when I have AxorB where all of these should be 32-bit numbers. And for numbers that need more than 10 bits this goes into literal millions of inferences that seem to increase expotentially. And I use the best labeling strategies, XOR arguments swapping and other tricks to speed up calculations.
So, I tried to do some maths. What I devised is XOR function for 2-bit values (0, 1, 2, 3):
xor_2bit_values(A, B, Result) :-
Result #= ((A + B*((-1)^A)) mod 4).
To use it in numbers larger than 3 there is code similar to what I presented before:
xor_number2(A, B, Result, Bits) :-
Count is (Bits / 2) - 1,
xor_number2(A, B, Result, Count, 0).
xor_number2(A, B, Result, 0, Sum) :-
xor_2bit_values(A, B, Xor),
Result #= Xor + Sum,
!.
xor_number2(A, B, Result, Count, Sum) :-
P is 4^Count,
X #= A / P,
Y #= B / P,
xor_2bit_values(X, Y, Tmp),
NewSum #= Sum + P*Tmp,
NewCount is Count - 1,
xor_number2(A, B, Result, NewCount, NewSum).
This seems to work nearly 50% faster than the first code. But still, two-fold difference is still too small for me.
So, my question for you is this: how can I implement efficient XOR for 32-bit numbers? If this is not possible on modern machines and you can prove it by some sort of calcucation then it is also a nice answer to my question. Eventually, how can I best improve my code? Maybe you have some ideas how to deal with numbers without breaking them apart or how to XOR numbers in other way?
Additional info: If it happens to you to try my code to guess two from three arguments or XOR, then because of possibility to freely swap arguments of that functions (which comes from its mathematical properties) I recommend setting A as bound variable and B and AxorB as unbound. CLPFD seems to work fastest that way. Also, the best labeling strategy would be labeling([bisect], [B,AxorB].
I think I would try to precompute some table of 'bit chunks', and then, using modulo and division (both supported operations), would do N lookups into the table. The idea it's that a lookup could work faster than the (huge!) arithmetic expansion performed by the library. This is the usual 'trade space for time' trick.
/** <module> bits_clpfd
*
* naive implementation of basic bit operations on constrained variables
* --------
*
* source file /home/carlo/prolog/bits_clpfd.pl
* created at dom mag 18 07:57:03 2014
*
* #author carlo
* #version 0.9.9
* #copyright carlo
* #license LGPL v2.1
*/
:- module(bits_clpfd,
[bits_clpfd_prepare_lut/2
]).
:- use_module(library(clpfd)).
:- dynamic lut_and_or_xor/5.
:- dynamic chunk_size/2.
%% bits_clpfd_prepare_lut(Bits, Max) is det.
%
% setup the lookup table for basic most operations on constrained variables
% the cost is mainly controlled by Bits, being the LUT size 2^(Bits*2)
%
% #arg Bits how many bits to store
% #arg Max describe Max
%
bits_clpfd_prepare_lut(Bits, BMax) :-
( nonvar(Bits) ; Bits = 4 ),
( nonvar(BMax) ; BMax = 32 ),
retractall(chunk_size(_, _)),
Max is 1 << BMax,
assert(chunk_size(Bits, Max)),
retractall(lut_and_or_xor(_,_, _,_,_)),
N is (1 << Bits) - 1,
forall((between(0, N, A), between(0, N, B)), (
And is A /\ B,
Or is A \/ B,
Xor is A xor B,
assertz(lut_and_or_xor(A,B, And,Or,Xor))
)).
%% xor_clpfd(A, B, C) is nondet.
%
% naive constraint A xor B #= C
%
% #arg A constrained variable
% #arg B constrained variable
% #arg C constrained variable
%
xor_clpfd(A, B, C) :-
maplist(check_domain_range, [A,B,C]),
split_apply_xor(1, A, B, C).
split_apply_xor(L, A, B, C) :-
chunk_size(NBits, Max),
( L < Max
-> Mod is (2 << NBits),
Am #= A mod Mod,
Bm #= B mod Mod,
Cm #= C mod Mod,
lut_and_or_xor(Am, Bm, _, _, Cm),
Ad #= A / Mod,
Bd #= B / Mod,
Cd #= C / Mod,
M is L << NBits,
split_apply_xor(M, Ad, Bd, Cd)
; true
).
check_domain_range(V) :-
chunk_size(_, Max),
assertion((fd_dom(V, Inf .. Sup), Inf>=0, Sup < Max)).
:- begin_tests(bits_clpfd).
test(1) :-
bits_clpfd_prepare_lut(2, 4),
Vs = [A,B,C], Vs ins 0..15,
A #= 1, B #= 1, C #= 0,
xor_clpfd(A, B, C).
:- end_tests(bits_clpfd).
test
?- run_tests(bits_clpfd).
% PL-Unit: bits_clpfd
Warning: /home/carlo/prolog/bits_clpfd.pl:83:
PL-Unit: Test 1: Test succeeded with choicepoint
done
% test passed
true.
anyway, this is a naive approach, the right one should be to compile your own run_propagator/2. But I've never done it...
Maybe it wasn't available then but now, we can do this:
Y in 0..5, X #= Y xor 1, label([Y]).
From the docs, it's written that:
The bitwise operations ()/1, (/)/2, (/)/2, (>>)/2, (<<)/2, lsb/1, msb/1, popcount/1 and (xor)/2 are also supported.
See if you can adapt this for your purposes.
I'm learning how to program in Prolog and I found the next program that defines the natural numbers and their sum:
sum( succ( X ), Y, succ( Z )) :- sum( X, Y, Z ).
sum( 0, X, X ).
?- sum( succ( succ(0)), succ( succ( succ(0))), Answer ).
Answer = succ( succ( succ( succ( succ(0)))))
(found here)
The problem is that I'm struggling with the execution flow of this program. To tell the truth I don't know what it does. How can Prolog figure out the Answer's value? What are the steps that Prolog follows to find the Answer's value?
Thanks in advance.
It helps to understand how Prolog operates when figuring out an existing predicate, or when designing a new one. When you make a query such as:
sum( succ(succ(0)), succ(succ(succ(0))), Answer ).
Prolog will look for facts and rules matching sum(_, _, _) (sum/3) and select the first one that matches. The rules in place are:
(1) sum( succ(X), Y, succ(Z) ) :- sum( X, Y, Z ).
(2) sum( 0, X, X ).
If you look at the query, it clearly matches the pattern of rule #1. Remember that in Prolog, a variable can be instantiated to any kind of term, and variables of the same name are unified (instantiated to the same value). When Prolog unifies the "head" of rule #1 with the query, it does so by unifying the variables as follows:
X = succ(0)
Y = succ(succ(succ(0)))
(A) Answer = succ(Z)
Notice that Answer has the value succ(Z) even though Z hasn't been bound (assigned a concrete value) yet. Now we follow the rule, which will query, sum(X, Y, Z), which will be the query:
sum( succ(0), succ(succ(succ(0))), Z )
| | |
X Y Z
Prolog will now start from the top again since this is a new query for sum/3. Just like the first time, it matches rule #1 with the following unifications:
X = 0
Y = succ(succ(succ(0)))
(B) Z = succ(Z')
I am using Z' above to distinguish it from the other variable Z in the sum(succ(0), succ(succ(succ(0))), Z), since it is a different Z than the one used in the head for sum(..., succ(Z)). This is like if you have a function in C declared as int f(x) { return 2*x; } and you call it with another local variable x from somewhere, that name x is used in two different places and represents two different variables).
Then we can follow the next recursive query, sum(X, Y, Z') again, which becomes:
sum( 0, succ(succ(succ(0))), Z' )
| | |
X Y Z'
This recursive query doesn't match rule #1 since the first argument, 0, doesn't match succ(X). However, it matches rule #2:
0 = 0
X = succ(succ(succ(0)))
(C) X = Z'
Now X = succ(succ(succ(0))) so Z' = succ(succ(succ(0))). Since this rule has no more queries within it, it finally succeeds back to where it was queried from. Returning this back to (B) above:
Z = succ(Z') = succ(succ(succ(succ(0))))
and returning this back to (A):
Answer = succ(Z) = succ(succ(succ(succ(succ(0)))))
And there you have it. Using the trace facility that #CapelliC mentioned, you can watch these successive steps occur in the Prolog interpreter and follow the instantiation of variables.
Prolog's "evaluation" proceeds by matching the given query to the program's rules' heads, and proceeding with the matching rule's body, under the matching substitution. When a rule is selected, its variables are uniformly renamed, for uniqueness:
(1) sum( succ( X ), Y, succ( Z )) :- sum( X, Y, Z ).
(2) sum( 0, X, X ).
?- sum( succ( succ(0)), succ( succ( succ(0))), Answer ).
(1) -> sum( succ( X1 ), Y1 , succ( Z1 )) :- sum( X1, Y1, Z1 ).
%% X1 = succ(0), Y1 = succ( succ( succ(0))), succ(Z1) = Answer. %%
-? sum( X1, Y1, Z1 ).
-? sum( succ( 0 ), Y1, Z1 ).
(1) -> sum( succ( X2 ), Y2, succ( Z2 )) :- sum( X2, Y2, Z2 ).
%% X2 = 0, Y2 = Y1, succ(Z2) = Z1. %%
-? sum( X2, Y2, Z2 ).
-? sum( 0, Y2, Z2 ).
(2) -> sum( 0, X3, X3 ). %% DONE. %%
%% X3 = Y2, X3 = Z2. %%
From here, Answer = succ(Z1) = succ( succ(Z2)) = succ( succ(X3)) = succ( succ( Y2)) = succ( succ (Y1)) = succ( succ( succ( succ( succ(0))))).
for such a simple program, trace/0 it's the way to go. leash/1 (that not totally obvious to newbies) allows controlling debugger interface:
21 ?- leash(-all),trace.
true.
[trace] 22 ?- sum( succ( succ(0)), succ( succ( succ(0))), Answer ).
Call: (6) sum(succ(succ(0)), succ(succ(succ(0))), _G710)
Call: (7) sum(succ(0), succ(succ(succ(0))), _G789)
Call: (8) sum(0, succ(succ(succ(0))), _G791)
Exit: (8) sum(0, succ(succ(succ(0))), succ(succ(succ(0))))
Exit: (7) sum(succ(0), succ(succ(succ(0))), succ(succ(succ(succ(0)))))
Exit: (6) sum(succ(succ(0)), succ(succ(succ(0))), succ(succ(succ(succ(succ(0))))))
Answer = succ(succ(succ(succ(succ(0))))).
You can see that your program does a bounded recursive search on first argument, unifying it with either the first clause (calls marked 6,7) or the second one (call marked 8).
I am trying to compile a SWI-Prolog program but keep getting test is always true, var (sum) error on line 7. I cant figure out what this means. Can someone please help? This is a program I am hoping will eventually solve Latin squares. Thank you.
:- use_module(library(clpfd)).
magic_counter(Count) :-
findall(a, magic_1(_Soln), As),
length(As, Count).
magic_1(Soln) :-
Row1 = [W1, W2, W3],
Row2 = [X1, X2, X3],
Row3 = [Y1, Y2, Y3],
Row1 ins 1..3,
Row2 ins 1..3,
Row3 ins 1..3,
Sum #= 6,
all_different(Row1),
all_different(Row2),
all_different(Row3),
all_different([W1,X1,Y1]),
all_different([W2,X2,Y2]),
all_different([W3,X3,Y3]),
W1 + W2 + W3 #= Sum,
X1 + X2 + X3 #= Sum,
Y1 + Y2 + Y3 #= Sum,
W1 + X1 + Y1 #= Sum,
W2 + X2 + Y2 #= Sum,
W3 + X3 + Y3 #= Sum,
append(Row1,Row2,Row12),
append(Row12,Row3,Soln),
labeling([], Soln).
It's a warning, not an error.
I posted some time again a request on SWI-Prolog mailing list for this problem, since some existing code begun to raise this warning after a refinement to messages. Here is the answer from Jan.
I think you can ignore the warning, or disable it, but this seems not advisable.
If a row consists of three integers between 1 and 3, and these integers must be distinct, then the sum of such a row must be 6 (by definition). Stating that the sum of such a row equals 6 is therefore an idle constraint. The same reasoning applies to the 'columns' for which you assert similar disjointness constraints.
Edit: Even though the above reasoning is correct, this is not the origin of the warning. Carlo is right on this, it simply depends on the way in which the constraint library rewrites the constraints.
test1:-
L = [X],
L ins 1..2,
Y #= 2,
X #= Y.
test2:-
L = [X],
L ins 1..2,
X #= 2.
test1/0 gives the warning, test2/0 does not. Still, I find it difficult to see why the warning is given in the first place, i.e. what the rational behind it is. For example, here is the expansion of test1/0 (notice my comments):
:- use_module(library(clpfd)).
test1:-
A=[D],
A ins 1..2,
(
integer(B)
->
(
var(2)
->
2 is B
;
true
->
B=:=2
;
C is B,
clpfd:clpfd_equal(C, 2)
)
;
true
->
(
var(B) % This does not throw a warning.
->
B is 2
;
C is 2,
clpfd:clpfd_equal(B, C)
)
;
clpfd:clpfd_equal(B, 2)
),
(
integer(D)
->
(
var(B) % This throws a "Test is always true" warning.
->
B is D
;
integer(B)
->
D=:=B
;
E is D,
clpfd:clpfd_equal(E, B)
)
;
integer(B)
->
(
var(D)
->
D is B
;
E is B,
clpfd:clpfd_equal(D, E)
)
;
clpfd:clpfd_equal(D, B)
).