Related
This is a question asking why backtracking happens in one simple program and not another.
Example 1.
% water/2 relates temperature to state
water(Temp, solid) :- Temp =< 0.
water(Temp, liquid) :- Temp > 0, Temp < 100.
water(Temp, gas) :- Temp >= 100.
?- water(50,X).
X = liquid
false
Example 2.
% parent facts
parent(john, jane).
parent(john, james).
parent(sally, jane).
parent(martha, sally).
?- parent(X, jane).
X = john
X = sally
In example 1, prolog finds X=liquid as one solution, then prompts to search for more solutions. When none are found it returns false.
In example 2, prolog correctly finds X=john, prompts to continue the search, and then finds X=sally, but then does not prompt to continue searching. It does not finish with a false to indicate it tried the remaining rules (eg parent(martha,sally) the last rule) and failed.
Question: Why does the first example finish with a false, but the second does not?
Simply write a rule which disallows water to be in more than one state. There's several methods (mostly using e.g. cut), here's one:
water_temp_state(Temp, State) :-
( Temp =< 0 -> State = solid
; Temp < 100 -> State = liquid
; State = gas
).
Results:
?- water_temp_state(-5, S).
S = solid.
?- water_temp_state(5, S).
S = liquid.
?- water_temp_state(500, S).
S = gas.
Use multiple predicates when there is an actual possibility of multiple states.
Here's another method, just for fun:
water_state_comparison(solid, =<, 0).
water_state_comparison(liquid, <, 100).
water_state_comparison(gas, >=, 100).
water_temp_state_compare(Temp, State) :-
water_state_comparison(State, Comp, Num),
Pred =.. [Comp, Temp, Num],
call(Pred),
!.
... with same results.
I'm new in prolog, and I wanted to create a "function" to count how many different values I have in a list.
I've made this predicate to count the total number of values:
tamanho([],0).
tamanho([H|T],X) :- tamanho(T,X1), X is X1+1.
I wanted to follow the same line of thought like in this last predicate.(Don't know if that's possible).
So in a case where my list is [1,2,2,3], the answer would be 3.
Can someone give me a little help?
Here is a pure version which generalizes the relation. You can not only count but just see how elements have to look like in order to obtain a desired count.
In SWI, you need to install reif first.
:- use_module(library(reif),[memberd_t/3]).
:- use_module(library(clpz)). % use clpfd in SWI instead
:- op(150, fx, #). % backwards compatibility for old SWI
nt_int(false, 1).
nt_int(true, 0).
list_uniqnr([],0).
list_uniqnr([E|Es],N0) :-
#N0 #>= 0,
memberd_t(E, Es, T),
nt_int(T, I),
#N0 #= #N1 + #I,
list_uniqnr(Es,N1).
tamanho(Xs, N) :-
list_uniqnr(Xs, N).
?- tamanho([1,2,3,1], Nr).
Nr = 3.
?- tamanho([1,2,X,1], 3).
dif:dif(X,1), dif:dif(X,2).
?- tamanho([1,2,X,Y], 3).
X = 1, dif:dif(Y,1), dif:dif(Y,2)
; Y = 1, dif:dif(X,1), dif:dif(X,2)
; X = 2, dif:dif(Y,1), dif:dif(Y,2)
; Y = 2, dif:dif(X,1), dif:dif(X,2)
; X = Y, dif:dif(X,1), dif:dif(X,2)
; false.
You can fix your code by adding 1 to the result that came from the recursive call if H exists in T, otherwise, the result for [H|T] call is the same result for T call.
tamanho([],0).
tamanho([H|T], X) :- tamanho(T, X1), (member(H, T) -> X is X1; X is X1 + 1).
Tests
/*
?- tamanho([], Count).
Count = 0.
?- tamanho([1,a,21,1], Count).
Count = 3.
?- tamanho([1,2,3,1], Count).
Count = 3.
?- tamanho([1,b,2,b], Count).
Count = 3.
*/
In case the input list is always numerical, you can follow #berbs's suggestion..
sort/2 succeeds if input list has non-numerical items[1] so you can use it without any restrictions on the input list, so tamanho/2 could be just like this
tamanho(T, X) :- sort(T, TSorted), length(TSorted, X).
[1] thanks to #Will Ness for pointing me to this.
I'm kinda new to Prolog so I have a few problems with a certain task. The task is to write a tail recursive predicate count_elems(List,N,Count) condition List_Element > N, Count1 is Count+1.
My approach:
count_elems( L, N, Count ) :-
count_elems(L,N,0).
count_elems( [H|T], N, Count ) :-
H > N ,
Count1 is Count+1 ,
count_elems(T,N,Count1).
count_elems( [H|T], N, Count ) :-
count_elems(T,N,Count).
Error-Msg:
ERROR: toplevel: Undefined procedure: count_elems/3 (DWIM could not correct goal)
I'm not quite sure where the problem is. thx for any help :)
If you want to make a tail-recursive version of your code, you need (as CapelliC points out) an extra parameter to act as an accumulator. You can see the issue in your first clause:
count_elems(L, N, Count) :- count_elems(L,N,0).
Here, Count is a singleton variable, not instantiated anywhere. Your recursive call to count_elems starts count at 0, but there's no longer a variable to be instantiated with the total. So, you need:
count_elems(L, N, Count) :-
count_elems(L, N, 0, Count).
Then declare the count_elem/4 clauses:
count_elems([H|T], N, Acc, Count) :-
H > N, % count this element if it's > N
Acc1 is Acc + 1, % increment the accumulator
count_elems(T, N, Acc1, Count). % check the rest of the list
count_elems([H|T], N, Acc, Count) :-
H =< N, % don't count this element if it's <= N
count_elems(T, N, Acc, Count). % check rest of list (w/out incrementing acc)
count_elems([], _, Count, Count). % At the end, instantiate total with accumulator
You can also use an "if-else" structure for count_elems/4:
count_elems([H|T], N, Acc, Count) :-
(H > N
-> Acc1 is Acc + 1
; Acc1 = Acc
),
count_elems(T, N, Acc1, Count).
count_elems([], _, Count, Count).
Also as CapelliC pointed out, your stated error message is probably due to not reading in your prolog source file.
Preserve logical-purity with clpfd!
Here's how:
:- use_module(library(clpfd)).
count_elems([],_,0).
count_elems([X|Xs],Z,Count) :-
X #=< Z,
count_elems(Xs,Z,Count).
count_elems([X|Xs],Z,Count) :-
X #> Z,
Count #= Count0 + 1,
count_elems(Xs,Z,Count0).
Let's have a look at how versatile count_elems/3 is:
?- count_elems([1,2,3,4,5,4,3,2],2,Count).
Count = 5 ; % leaves useless choicepoint behind
false.
?- count_elems([1,2,3,4,5,4,3,2],X,3).
X = 3 ;
false.
?- count_elems([1,2,3,4,5,4,3,2],X,Count).
Count = 0, X in 5..sup ;
Count = 1, X = 4 ;
Count = 3, X = Count ;
Count = 5, X = 2 ;
Count = 7, X = 1 ;
Count = 8, X in inf..0 .
Edit 2015-05-05
We could also use meta-predicate
tcount/3, in combination with a reified version of (#<)/2:
#<(X,Y,Truth) :- integer(X), integer(Y), !, ( X<Y -> Truth=true ; Truth=false ).
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
Let's run above queries again!
?- tcount(#<(2),[1,2,3,4,5,4,3,2],Count).
Count = 5. % succeeds deterministically
?- tcount(#<(X),[1,2,3,4,5,4,3,2],3).
X = 3 ;
false.
?- tcount(#<(X),[1,2,3,4,5,4,3,2],Count).
Count = 8, X in inf..0 ;
Count = 7, X = 1 ;
Count = 5, X = 2 ;
Count = 3, X = Count ;
Count = 1, X = 4 ;
Count = 0, X in 5..sup .
A note regarding efficiency:
count_elems([1,2,3,4,5,4,3,2],2,Count) left a useless choicepoint behind.
tcount(#<(2),[1,2,3,4,5,4,3,2],Count) succeeded deterministically.
Seems you didn't consult your source file.
When you will fix this (you could save these rules in a file count_elems.pl, then issue a ?- consult(count_elems).), you'll face the actual problem that Count it's a singleton in first rule, indicating that you must pass the counter down to actual tail recursive clauses, and unify it with the accumulator (the Count that gets updated to Count1) when the list' visit is done.
You'll end with 3 count_elems/4 clauses. Don't forget the base case:
count_elems([],_,C,C).
i'm having problems with this subject in Prolog.
The thing is that I want to count the number of repeated elements appearing in a list,
and I also want to fill, in another list with 1, for each appearance of duplicated elements and a 0 if is not duplicated, e.g.
I have a list like this: [420,325,420,582,135,430,582], and the result should be [1,0,1,1,0,0,1].
I've tried some code snippets and it's driving me nuts.
The last code i've tried is:
count_duplicates([],[]).
count_duplicates([Head|Tail],[1|LS]):-
member(Head,Tail),
count_duplicates([Tail|Head],LS).
count_duplicates([Head|Tail],[0|LS]):-
\+ member(Head,Tail),
count_duplicates([Tail|Head],LS).
this predicate receive a list and have to generate the result list
Thanks in advance
You can try this :
count_duplicate(In, Out) :-
maplist(test(In), In, Out).
test(Src, Elem, 1) :-
select(Elem, Src, Result),
member(Elem, Result).
test(_Src, _Elem, 0).
EDIT Without maplist, you can do
count_duplicate(In, Out) :-
test(In, In, Out).
test(_, [], []).
test(In, [Elem | T], [R0 | R]) :-
select(Elem, In, Rest),
( member(Elem, Rest) -> R0 = 1; R0 = 0),
test(In, T, R).
I would rewrite using some of list processing builtins available:
count_duplicates(L, R) :-
maplist(check(L), L, R).
check(L, E, C) :-
aggregate(count, member(E, L), Occurs),
( Occurs > 1 -> C = 1 ; C = 0 ).
with that
?- count_duplicates([420,325,420,582,135,430,582],L).
L = [1, 0, 1, 1, 0, 0, 1].
About your code, I think it's simple to get termination:
count_duplicates([],[]).
count_duplicates([Head|Tail],[1|LS]):-
member(Head,Tail),
count_duplicates(Tail,LS).
count_duplicates([Head|Tail],[0|LS]):-
\+ member(Head,Tail),
count_duplicates(Tail,LS).
Note I corrected the recursive calls, and consider that could be done in a slightly more efficient way (both source and runtime) using the if .. then .. else .. construct.
count_duplicates([],[]).
count_duplicates([Head|Tail],[R|LS]):-
( member(Head,Tail) -> R = 1 ; R = 0 ),
count_duplicates(Tail,LS).
it's cleaner, isn't it? member/2 it's called just once, that's a big gain,
and consider using memberchk/2 instead of member/2.
But that code fails to tag as multiple the last occurrence.
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.