Related
I have a predicate set/2 that is supposed to instantiate the second argument to a list whose elements are only one occurance of each term from the first argument. What I have so far is:
set([],OutList).
set([X|InList],OutList) :- \+member(X,InList), append([X], OutList, OutListNew), set(InList,OutListNew).
set([X|InList],OutList) :- member(X,InList), set(InList,OutList).
And calling set/2:
set([1,1,2,3],X).
returns true. That's halfway there - I want X to be instantiated to [1,2,3] - but I'm not sure how to make X true in this case. Any help and explanations would be appreciated.
Your Prolog should warn you have a singleton in the first clause, that is
set([],OutList).
It means that when the execution hits such clause, it succeeds, but OutList remains unbound.
Now should be clear that you need to substitute OutList with the empty list.
Another bug is located in the second clause.
append([X], OutList, OutListNew) should be instead append([X], OutListNew, OutList). As a style note, it can be substituted by this unification: [X|OutListNew]=OutList, and then moved into the head.
sort/2 removes duplicates (msort/2 leaves duplicates, if that's what you want.
Also: https://www.swi-prolog.org/pldoc/man?predicate=list_to_set/2
I'm having some (or a lot of) trouble with lists of lists in prolog.
So I have a list of numbers, say [5,6,1,3] as input.
The output should be [[5,25],[6,36],[1,1],[3,9]].
I already have a predicate that 'return's the 2 item lists (keep in mind that I'll have to change the get_squared_pair function to get some other relevant value):
get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].
get_squared_value(Number, Result) :-
Result is Number * Number.
Until here it's pretty logical. Now I need a predicate that recursively iterates though a list, adds the squared pair to a new list, and then returns this lists of lists. What I have right now is:
return_list([], 0).
return_list([Head | Tail], Result) :-
get_squared_pair(Head, Add),
append(Add,Result),
return_list(Tail, Result).
This doesn't work for a number of reasons, and it's mostly because I can't seem to figure out how the recursion actually works with lists, much less lists of lists. Also it's currently running in the wrong order which doesn't help.
I understand this might be a bit vague but I've tried googling my way out of this one but can't seem to translate what I find into my own problem very well.
Any help would be much appreciated!
Let's look at your get_squared_pair/2 first. Although it's working, it can be tidied up a bit which will also help understand how Prolog works. The primary mechanism of Prolog is unification, which is not the same as assignment which occurs in other languages. In unification, Prolog examines two terms and attempts to unify them by instantiating variables in one or both of the terms to make them match. There are some predicates in Prolog, like is/2 which are used to evaluate expressions in one argument, and then unify the first argument with that result.
Your first predicate, then, which you have written as:
get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].
get_squared_value(Number, Result) :-
Result is Number * Number.
Can be simplified in two ways. First, you can consolidate the get_squared_value/2 since it's just one line and doesn't really need its own predicate. And we'll rename the predicate so it's not imperative.
square_pair(Number, Square) :-
S is Number * Number, % Square the number
Square = [Number, S]. % Unify Square with the pair
Prolog can unify terms in the head of the clause, so you can avoid the redundant unification. So this is all you need:
square_pair(Number, [Number, Square]) :-
Square is Number * Number.
On to the main predicate, return_list/2. First, we'll rename this predicate to square_pairs. When doing recursion with lists, the most common pattern is to continue reducing a list until it is empty, and then a base case handles the empty list. Your implementation does this, but the base case is a little confused since the 2nd argument is an integer rather than a list:
square_pairs([], 0).
This really should be:
square_pairs([], []).
Your main predicate clause isn't making correct use of append/2. There are two forms of append in SWI Prolog: append/2 and append/3. You can look up what these do in the SWI Prolog online documentation. I can tell you that, in Prolog, you cannot change the value of a variable within a predicate clause once it's been instantiated except through backtracking. For example, look at the following sequence that might be in a predicate clause:
X = a, % Unify X with the atom 'a'
X = b, % Unify X with the atom 'b'
In this case, the second expression will always fail because X is already unified and cannot be unified again. However, if I have this:
foo(X), % Call foo, which unifies X with a value that makes 'foo' succeed
bar(X, Y), % Call bar, which might fail based upon the value of 'X'
In the above case, if bar(X, Y) fails, then Prolog will backtrack to the foo(X) call and seek another value of X which makes foo(X) succeed. If it finds one, then it will call bar(X, Y) again with the new value of X, and so on.
So append(Add, Result) does not append Add to Result yielding a new value for Result. In fact, append with two arguments says that the second list argument is the concatenation of all the elements of the first list, assuming the first argument is a list of lists, so the definition of append/2 doesn't match anyway.
When thinking about your recursion, realize that the argument lists are in one-to-one correspondence with each other. The head of the result list is the "square pair" for the head of the list in the first argument. Then, recursively, the tail of the 2nd argument is a list of the square pairs for the tail of the first argument. You just need to express that in Prolog. We can also use the technique I described above for unification within the head of the clause.
square_pairs([Head | Tail], [SqPair | SqTail]) :-
square_pair(Head, SqPair),
square_pairs(Tail, SqTail).
square_pairs([], []).
Now there's another simplification we can do, which is eliminate the square_pair/2 auxiliary predicate completely:
square_pairs([Head | Tail], [[Head, SqHead] | SqTail]) :-
SqHead is Head * Head,
square_pairs(Tail, SqTail).
square_pairs([], []).
There's a handy predicate in Prolog called maplist which can be used for defining a relationship which runs parallel between two lists, which is the scenario we have here. We can bring back the square_pair/2 predicate and use maplist:
square_pairs(Numbers, SquarePairs) :-
maplist(square_pair, Numbers, SquarePairs).
So you want to turn your list into another, such that each element (a number) is turned into a two-element list, the number and its square.
All you need to do is to tell that to Prolog. First, the second one:
turn_into_two(Num, [A,B]):-
what is A?
A is Num,
what is B? We just tell it to Prolog, too:
B is ... * ... .
Now, on to our list. A list [A|B] in Prolog consists of its head element A, and its tail B - unless it's an empty list [] of course. It doesn't matter what the list's elements are; a list is a list.
We need to account for all cases, or else we're not talking about lists but something else:
turn_list([], Res):-
so what is our result in case the list was empty? It should be empty as well, right?
Res = ... .
in the other case,
turn_list([A|B], Res):-
our result won't be empty, so it'll have its head and tail, correct?
Res = [C|D],
next we say what we know about the heads: the input list's head turns into that two elements list we've described above, right?
turn_into_two(A,C),
and then we say our piece about the tails. But what do we know about the tails? We know that one is the result of the conversion of the other, just as the whole list is:
turn_list( ... , ...) .
And that's it. Incidentally, what we've described, follows the paradigm of mapping. We could have used any other predicate in place of turn_into_two/2, and it would get called for each of the elements of the input list together with the corresponding element from the resulting list.
From what I have understood the declarative paradigm indicate what is important to reach the solution and not how reach it but, being accustomed to think procedurally, I often make confusion...
So the solution is this one:
mymember(X, [X|_]).
mymember(X,[_|T]) :- mymember(X,T).
This is my declarative interpretation of this simple program:
1) X belong to the list if it is TRUE that X is the Head of this list (if the head element of the list unifies with the X element that I would know if is in the list)
2) If the first fact is not true (X don't unifies with the first list element) the program try to execute the second rule (and maybe here I have some interpretation problem). This rule say that: the head is true if the body of the rule is true)
The head of rule say that: X belongs to the TAIL of the list (I use an anonymous variable using the _ character to say that don't care of the first element of the list)
So this rule say that: It is TRUE that the X element belong to list without its head if it is TRUE that the X element belong to the tail of the list
Is it a correct declarative and logic interpretation of this program or I am missing something?
You're reading them as exclusive-or, but they're actually inclusive-or. Both 1) and 2) are correct, minus the connective "if the first fact is not true". It's not necessary for 1) to be false for 2) to hold. In other words, it can be true that X is both the head of the list and present in the tail of the list (for instance mymember(a, [a, b, a]).
Edit: responding to your comment.
There's a language barrier issue here, so let me try answering your question with yes and no.
Yes, that using ; produces another answer is evidence that Prolog was able to compute alternative answers. In one sense, ; triggers backtracking manually, but in another sense it is Prolog asking you if this is the answer you wanted, and then you're able to say "yes" or "no." When you say ; you're telling Prolog, in essence, "this isn't the right answer." But this is not the only way to trigger backtracking; in fact, most of the time you won't trigger it manually at all.
For instance, let's look at this:
even_member(X, L) :- member(X, L), 0 is X mod 2.
?- even_member(X, [1,5,17,23,4,19]).
X = 4 ;
false.
So here I defined a predicate that says, declaratively, X is an even_member of L if X is a member of L and X mod 2 = 0. When I used the predicate, we got the answer X = 4. We then pressed ; to say, this isn't the right answer, and Prolog said there are no more answers. But internally, member(X, L) backtracked 5 times before it found an element that satisfied the second part of the predicate--in other words, the statement 0 is X mod 2 tells Prolog that 1, 5, 17 and 23 are "wrong" the same way we do by pressing ; interactively. When we said we wanted another answer, we engaged the same machinery, so Prolog went back to member(X, L), found 19, and then found that 19 is not divisible by two and gave up.
Prolog backtracked six times, five of those times just to get the one answer. We only asked it to backtrack once, and it happened that it was the last possibility so it didn't backtrack again.
Let me try:
mymember(X, [X|_]).
X is a member of the list if it's the first element of the list
mymember(X,[_|T]) :- mymember(X,T).
X is a member of the list if it's a member of the rest of the list.
Suppose I give you a stack of (paper) programmer resumes and say "see if there is a programmer who knows Prolog among these"
What do you do? You look at the top resume. If that programmer knows Prolog, you're done.
If not, then the only way there can be such a resume is if it's in the rest of the stack.
point 2) doesn't hold: Prolog will try each rule searching for a solution.
But it will follow a strictly specified order searching in your database, resulting in a depth first search of the solution space.
I would read
X is a member of a list if it is the first element (i.e. unify the head, clause 1), or is a member of the tail (clause 2).
In Prolog:
?-P=[A|B], P=[1,_].
P = [1, _G1091],
A = 1,
B = [_G1091]
B is shown as [_G1091] showing it's an uninstantiated variable. However, if I change a tiny bit...
?-P=[A|B], P=[1|_].
P = [1,B],
A = 1,
All of a sudden it's not interested in showing me that B is uninstantiated but still a variable ready to unify with anything.. how come? (I like to focus on weird details sometimes :) )
The precise details of Prolog syntax are sometimes quite subtle. To get used to it use write_canonical/1 which shows you the term in functional notation:
?- write_canonical([A|B]).
'.'(_1,_2)
true.
?- write_canonical([1,_]).
'.'(1,'.'(_1,[]))
true.
May I recommend a "drill"-exercise to get used to Prolog's list notation:
Take some list like [[1,2],3] and now try to write it down in as many variants you can imagine.
?- [[1,2],3] == [[1,2],3|[]].
true.
etc.
In many Prologs the toplevel lets you take the last input (often: cursor-up) such that you can re-edit the right-hand side rapidly.
In the first case:
?-P=[A|B], P=[1,_].
you are stating that P is a list with two elements, the first one being the number 1 (unified to variable A). Therefore, B has to be a list with one element (an unnamed variable).
On the other hand, in the second case:
?-P=[A|B], P=[1|_].
you are stating that P is a list with at least one element (1 again unified to A) but you are not stating anything else. B can be either an empty list, or a list with any amount of elements.
If you look at the second part of each query, the first amounts to
P=.(1,.(_,[]))
while the second amounts to
P=.(1,_)
In the first, B is bound to .(_,[]); that is, a list that contains an uninstantiated variable
In the second, B is bound to an uninstantiated variable
When a variable is just bound to an uninstantiated variable, there's no point in showing it; in the first example it's bound to something with some additional structure, so there is a point in showing it.
I have this code for splitting input list into its halves. It seems to be OK.
halve(List,A,B) :- halve(List,List,A,B), !.
halve(B,[],[],B).
halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :-halve(T,T2,A,B).
Ok, so I tried to decode it. The beginning is clear:
"Halve took list and 2 logic variables" is this:
halve(List,A,B)
(1) Then continuous this part:
:- halve(List,List,A,B).
And this means, that I am creating new two lists (List, List) from the first one or what? What exacly represents ":-"? I guess the new lists = halves will be the A, and B, right?
(2) Second, please, I don't quite get these two lines:
halve(B,[],[],B).
halve(B,[_],[],B).
Maybe you could explain it on some examples, please?
(3) Well, I hope after your explanation of (1) and (2), I'll get the final part by myself...
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Thank you very, very much for helping me.
Ok, our first problem already has its solution. Long story short, it works like this:
halve([1,2,3,4,5],[1,2],[3,4,5]).
->true
If you notice it splits the list into its halves but if the list has an odd number of the elements, the second half is the bigger one.
Now what I want to obtain is to have the first one bigger.
So I'm thinking about this:
I'm going to reach this:
Halves_div([1,2,3],A,B).
A=[1,2],
B=[3].
Let's say my input is list: [1,2,3]. So I'll start with splitting list's head and tail: [H|T] and then I will merge the H with new empty list - my 1st Half (A).
After that I have A=[1], B=[] and Input=[2,3].
For merging I have:
merge([],List,List).
merge([H|T],List,[H|New]) :- merge(T,List,New).
And one more thing - I need to check whether the 1st half is already >= 2nd half, right?
So this is my idea and only thing I'd love you to help me is to write it in prolog. I'm kinda confused how to put it together.
Thanks!
It seems my idea of solution is too complicated and I found something better!
To start, a Prolog clause looks like that:
Head :- Body
You can read that as "Head if Body", or "Body implies Head".
Note that sometimes you just have
Head
That's because Head is always true. Instead of calling Head a clause, we rather call it a fact in this case.
So here, we have:
halve(List,A,B) :- halve(List,List,A,B).
That means that halve(List, A, B) is true if halve(List, List, A, B) is true. Concretely it's just a way to delegate the work of halve/3 to halve/4, a so called worker predicate.
Why do we need a worker predicate? Well, because here we'd like to use another variable to calculate our A and B terms. But we couldn't do that with halve/3 because the 3 argument spots of halve/3 were already taken by the input list, List, the first half of the result, A and the second half of the result, B.
About the List, List thing, it's just a way to say that we call halve/4 with the same first and second argument, like you would in any programming language.
Then the interesting stuff starts. Prolog will try to prove that halve/4 is true for some given arguments. Let's say to illustrate the execution that we called halve/3 this way:
?- halve([1, 2], A, B).
Then, if you followed what I talked about previously, Prolog will now try to prove that halve/3 is true by proving that halve/4 is true with the following arguments: halve([1, 2], [1, 2], A, B)..
To do that, Prolog has 3 choices. The first choice is the following clause:
halve(B,[],[],B).
Obviously, that won't work. Because when Prolog will try to fit the second argument of the caller "in" the second argument of the callee through unification, it will fail. Because
[1, 2] can't be unified with [].
Only two choices left, the next is:
halve(B,[_],[],B).
Same thing here, Prolog cannot unify [1, 2] and [_] because _ is just a variable (see my post about the anonymous variable _ if you've troubles with it).
So the only chance Prolog has to find a solution to the problem you presented it is the last clause, that is:
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Here, Prolog will find a way to unify thing, let's see which way:
we have to unify [1, 2] with [H|T]. That means that H = 1. and T = [2].
we have to unify [1, 2] with [_,_|T2]. that means that T2 = [].
now we start to build our results with the next unification, ie A = [H|A'] (I primed the second A because variables are scoped locally and they are not the same). Here we tell that when we'll have our result calculated from the body of the clause, we'll add H to it. Here H is 1 so we already know that the first element of A will be 1.
Ok ok, unification succeeded, great! We can proceed to the body of the clause. It just calls halve/4 in a recursive manner with those values (calculated above):
halve([2], [], A, B).
And here we start all over again. Though this time things will be fast since the first choice Prolog has will be a good fit:
halve(B,[],[],B).
can be unified to
halve([2], [], A, B).
with those values: A = [] and B = [2].
So that's a good step, we now reached the "base case" of the recursion. We just have to build our result from bottom to top now. Remember when we called recursively our predicate halve/4 a few steps above? We had already said that the first element of A would be 1. Now we know that the tail is [] so we can state that A = [1]. We hadn't stated anything particular about B so B = [2] is left untouched as the result.
Now that I detailed the execution, you might wonder, why does this work? Well, if you pay attention, you'll note that the second argument of halve/4 is gone through twice as fast as the first one. [H|T] vs [_, _|T2]. That means that when we hit the end of the list with our second argument, the first one is still at the middle of our list. This way we can divide the thing in two parts.
I hope I helped you catch some of the subtle things at work here.
halve(List,A,B) copies first half of List to A and unifies second half with B
That will be true when length of our list will be even: halve(B,[],[],B).
That will be true when length of out list will be odd: halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Here we are setting 2 lets call them 'pointers' in each step we copy one element from beginning of our list to A because we want get first half.
Because in each step we are removing 2 elements from our list [_,_|T2] Predicate will stop when list will have only one left element or empty, then it will unify rest of our list with B. If you cant understand use trace/0
This version might prove useful ...
split_in_half(Xs, Ys, Zs) :- length(Xs, Len),
Half is Len // 2, % // denotes integer division, rounding down
split_at(Xs, Half, Ys, Zs).
split_at(Xs, N, Ys, Zs) :- length(Ys, N), append(Ys, Zs, Xs).