Related
I have the following experimental code
s(a,b).
s(b,c).
s(c,b).
r(a).
r(c).
r(d).
p(X,Y) :- s(X,Y), not(r(Y)).
q(X,Y) :- q(Y,X), r(X).
q(X,Y) :- p(Y,X), s(X,Y).
t(X,Y) :- r(X), q(X,Y).
Querying for t(X,Y) will result in a endless recursion blowing up the stack. But I can actually think of X=c,Y=b being the solution because
t(c,b) <- r(c), q(c,b)
q(c,b) <- q(b,c), r(c)
q(b,c) <- p(c,b), s(b,c)
p(c,b) <- s(c,b), not(r(b))
Can someone explain to me, why prolog doesn't come to this solution and gets caught in an endless recursion around q(c,b) and q(b,c)
Many thanks!
In SWI-Prolog, you can solve the problem using tabled execution.
:- table q/2.
s(a,b).
s(b,c).
s(c,b).
r(a).
r(c).
r(d).
p(X,Y) :- s(X,Y), not(r(Y)).
q(X,Y) :- q(Y,X), r(X).
q(X,Y) :- p(Y,X), s(X,Y).
t(X,Y) :- r(X), q(X,Y).
Examples:
?- t(X,Y).
X = c,
Y = b ;
false.
?- q(X,Y).
X = c,
Y = b ;
X = b,
Y = c.
i should write a rule on prolog, which finds the last element of a list and add 1 to it. Here's what i came up with so far. It works, but my question is can this rule be written otherwise:
element(D ,[_|B]):- element(D, B).
element(D, [X]):- D is X+1.
(1) I'd rename the predicate to something like last_element_incremented which would be more descriptive than just element which doesn't say much.
(2) To make the rules non-overlapping, change the recursive rule:
last_element_incremented(Xinc, [_,X|T]) :- last_element_incremented(Xinc, [X|T]).
(3) If you use CLP(FD) you can make the solution more general. Also, swap the order of clauses so that you don't get a non-termination issue for more general queries:
last_element_incremented(Xinc, [X]) :- Xinc #= X + 1.
last_element_incremented(Xinc, [_,X|T]) :- last_element_incremented(D, [X|T]).
Then you can query, for example:
| ?- last_element_incremented(3, L).
L = [2] ? ;
L = [_,2] ? ;
L = [_,_,2] ? ;
L = [_,_,_,2] ? ;
(4) Finally, you could just use append/3:
last_element_incremented(Xinc, L) :- append(_, [X], L), Xinc #= X + 1.
I've been searching for something that might help me with my problem all over the internet but I haven't been able to make any progress. I'm new to logic programming and English is not my first language so apologize for any mistake.
Basically I want to implement this prolog program: discord/3 which has arguments L1, L2 lists and P where P are the indexes of the lists where L1[P] != L2[P] (in Java). In case of different lengths, the not paired indexes just fail. Mode is (+,+,-) nondet.
I got down the basic case but I can't seem to wrap my head around on how to define P in the recursive call.
discord(_X,[],_Y) :-
fail.
discord([H1|T1],[H1|T2],Y) :-
???
discord(T1,T2,Z).
discord([_|T1],[_|T2],Y) :-
???
discord(T1,T2,Z).
The two clauses above are what I came up to but I have no idea on how to represent Y - and Z - so that the function actually remembers the length of the original list. I've been thinking about using nth/3 with eventually an assert but I'm not sure where to place them in the program.
I'm sure there has to be an easier solution although. Thanks in advance!
You can approach this in two ways. First, the more declarative way would be to enumerate the indexed elements of both lists with nth1/3 and use dif/2 to ensure that the two elements are different:
?- L1 = [a,b,c,d],
L2 = [x,b,y,d],
dif(X, Y),
nth1(P, L1, X),
nth1(P, L2, Y).
X = a, Y = x, P = 1 ;
X = c, Y = y, P = 3 ;
false.
You could also attempt to go through both list at the same time and keep a counter:
discord(L1, L2, P) :-
discord(L1, L2, 1, P).
discord([X|_], [Y|_], P, P) :-
dif(X, Y).
discord([_|Xs], [_|Ys], N, P) :-
succ(N, N1),
discord(Xs, Ys, N1, P).
Then, from the top level:
?- discord([a,b,c,d], [a,x,c,y], Ps).
Ps = 2 ;
Ps = 4 ;
false.
I was just introduced to Prolog and am trying to write a predicate that finds the Max value of a list of integers. I need to write one that compares from the beginning and the other that compares from the end. So far, I have:
max2([],R).
max2([X|Xs], R):- X > R, max2(Xs, X).
max2([X|Xs], R):- X <= R, max2(Xs, R).
I realize that R hasn't been initiated yet, so it's unable to make the comparison. Do i need 3 arguments in order to complete this?
my_max([], R, R). %end
my_max([X|Xs], WK, R):- X > WK, my_max(Xs, X, R). %WK is Carry about
my_max([X|Xs], WK, R):- X =< WK, my_max(Xs, WK, R).
my_max([X|Xs], R):- my_max(Xs, X, R). %start
other way
%max of list
max_l([X],X) :- !, true.
%max_l([X],X). %unuse cut
%max_l([X],X):- false.
max_l([X|Xs], M):- max_l(Xs, M), M >= X.
max_l([X|Xs], X):- max_l(Xs, M), X > M.
Ignoring the homework constraints about starting from the beginning or the end, the proper way to implement a predicate that gets the numeric maximum is as follows:
list_max([P|T], O) :- list_max(T, P, O).
list_max([], P, P).
list_max([H|T], P, O) :-
( H > P
-> list_max(T, H, O)
; list_max(T, P, O)).
A very simple approach (which starts from the beginning) is the following:
maxlist([],0).
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head > TailMax,
Max is Head.
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head =< TailMax,
Max is TailMax.
As you said, you must have the variables instantiated if you want to evaluate an arithmetic expression. To solve this, first you have to make the recursive call, and then you compare.
Hope it helps!
As an alternative to BLUEPIXY' answer, SWI-Prolog has a builtin predicate, max_list/2, that does the search for you. You could also consider a slower method, IMO useful to gain familiarity with more builtins and nondeterminism (and then backtracking):
slow_max(L, Max) :-
select(Max, L, Rest), \+ (member(E, Rest), E > Max).
yields
2 ?- slow_max([1,2,3,4,5,6,10,7,8],X).
X = 10 ;
false.
3 ?- slow_max([1,2,10,3,4,5,6,10,7,8],X).
X = 10 ;
X = 10 ;
false.
edit
Note you don't strictly need three arguments, but just to have properly instantiated variables to carry out the comparison. Then you can 'reverse' the flow of values:
max2([R], R).
max2([X|Xs], R):- max2(Xs, T), (X > T -> R = X ; R = T).
again, this is slower than the three arguments loops, suggested in other answers, because it will defeat 'tail recursion optimization'. Also, it does just find one of the maxima:
2 ?- max2([1,2,3,10,5,10,6],X).
X = 10 ;
false.
Here's how to do it with lambda expressions and meta-predicate foldl/4, and, optionally, clpfd:
:- use_module([library(lambda),library(apply),library(clpfd)]).
numbers_max([Z|Zs],Max) :- foldl(\X^S^M^(M is max(X,S)),Zs,Z,Max).
fdvars_max( [Z|Zs],Max) :- foldl(\X^S^M^(M #= max(X,S)),Zs,Z,Max).
Let's run some queries!
?- numbers_max([1,4,2,3],M). % integers: all are distinct
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3],M).
M = 4. % succeeds deterministically
?- numbers_max([1,4,2,3,4],M). % integers: M occurs twice
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3,4],M).
M = 4. % succeeds deterministically
What if the list is empty?
?- numbers_max([],M).
false.
?- fdvars_max( [],M).
false.
At last, some queries showing differences between numbers_max/2 and fdvars_max/2:
?- numbers_max([1,2,3,10.0],M). % ints + float
M = 10.0.
?- fdvars_max( [1,2,3,10.0],M). % ints + float
ERROR: Domain error: `clpfd_expression' expected, found `10.0'
?- numbers_max([A,B,C],M). % more general use
ERROR: is/2: Arguments are not sufficiently instantiated
?- fdvars_max( [A,B,C],M).
M#>=_X, M#>=C, M#=max(C,_X), _X#>=A, _X#>=B, _X#=max(B,A). % residual goals
list_max([L|Ls], Max) :- foldl(num_num_max, Ls, L, Max).
num_num_max(X, Y, Max) :- Max is max(X, Y).
%Query will be
?-list_max([4,12,5,3,8,90,10,11],Max).
Max=90
Right now I was working with recursion in Prolog, so if it is useful for someone I will leave 'my two cents' solving it in the two ways that I have thought:
% Start
start :- max_trad([2, 4, 6, 0, 5], MaxNumber1),
max_tail([2, 4, 6, 0, 5], 0, MaxNumber2),
show_results(MaxNumber1, MaxNumber2).
% Traditional Recursion (Method 1)
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head > Value, Max is Head.
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head =< Value, Max is Value.
max_trad([], 0).
% Tail Recursion (Method 2)
max_tail([], PartialMax, PartialMax).
max_tail([Head|Tail], PartialMax, FinalMax) :- Head > PartialMax, max_tail(Tail, Head, FinalMax).
max_tail([_|Tail], PartialMax, FinalMax) :- max_tail(Tail, PartialMax, FinalMax).
% Show both of the results
show_results(MaxNumber1, MaxNumber2) :-
write("The max value (obtained with traditional recursion) is: "), writeln(MaxNumber1),
write("The max value (obtained with tail recursion) is: "), writeln(MaxNumber2).
The output of the above code is:
Both methods are similar, the difference is that in the second an auxiliary variable is used in the recursion to pass values forward, while in the first method, although we have one less variable, we are filling the Stack with instructions to be executed later, so if it were an exaggeratedly large list, the second method is appropriate.
maximum_no([],Max):-
write("Maximum No From the List is:: ",Max).
maximum_no([H|T],Max):-
H>Max,
N = H,
maximum_no(T,N).
maximum_no(L,Max):-
maximum_no(L,Max).
The maximum number in a list in Prolog ?
max([],A):-print(A),!.
max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
max(L,M):-
member(M,L),
findall(X,(member(X,L),X>M),NL),
length(NL,0).
How to Implement using recursion and cut-off cycle of the counter
(like for i: = 1 downto N do <operator>) ?
my naive implementation, to be seen as an extendend between/3
:- module(loop, [upto/4, downto/4]).
upto(Low,High,_Step,Low) :- Low =< High.
upto(Low,High,Step,Var) :-
Inc is Low+Step,
Inc =< High,
upto(Inc, High, Step, Var).
downto(Low,High,_Step,High) :- Low =< High.
downto(Low,High,Step,Var) :-
Dec is High-Step,
Dec >= Low,
downto(Low, Dec, Step, Var).
usage:
8 ?- forall(upto(0,6,3,V),writeln(V)).
0
3
6
true.
9 ?- forall(downto(0,6,3,V),writeln(V)).
6
3
0
true.
another example, the easiest question posed # this year Prolog programming contest:
icecream(N) :-
loop(N, top(N)),
left, loop(N+1, center), nl,
loop(N+1, bottom(N)).
:- meta_predicate loop(+, 1).
loop(XH, PR) :-
H is XH,
forall(between(1, H, I), call(PR, I)).
top(N, I) :-
left, spc(N-I+1), pop,
( I > 1
-> pop,
spc(2*(I-2)),
pcl
; true
),
pcl, nl.
bottom(N, I) :-
left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.
center(_) :- put(/), put(\).
left :- spc(4).
pop :- put(0'().
pcl :- put(0')).
spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).
yields
?- icecream(4).
()
(())
(( ))
(( ))
/\/\/\/\/\
\ /
\ /
\ /
\ /
\/
true.
note: loop in the second snippet is unrelated to first...
The short answer is that you don't.
Prolog is a declaritive language, not a procedural language. It comes from the predicate calculus. You describe the problem space in terms of facts and rules (the "database"). This forms a collection of connected, directed graphs.
You formulate an initial goal that describes the solution to your "problem" and let the inference engine find the solution(s), if any.
The inference engine starts with the initial goal you give it. It evaluates it in terms of the database, walking the graph as it goes, backtracking on failure, until it finds a solution (or not). Backtracking into the initial goal will cause it to look for the next solution, if any.
So the notion of a procedural construct such as a loop is rather non-idiomatic (to say the least) and (in my experience, at least) is pretty much a guarantee of poor performance.
Nicholas Carey is correct in advising you to think declaratively rather than procedurally for Prolog. However I take the question to mean something like, "How can I use Prolog to solve a certain kind of task for which I would employ loops in other languages: in particular, how can I get some set of results or outcomes?" For there are certainly times when, working completely within a declarative idiom, we want to describe N of something. The main difference will be that in instead of having to fit every problem into a loop, there are different ways of solving these kinds of problems depending on the nature of the problem itself.
twinterer's answer works, but is confined to an imperative idiom within a particular language.
Here are possible solutions for three common cases written in common, declarative Prolog idioms:
For numbers from N to M, you can use the built in predicate between(N,M,Num):
?- between(1, 5, X).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5.
For a list containing N instances of X, we can use a predicate like this:
n_xs(N, X, Xs) :-
length(Xs, N), % Creates a list of N uninstantiated variables.
maplist('='(X), Xs). % Unifies each variable with X
Then, to get your list:
?- n_xs(5, dingo, Ds).
Ds = [dingo, dingo, dingo, dingo, dingo].
This predicate can also be used to verify the length of a list which already contains a single homogeneous element,
?- n_xs(5, dingo, [dingo, dingo, dingo, dingo, dingo]).
true.
?- n_xs(N, dingo, [dingo, dingo, dingo, dingo, dingo]).
N = 5.
For performing some action N times, we can use something like this:
x_written_n_times(X, N) :-
foreach(between(1,N,_), write(X)).
?- x_written_n_times('dingo\n', 5).
dingo
dingo
dingo
dingo
dingo
true.
More information on kinds of looping behavior can be found at the bottom of this tutorial: http://www.pathwayslms.com/swipltuts/student/index.html
The ECLiPSe language (which basically is a variant of Prolog) has a do/2 predicate which is used to build loops. Using loops in Prolog code is sometimes useful, since it leads to more readable code that is also easier to change.
However, the do/2 predicate is in effect just a macro that gets translated into a recursive predicate, so that underneath it's still recursive:
?- ( for(I,From,To,Inc) do Body ).
maps into something like
?- do__1(From, To, Inc).
do__1(I, To, Inc) :- Inc >= 0, I > To, !.
do__1(I, To, Inc) :- Inc < 0, I < To, !.
do__1(I, To, Inc) :- Body, Next is I+Inc, do__1(Next, To, Inc).
(see the paper Logical Loops, which also gives a number of reasons why logical loops are preferable to pure recursion)
I have written an interpreter for imperative functions in Prolog. This is an example of its usage:
:- initialization(main).
main :-
imperative(Result,[
a = 1,
b = 2,
z = b + 1,
while(a < 10,[
a = a + 1,
(a mod 3 = 0) ->
[writeln(a mod 2),
writeln(a)]
])
]),
writeln(Result).
and this is its implementation:
while(List,Result,Condition,Statements) :-
get_var(List,Condition_,Condition),
(Condition_ -> (imperative(List,Result_,Statements),while(Result_,Result,Condition,Statements));
List=Result).
imperative_(List,Result,Command) :-
(member(A:_,List),
replaceP(A:A1,A:A2,List,Result);Result=[A:A2|List]),
(Command = increment(A,B), A2 is A1 + B;
Command = increment(A), A2 is A1 + 1;
Command = decrement(A), A2 is A1 - 1;
Command = (A = B), get_var(List,A2,B)).
imperative_(List,Result,while(Condition,Statements)) :-
while(List,Result,Condition,Statements).
imperative_(List,List,writeln(A)) :-
get_var(List,A_,A),
writeln(A_).
imperative_(List,Result,(Condition -> Statements)) :-
get_var(List,Condition_,Condition),
(Condition_ -> imperative(List,Result,Statements);List=Result).
imperative(Result,Steps) :- imperative([],Result,Steps).
imperative(List,Result,[Step]) :-
imperative_(List,Result,Step).
imperative(List,Result,[Step|Rest]) :-
imperative_(List,List1,Step), imperative(List1,Result,Rest).
get_var(List,A2,B) :- phrase(get_var(List,B),[A2]).
get_var(List,get_var(A)) -->
{get_var(List,A_,A)},[A_].
get_var(List,B) -->
{member(B:A2,List)},[A2].
get_var(_,B) -->
{number(B)},[B].
get_var(List,(A+B)) -->
{get_var(List,A_,A), get_var(List,B_,B), A2 is A_ + B_},[A2].
get_var(List,(A-B)) -->
{get_var(List,A_,A), get_var(List,B_,B), A2 is A_ - B_},[A2].
get_var(List,(A/B)) -->
{get_var(List,A_,A), get_var(List,B_,B), A2 is A_ / B_},[A2].
get_var(List,(A*B)) -->
{get_var(List,A_,A), get_var(List,B_,B), A2 is A_ * B_},[A2].
get_var(List,(A mod B)) -->
{get_var(List,A_,A), get_var(List,B_,B), A2 is A_ mod B_},[A2].
get_var(List,(A>B)) -->
{get_var(List,A_,A), get_var(List,B_,B)},[A_ > B_].
get_var(List,(A<B)) -->
{get_var(List,A_,A), get_var(List,B_,B)},[A_ < B_].
get_var(List,(A,B)) -->
{get_var(List,A_,A), get_var(List,B_,B)},[(A_,B_)].
get_var(List,(A=B)) -->
{get_var(List,A_,A), get_var(List,B_,B)},[(A_=B_)].
get_var(List,(A;B)) -->
{get_var(List,A_,A), get_var(List,B_,B)},[(A_;B_)].
get_var(_,true) -->
[true].
get_var(_,false) -->
[false].
% code by #svick, modified to use dif/2 instead of (\=)/2
replaceP(_, _, [], []).
replaceP(O, R, [O|T], [R|T2]) :- replaceP(O, R, T, T2).
replaceP(O, R, [H|T], [H|T2]) :- dif(H,O), replaceP(O, R, T, T2).
A simple code snippet :
loop(M,N):-
between(M, N, X),
writeln(X),
X >= N, !.
loop(M,X).
Goal :
?- loop(5,10).
5
6
7
8
9
10
Well, I've made this simple program that implements a loop in Prolog:
:- initialization(main).
loop(I, End) :-
I > End;
writeln(I), Ii is I + 1, loop(Ii, End).
main :- loop(0, 10).
It basically prints numbers from 0 to 10 (inclusive).
Here's how i did it(using recursion) :
for(X , Y , Z):-
X<Y,
X1 is X+Z,
writeln("Hello"),
for(X1 , Y , Z).
nestedFor(X , Y , Z):-
X<Y,
X1 is X+Z,
not(for(0 , 10 , 1)),
writeln("World!"),
nestedFor(X1 , Y , Z).
Keep adding more functions to create more loops.