I made this code so basically, it detects if the array in the first argument is the reverse array in the second argument, it works well but when I want to have the reversed array for a giving array, first it gives me the right answer than if I do ";" to have another answer I expect to get false which is normal, but Prolog just enters an infinite loop.
here is my code :
rev([],[]).
rev([X|A],B):- append(C,[X],B), rev(A,C) .
and this is a test to explain the problem:
enter image description here
?- rev([4,3,9,9],[9,9,3,4]).
true ;
false.
?- rev([4,3,9,9],[4,2,1,4]).
false.
?- rev([4,3,9,9],Result).
Result = [9, 9, 3, 4] ;
.
.
.
Waiting for Prolog. Close again to force termination.
First of all, is this such a big problem? From time to time you do not get a clear response from Prolog but instead it just loops. So sometimes it behaves like a runaway engine. Certainly not ideal. But it could be worse! In particular, if it would produce an incorrect answer. Like failing, when there are solutions.
To understand why Prolog loops in your case, it helps to put some falsework into your program. By adding goals false. In this manner we will see just the real reason:
rev([],[]) :- false.
rev([X|A],B):- append(C,[X],B), false, rev(A,C).
?- rev([4,3,9,9],Result), false.
loops.
Such a program is called a failure-slice. The nice property here is that if this failure slice loops, also your original program will loop. But often this slice is much smaller, so the error is easier to detect.
In order to get rid of that looping, you need to modify something in the visible part. One possibility would be to exchange the two goals. This would make this query terminate. But then,
rev([],[]) :- false.
rev([X|A],B):- rev(A,C), false, append(C,[X],B).
?- rev(L, [9,9,3,4]), false.
loops.
So by just exchanging goals, things are not solved in general.
To solve this for both cases, both lists have to be taken into account prior to the first goal.
rev(Xs, Ys) :-
rev(Xs, Ys, Ys).
rev([], [], []).
rev([X|Xs], Ys, [_|Zs]) :-
rev(Xs, Xsr, Zs),
append(Xsr,[X],Ys).
So a third argument was added, which ensures that the length of Ys may influence termination.
There are actually better more efficient ways to express this. But conceptually this solution is simpler to understand.
Your rev/2 is invoking append/3 with two unbound variables. On backtracking, it's generating unbound lists of ever-increasing length:
That's a feature of append/3.
The "classic" reversal of a list is this:
rev( [] , [] ) .
rev( [X|Xs] , Ys ) :- rev(Xs,X1), append(X1,[X],Ys) .
It runs on O(N2) time. And it will blow the stack given a list of sufficient length. And if the 1st argument to rev/2 is unbound, you'll go into a recursive loop (until the stack overflows).
Instead, use a helper predicate with an accumulator. It's a common Prolog idiom to have a "public" predicate that does little more than invoke a "private" helper predicate of the same name, but with different arity, where the extra arguments carry the necessary state to accomplish the task at hand.
rev( [] , Ys , Ys ) .
rev( [X|Xs] , Ts , Ys ) :- rev(Xs,[X|Ts],Ys).
Now you have something that is (1) tail recursive, and (2) runs in O(n) time and space.
Once you have that, the "public" rev/2 is just this:
rev( Xs, Ys ) :- rev(Xs,[],Ys) .
where we seed the accumulator with the empty list.
Note however, that this rev/2 is not bi-directional. Invoking rev(Xs,[a,b,c]) will work successfully, but backtracking into it will result in an infinite recursive loop.
To fix that, simply add some type checking into rev/2. To successfully reverse a list, at least one of Xs or Ys must be bound. That gives us this:
rev( Xs , Ys ) :- nonvar(Xs), !, rev( Xs, [] , Ys ) .
rev( Xs , Ys ) :- nonvar(Ys), rev( Ys, [] , Xs ) .
Putting it all together, you get:
https://swish.swi-prolog.org/p/RdhuxIlF.pl
rev( Xs , Ys ) :- nonvar(Xs), !, rev( Xs, [] , Ys ) .
rev( Xs , Ys ) :- nonvar(Ys), rev( Ys, [] , Xs ) .
rev( [] , Ys , Ys ) .
rev( [X|Xs] , Ts , Ys ) :- rev(Xs,[X|Ts],Ys).
I liked the creative approach of your code... then I dare to suggest a fix, in plain old style, instead of a rewrite:
rev([],[]).
rev([X|A],B):- append(C,[X],B), rev(A,C), !.
Related
Let's assume that I have a
list = [1,2,3,4,5]
and an element = 3
I want to get a sublist based on that element , like that
sublist = [3,4,5]
What is the implementation in Prolog ?
The simplest way is to use append/3. This will give you the list starting from X. Backtracking will try to find the next X:
list_from_element(X,Ys,[X|Xs]) :- append(_, [X|Xs], Ys) .
To roll your own isn't much more difficult:
list_from_element( X, [X|Xs] , [X|Xs] ) . % once we find X, we're done
list_from_element( X, [Y|Ys] , Xs ) :- % otherwise, discard the head of the list
list_from_element(X,Ys,Xs). % - and recurse down
Again, backtracking will try to find alternate solutions by looking for another X
How exactly does append/3 work with an anonymous variable such as the one in the example below:
append(_,[b(F,ND,P)|Rest],Visited).
Couldn't we in fact just use append/2?
Thank you for your answer!
The goal
..., append(_,[b(F,ND,P)|Rest],Visited).
reads:
Somewhere in the list of Visited nodes, there is a b(F, ND, P) with subsequent nodes Rest.
Note that there might be more than one such node, so most probably there is a cut at some place or a once/1.
Couldn't we in fact just use append/2?
Where did you dig out that skeleton - er - library predicate? But in fact, this may permit us to implement append/3:
myappend(Xs, Ys, Zs) :-
append([Xs,Ys], Zs).
So the intuition behind is that list Xs concatenated with list Ys is list Zs. From this declarative viewpoint, there are clearly no differences. Or are they?
At least procedurally, there are differences! For ...
?- append([], Ys, Zs), false.
false.
... terminates, but ...
?- append([[], Ys], Zs), false.
loops.
... loops! (In SWI and SICStus) Let's see the concrete answers produced (I'll use SICStus, because it prints variables more compactly, SWI uses hard-to-read variables like _G1376):
?- append([], Ys, Zs).
Zs = Ys.
?- append([[], Ys], Zs).
Ys = [], Zs = []
; Ys = [_A], Zs = [_A]
; Ys = [_A,_B], Zs = [_A,_B]
; Ys = [_A,_B,_C], Zs = [_A,_B,_C]
; ... .
So append/3 produced a single answer, whereas append/2 seems to produce infinitely many. How can they be declaratively equivalent, or are they not?
Answers vs. solutions
First, let me point out that Ys = [], Zs = [] above is a concrete solution. The next is the answer Ys = [_A], Zs = [_A] which contains infinitely many solutions. The _A stands here for infinitely many ground terms. So there is a way to collapse (or lift) infinitely many solutions into a single, elegant and finite answer.
Now, append([], Ys, Zs) went a step further, it collapsed all answers into a single one: Ys = Zs. But, is this right? This answer means that any term could be the Ys. In particular, say, non_list which is certainly not a list. Think of it:
?- append([a],nonlist,Zs).
Zs = [a|nonlist].
So what append/3 effectively did was to overgeneralize or to lift things too far. In fact, its definition is:
append([], Zs, Zs).
append([X|Xs], Ys, [X|Zs]) :-
append(Xs, Ys, Zs).
The fact reads:
The empty list appended with anything, really anything (including all Polish kings), is just that anything.
Clearly that fact states a bit too much. But it is this very overgeneralization that helped to improve termination properties! And, if we are a bit careful, this overgeneralization will never show. ((Kind of a shady deal?))
But then, Prolog enjoys many other properties - in particular the "single assignment" property of logic variables that mitigates this problem. The very same technique is used very often also for difference lists and DCGs. If you use it consistently and wisely, it will improve performance and termination properties.
So I am currently trying to compute a formula using Prolog. I currently have part of the formula done, but I am having trouble implementing the next part where I need to add the elements of the list and then square root the sum. Not sure how I would do that.
What I currently have:
formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
L = H2,
formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
L = H1,
formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
L is (H1 - H2)*(H1 - H2),
formula(T1, T2, Ls).
Your original formula
formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
L = H2,
formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
L = H1,
formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
L is (H1 - H2)*(H1 - H2),
formula(T1, T2, Ls).
can be simplified to make the pattern matching more explicit:
formula( [] , [] , [] ) .
formula( [] , [Y|Ys] , [Y|Zs] ) :- formula( [] , Ys , Zs ) .
formula( [X|Xs] , [] , [X|Zs] ) :- formula( Xs , [] , Zs ) .
formula( [X|Xs] , [Y|Ys] , [Z|Zs] ) :-
L is ( X - Y ) * ( X - Y ) ,
formula(Xs,Ys,Zs)
.
I assume your instructor wants you to roll your own here and learn about recursion rather than using a built-in predicate. So, ... You could sum the elements of a list like this (the naive implementation):
sum_of( [] , 0 ) . % the sum of the empty list is zero.
sum_of( [X|Xs] , S ) :- % the sum of an empty list is computed by
sum(Xs,T) , % - computing the sum of the tail of the list
S is T+X % - and adding that to the value of the head of the list.
. %
But that will fail with a stack overflow once the list gets sufficiently long as each recursive call pushes a new frame onto the stack. Prolog has an nifty optimization (tail recursion optimization) that effectively converts recursion into iteration by recognizing when it can reuse the stack frame. To do that, the recurive call must be the very last thing done.
This introduces a common pattern in prolog programming:
a public interface predicate (here, sum_of/2),
that invokes a "private" tail-recursize worker predicate (here, sum_of/3) that uses an accumulator argument to build up its result.
Using that pattern, we get this implementation:
sum_of(Xs,Sum) :- sum_of(Xs,0,Sum) .
sum_of( [] , S , S ) . % the sum of the empty list is 0.
sum_of( [X|Xs] , T , S ) :- % the sum of a non-empty list is computed by
T1 is T+X , % incrementing the accumulator by the value of the head of the list, and
sum_of( Xs , T1 , S ) % recursing down on the tail.
. % Easy!
This will work for lists of any length.
Using the SWI-Prolog library predicate sum_list/2:
list_summed_and_square_rooted(List, Value) :-
sum_list(List, Sum),
Value is sqrt(Sum).
You probably don't need to write a separate predicate for relating a list to the square root of the sum of its elements, unless you'll be needing to use that particular relation often. Your formula/3 makes one list out of two, but ultimately you seem to be after a numerical value, so you probably do want another predicate to describe the relation between two lists and the resultant numerical value.
lists_processed_in_some_way(List1, List2, Value) :-
formula(List1, List2, CombinedList),
sum_list(CombinedList, Sum),
Value is sqrt(Sum).
By the way, you can simplify your formula/3 because you don't need L = H2:
formula([], [H2|T2], [H2|Ls]) :-
formula([], T2, Ls).
Also, it's generally good practice to name your predicates carefully, with something descriptive. It will help you reason about what your predicates do and help you communicate your programs to others.
Having trouble understanding how Prolog works. I'm tryig to write a rule that takes three lists of integers as input (representing sets) and puts the integers that belong to both the first and second list in the third list.
Example:
?-inter([10,20,30,40],[10,50,40,60], List3 )
List3 = [10, 40]
So far I have this, that can recognize if a list contains a certain letter:
mymember(X,[X|T]).
mymember(X,[H|T]) :- mymember(X,T).
There's actually an inbuilt library to sort that all out for you, known as ordsets.
inter(X, Y, Z) :-
list_to_ord_set(X, L1),
list_to_ord_set(Y, L2),
ord_intersection(L1, L2, Z).
Using your example input you get the following
| ?- inter([10,20,30,40],[10,50,40,60],X).
X = [10,40] ? ;
no
inter(Xs, Ys, Zs) will be true when each element in Zs also is in Xs and in Ys.
But Zs are unknown, then a more constructive approach is required.
Here it is: iterate on Xs and store in Zs each element that is in Ys.
An example of iteration is mymember/2, you can see that it requires a recursive predicate.
The other idiomatic part of the above statement is store in Zs, Prolog has a peculiar way to do such things, using pattern matching.
inter([X|Xs], Ys, [X|Zs]) :-
mymember(X, Ys), inter(Xs, Ys, Zs).
You will need to complete inter/3 with other 2 clauses: base recursion, i.e. when all Xs elements have been processed, and the case where X is not a member of Ys.
Try something like this, using the builtins member/2 and setof\3:
set_intersection( As , Bs , Xs ) :-
set_of( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
One should note that this will fail if the lists As and Bs have no elements in common. An alternative would be use findall/3 rather than set_of/3. findall/3 will hand back and empty list rather than failure if the goal is not satisfied:
set_intersection( As , Bs , Xs ) :-
findall( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
However findall/3 returns a bag (duplicates are allowed) rather than a set (no duplicates allowed), so if your two source lists aren't sets, you won't get a set out.
member/2 is a builtin predicate that unifies its first argument with an element of the list — the equivalent of
member(X,[X|_).
member(X,[_|Xs) :- member(X,Xs) .
And, finally, as #chac noted in his answer, you can recursively traverse the list.
set_intersection( [] , _ , [] ) . % the intersection of the empty set with anything is the empty set.
set_intersection( [A|As] , Bs , [A|Xs] ) :- % if the list is non-empty,
member(A,Bs) , % - and A is a member of the 2nd set
! , % - we cut off alternatives at this point (deterministic)
set_intersection( As , Bs , Xs ) % - and recurse down on the tail of the list.
.
set_intersection( [_|As] , Bs , Xs ) :- % if the list is non-empty, and A is NOT a embmer of the 2nd set
set_intersection( As , Bs , Xs ) % we just recurse down on the tail of the list.
.
#chac's technique builds the result list as he goes, something like:
[a|X]
[a,b|X]
[a,b,c|X]
The final unification, the special case of the empty list unifies the unbound tail of the list with [] making the list complete, so the final [a,b,c|X] becomes
[a,b,c]
A little prolog magic. An alternative that might be easier to understand is to use a worker predicate with an accumulator:
%
% set_intersection/3: the public interface predicate
%
set_intersection( As , Bs , Xs ) :-
set_intersection( As , Bc , [] , T ) % we seed our accumulator with the empty list here
.
%
% set_intersection/4: the private worker bee predicate
%
set_intersection( [] , _ , T , Xs ) :- % since our accumulator is essentially a stack
reverse(T,Xs) % we need to reverse the accumulator to
. % put things in the expected sequence
set_intersection( [A|As] , Bs , T , Xs ) :-
member( A, Bs ) ,
! ,
T1 = [A|T] ,
set_intersection( As , Bs , T1 , Xs )
.
set_intersection( [_|As] , Bs , T , Xs ) :-
set_intersection( As , Bs , T , Xs )
.
For example:
isin([1,2,3], [1,0,1,2,3,0])
will yield true because 123 is inside of 101230
I wrote the following code:
isin([AH|AT],[AH|AT]).
isin([AH|AT],[BH|BT]):- AH = BH, isin(AT,BT),isin([AH|AT],BT).
seems not working. Try not use any built-in functions and BTW, Prolog has a built-in sublist(L1,L2) function.
How do I write a query against a built-in function using SWI-Prolog? I tried to directly write
?- sublist([1],[2]).
but it gives me underfined procedure error.
Is it possible to see how a built-in function is coded? How?
sublist( [], _ ).
sublist( [X|XS], [X|XSS] ) :- sublist( XS, XSS ).
sublist( [X|XS], [_|XSS] ) :- sublist( [X|XS], XSS ).
If you want
my_sublist( [2,3,4], [1,2,3,4,5] )
...to succeed, but
my_sublist( [1,3,5], [1,2,3,4,5] )
...to fail, you might want to consider
my_sublist( Sublist, List ) :-
append( [_, Sublist, _], List ).
Note that if you pass a variable through as Sublist, backtracking will give you a comprehensive set of all possible sublists of List, but this will in general include several repeats of the empty list (because the empty list can combine with all other sublists both ahead and behind of them in an append operation).
Since it seems to be homework I will only give you a few hints:
It seems you are missing the case where an empty list is a sublist of the other one.
You mixed the two cases "the sublist starts here" and "the sublist starts later" into one clause.
It seems the elements of the sublist should be consecutive in the larger list. For that you need two predicates. Essentially you have to remember that the sublist has started when you take apart the lists.
There is no builtin sublist/2, only a sublist/3 which does something different (filter list with a predicate).
another implementation using member is :
sublist([],_).
sublist([X|Xs],Y) :- member(X,Y) , sublist(Xs,Y).
member/2 returns true if find the element in a list
member(X,[X|_]).
member(X,[_|Ys]):-member(X,Ys).
sublist(S, L) :-length(S, N),
length(L, N1),
N2 is N1 - N,
length(P, N2),
append( _ , S, P),
append(P, _ , L).
to avoid stack overflow for failing cases we must determine the size of the list P.
sublist([],[],_):-!.
sublist(_,[],_):-!.
sublist([H1|T1],[H2|T2],LV):-
H1 = H2,!,
sublist(T1,T2,LV).
sublist([H1|T1],[H2|_],LV):-
not(H1 = H2),
sublist(T1,LV,LV).
If you try these queries:
?-sublist([1,2,3,4,5],[1,2,3],[1,2,3]).
TRUE
?-sublist([1,2,3,4,5],[1,2,4],[1,2,4]).
FALSE
With a few modifications to ДМИТРИЙ МАЛИКОВ's answer, this is something that works,
preList([], L).
preList([H_s|T_s], [H_s|Tail]):-
preList(T_s, Tail).
subList([H_s|T_s], [H_s|Tail]):-
preList(T_s, Tail).
subList([H_s|T_s], [H_s|Tail]):-
subList([H_s|T_s], Tail).
subList(Sub, [_|Tail]):-
subList(Sub, Tail).
Essentially, look for a match between the first elements of the sub-list and the main-list using the subList procedure. When a match occurs, head over to the preList procedure and check if this turns out to be a prefix for the remainder of the list. If so, the resolution ends in success.
If not, come back and continue comparing the remainder of the list for a first-element match.