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.
Related
I'm trying to implement a simple predicate, that would simply remove items that occur more than once in a list.
For instace, for,
unique([a,b,a,b,c,c,a], R)
should be R = [a,b,c]
unique([], []).
unique([X], [X]).
unique([H|T], [H|R]) :-
not_contains(H, R),
unique(T, R).
unique([H|T], R) :-
contains(H, R),
unique(T, R).
contains(_, []).
contains(X, [X|T]).
not_contains(_, []).
not_contains(X, [H|T]) :-
X \= H,
not_contains(X, T).
I am unsure what I'm doing wrong. If the item is not contained within R, add to it and repeat, and if is, don't add it and proceed with iteration.
A fun way to do it that I just thought of:
nub(L,R):- maplist( p(R), L), length(R,_), !.
p(R,E):- memberchk(E,R).
nub(L,R) makes a unique list R out of an input list L. It assumes R is a non-instantiated variable before the call is made, and L is a fully ground list.
This uses the result list as its own uniqueness accumulator while it is being built!
Testing:
6 ?- nub([a,b,a,b,c,c,a], R).
R = [a, b, c].
The easiest way to make a list unique is just use the built-in sort/2:
unique(Xs,Ys) :- sort(Xs,Ys).
so unique( [c,a,b,a] , Rs ) yields Rs = [a,b,c].
If you want to maintain order, you need to decide on the strategy you want to use — in case of duplicates, which duplicate "wins": First or last?
The "last wins" strategy is the simplest to implement:
unique( [] , [] ) . % the empty list is itself a unique set
unique( [X|Xs] , Ys ) :- % A non-empty list is unique if . . .
contains(X,Xs), % - X is contained within the source list's tail,
!, - and (eliminating the choice point)
unique( Xs, Ys ) . - omitting X, the remainder of the list is (recursively) unique
unique( [X|Xs] , Ys ) :- % Otherwise, the non-empty list is unique if . . .
unique( Xs,[X|Ys] ) . % - adding X to the results, the remainder of the list is (recursively) unique .
Here, unique( [a,b,a,c,a], Rs ) yields Rs = [b,c,a].
If you want to use the "first wins" strategy, you'll be wanting to use a helper predicate with an accumulator that grows the result list in reverse order, which is then reversed. That gives us something like this:
unique( Xs , Ys ) :- unique(Xs,[],Zs), reverse(Zs,Ys) .
unique( [] , Ys , Ys ) . % Source list exhausted? we're done.
unique( [X|Xs] , Ts , Ys ) :- % Otherwise . . .
contains(X,Ts) , % - if X is found in the accumulator,
!, % - eliminate the choice point, and
unique(Xs,Ts,Ys) . % - recurse down, discarding X
unique( [X|Xs] , Ts , Ys ) :- % Otherwise (X is unique) . . .
unique(Xs,[X|Ts],Ys) . % - recurse down, prepending X to the accumulator
And here, unique( [a,b,a,c,a], Rs ) yields Rs = [a,b,c].
You can avoid the use of reverse/2 here, by building the 2 lists (accumulator and final set) in parallel. A trade-off, though: memory for speed:
unique( Xs , Ys ) :- unique(Xs,[],Ys) .
unique( [] , _ , [] ) .
unique( [X|Xs] , Ts , Ys ) :- memberchk(X,Ts), !, unique( Xs, Ts , Ys ) .
unique( [X|Xs] , Ts , [X|Ys] ) :- unique( Xs, [X|Ts] , Ys ) .
You don't really need a contains/2 predicate: the in-built member/2 and memberchk/2 do exactly what you want. member/2 is non-deterministic and will succeed once for every time the item is found in the list; memberchk/2 is non-deterministic and will succeed at most once.
Since this is testing for uniqueness, memberchk/2 is what you'd want, giving you this:
contains(X,Ys) :- memberchk(X,Ys) .
Or you can roll you own (it's trivial):
contains( X , [X|Ys] ) :- ! .
contains( X , [_|Ys] ) :- contains(X,Ys) .
Or even simpler, just a one-liner:
contains( X , [Y|Ys] ) :- X = Y -> true ; contains(X,Ys) .
I'm exercising for an exam and I'm having a hard time understanding the process of how Prolog works. Can someone please explain to me the process behind this exercise?
The question is:
Write a Prolog program that removes all duplicates from a list and returns the duplicate-free list.
For instance, given the list L1 = [a,b,a,c,a,a,b], the duplicate-free list is L2 = [c,a,b].
Note that the order of the elements in L2 does not matter.
You can use the built-in predicate member(X,L) to check whether X is a member in L
The solution is:
rmdup( [], [] ).
rmdup( [H|T], R ):- member( H, T ), !, rmdup(T,R).
rmdup( [H|T], [H|Rest] ):- rmdup( T, Rest ).
Thanks a lot for the help.
Let's break it down, line-by-line, shall we?
rmdup( [] , [] ) . % The empty list is unique by definition
rmdup( [H|T] , R ) :- % For a non-empty list, though...
member( H, T ), % - Is the current item found later in the list?
!, % - If so, eliminate the choice point (we don't want to follow the "unique" path
rmdup(T,R). % - Discard the current item and recurse down
rmdup( [H|T] , [H|R] ) :- % Otherwise (this list item is unique)
rmdup( T, R ) % - prepend it to the result list and recurse down.
. % Easy!
One could also write this without the cut, like this, which might make it easier to understand. It does, however, introduce a redundant member/2 test:
rmdup( [] , [] ) .
rmdup( [H|T] , R ) :- member(H,T), rmdup(T,R) .
rmdup( [H|T] , [H|R] ) :- \+ member(H,T), rmdup(T,R) .
I have intentionally aligned the structures in the head of each clause because a lot of Prolog is about pattern matching.
Also note that the result list is built as an open list, where the end of the list is unbound. That open list will become a closed list, when the source list is exhausted and the result list is unified with the empty list []. Until then R is a variable, and the result list gets constructed as a side-effect of unification in the head in the 3rd clause that handles unique items.
And finally, the order of clauses here does not really matter. You could switch the order up and it will still behave properly. This
rmdup( [] , [] ) .
rmdup( [H|T] , [H|R] ) :- \+ member(H,T), rmdup(T,R) .
rmdup( [H|T] , R ) :- member(H,T), rmdup(T,R) .
works, as does even
rmdup( [H|T] , [H|R] ) :- \+ member(H,T), rmdup(T,R) .
rmdup( [H|T] , R ) :- member(H,T), rmdup(T,R) .
rmdup( [] , [] ) .
I'm a beginner at prolog and I'm having trouble getting started with the following problem:
Define the predicate partstr/3, where the first argument is a list, that generates a list A of length L that you find consecutive in the first list.
You should be able to present all answers with backtracking.
E.g.:
?- partstr([1, 2 , 3], L, A).
If L = 2 then A = [1,2] and [2,3],
or if L = 2 then F=[1,2] and [2,3].
and so on...
I feel like you would use recursion to solve it, but I'm not sure where to start. I would really appreciate some tips on how to solve this because I feel like I'm getting nowhere.
The core of this problem is that you need a way to pull all the sublist of length N from a list, correct?
So...
Consider that append/3 can concatenate two lists: append( [a,b,c], [1,2,3], L) returns L as [a,b,c,1,2,3]. But it can also decompose a list into a prefix and a suffix, so
append( Pfx, Sfx, [a,b,c])
will, on backtracking, successively yield:
Pfx
Sfx
[]
[a,b,c]
[a]
[b,c]
[a,b]
[c]
[a,b,c]
[]
...and... length/2 can not only tell you the length of a list, but
can generate lists of a specified length populated with unique,
unbound variables, so length(L,3) returns [V1,V2,V3].
You can combine those to get the behavior you want:
partstr( Xs, N, SL ) :- % To get all the contiguous sublists of length N from Xs...
append(_,Sfx,Xs) , % - repeatedly get all possible suffixes of Xs, and...
length(SL,N) , % - construct an empty, unbound list of the desired length (N), and...
append(SL,_,Sfx) % - pull that prefix off the suffix
. % Easy!
That's one approach. I imagine that this is coursework and that your instructor likely would like you to roll your own solution from scratch.
To do that, we first need a predicate that will yield the source list, and on backtracking remove the head of the list. Something like:
suffix( Xs , Xs ) .
suffix( [_|Xs] , Sfx ) :- suffix(Xs,Sfx).
Then we need a way to grab the 1st n elements from a list, something like this:
take( _ , 0 , [] ) :- ! .
take( [X|Xs] , N , [X|Sfx] ) :- N1 is N-1 , take(Xs,N1,Sfx) .
Given those two...
partstr( Xs, N , SL ) :-
suffix(Xs,Sfx),
take(Sfx,N, SL )
.
You can even dispense with the suffix/2 predicate, thus, rolling its functionality into partstr/3 itself:
partstr( Xs , N , SL ) :- take(Xs,N,SL).
partstr( [_|Xs] , N , SL ) :- partstr(Xs,N,SL).
And that, I think, is the sweet spot: it is hard to beat 4 lines of code —
partstr( Xs , N , SL ) :- take(Xs,N,SL) .
partstr( [_|Xs] , N , SL ) :- partstr(Xs,N,SL) .
take( _ , 0 , [] ) :- ! .
take( [X|Xs] , N , [X|Sfx] ) :- N > 0 , N1 is N-1 , take(Xs,N1,Sfx) .\
How can i substract elements from one list with elements from other list? Something like this:
substract_lists(List1, List2, ListR) :- maplist(plus, List1, List2, ListR).
but for substract.
EDIT:
I'm tried with ListR is List1 - List2 but it given me an error.
Following the advice of Willem Van Onsem, the code is like this:
substract(A, B, R) :- R is A - B.
substract_lists(List1, List2, ListR) :- maplist(substract, List1, List2, ListR).
Assuming that this is a homework problem, the instructor is probably looking for you to roll your own.
The one problem you'll have to consider is what happens when the two lists of are different lengths.
Here is one approach. I resolve the above problem by treating missing elements as being zero:
subtract( [] , [] , [] ) .
subtract( [A|As] , [] , [R|Rs] ) :- R is A-0, subtract(As,[],Rs).
subtract( [] , [B|Bs] , [R|Rs] ) :- R is 0-B, subtract([],Bs,Rs).
subtract( [A|As] , [B|Bs] , [R|Rs] ) :- R is A-B, subtract(As,Bs,Rs).
You can also just flip the order for plus, since plus(A, B, C) gives B is C - A when both C and A are instantiated.
substract_lists(List1, List2, ListR) :- maplist(plus, List2, ListR, List1).
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 )
.