Prolog Beginner: Reverse List only once - list

Assume I have two arbitrary lists that represent the first two items of a 3-place predicate:
[anna,berta,charlotte],[charles,bob,andy]
I want to match every item in a third list (the third item of the 3-place predicate) as follows:
[[anna,andy],[berta,bob],[charlotte,charles]]
Basically the items get matched in a sequentially reverse fashion. To match the items in a sequential manner, I've devised the following code:
match([],[],[]).
match([A|At],[C|Ct],[[A,C]|Dt]):-match(At,Ct,Dt).
But this would give me the following:
match([anna,berta,charlotte],[charles,bob,andy],X).
X=[[anna,charles],[berta,bob],[charlotte,andy]]
So I need to reverse the second list somehow. So far, I've altered the code as follows:
match([],[],[]).
match([A|At],[C|Ct],[[A,B]|Dt]):-reverse([C|Ct],[B|Bt]),match(At,Bt,Dt).
But this would continually reverse the second list with each pass. The result would look as follows:
match([anna,berta,charlotte],[charles,bob,andy],X).
X=[[anna,andy],[berta,charles],[charlotte,bob]]
Question:
How do I reverse the second list only ONCE, so the actual results match the desired ones? Or is my approach fundamentally flawed? I'm new to prolog and am currently stymied by this. Any help would be appreciated.

Do exactly what you say: Reverse the list once, and then use the reversed list.
lists_pairs(Ps1, Ps2, Pairs) :-
reverse(Ps2, RPs2),
pairs_keys_values(Pairs, Ps1, RPs2).
You can check out the source code of reverse/2 and pairs_keys_values/3 in any decent Prolog library to see how it is defined.
Sample query and answer:
?- lists_pairs([anna,berta,charlotte], [charles,bob,andy], Ps).
Ps = [anna-andy, berta-bob, charlotte-charles].
I leave converting such pairs to the non-sensible "pair as list" representation as an exercise.

The trick to solving problems that require you to apply a rule only once is to build an auxiliary rule which performs extra steps before and/or after invoking the recursive rule:
match(A, B, R) :- reverse(B, RevB), match_impl(A, RevB, R).
match_impl([], [], []).
match_impl([A|At], [C|Ct], [[A,C]|Dt]) :- match_impl(At, Ct, Dt).
match_impl/3 is your match/3 rule renamed to avoid conflicting with the "top" match/3 rule that includes an auxiliary step.

This is a small followup to #mat's answer.
To aid termination in some cases you could add a redundant same_length_as/3 goal like so:
lists_pairs(Ps1, Ps2, Pairs) :-
same_length_as(Ps1, Ps2, Pairs),
reverse(Ps2, RPs2),
pairs_keys_values(Pairs, Ps1, RPs2).
The auxiliary predicate same_length_as/3 can be defined like this:
same_length_as([],[],[]).
same_length_as([_|As],[_|Bs],[_|Cs]) :-
same_length_as(As,Bs,Cs).

Related

Prolog: put recursive predicates into Variable

I'm beginner in prolog and I need to resolve the following exercise:
Write a 3-predicate prereqchain(P,Q,L) that, given two courses P and Q, returns in L a representation of all the steps on a prerequisite path from P to Q.
For example prereqchain(comp085,itec450,L) should give the answer
L=prerequisite(comp085, comp101,
prerequisite(comp101, comp281,
prerequisite(comp281, itec450))).
Basically, the knowledge data base stand for the prerequisite relationship between the degree's courses. My main problem is, How can I capture the recursive calls trace and put it into variable ? On the other hand, is not really all the trace, because I just need the calls where the variables was replaced with the values.
Thanks a lot!
What's your base case? It's going to look like this:
prereqchain(Start, End, prerequisite(Start, End)) :-
prerequisite(Start, End).
This gives you the following situation:
?- prereqchain(comp281, itec450, L).
L = prerequisite(comp281, itec450).
So this is the first thing you need, now what happens when you ask for prereqchain(comp101, itec450)? You need an inductive case that follows the rest of the chain:
prereqchain(Start, End, prerequisite(Start, Middle, Tail)) :-
prerequisite(Start, Middle),
prereqchain(Middle, End, Tail).

Prolog Predicate Solution

I am going through some past exam questions for my prolog exam that is coming up.
Here is the question:
(a) Write a predicate insert(Xs, Y, Zs) that holds when Zs is the list obtained
by inserting Y into the list Xs. A query such as:
? - insert([1,2,3], 4, Zs).
should succeed four times and give the following answers:
Zs = [4, 1, 2, 3]
Zs = [1, 4, 2, 3]
Zs = [1, 2, 4, 3]
Zs = [1, 2, 3, 4].
I'm a bit concerned because I have no idea where to start. Would anyone be able to help out as I need example solutions to practice for my exam.
Would really appreciate any help with this.
We start by changing the terrible name of this predicate: The predicate should describe what holds, not what to do. The name should reflect that. I suggest list_with_element/3, and encourage you to try finding even better names, ideally making clear what each argument stands for.
Then, we do what we set out to do: Describe the cases that make this relation hold.
For example:
list_with_element([], E, [E]).
list_with_element([L|Ls], E, [E,L|Ls]).
list_with_element([L|Ls0], E, [L|Ls]) :-
...
I leave filling in the ... as an easy exercise. State the condition that is necessary for the clause head to be true!
EDIT: I would like to say a bit more about the pattern above. In my experience, a good way—and definitely in the beginning—to reason about predicates that describe lists is to consider two basic cases:
the atom [], denoting the empty list
terms of the form '.'(E, Es), also written as [E|Es], where E is the first element of the list and Es is again a list.
This follows the inductive definition of lists.
The drawback in this specific case is that this approach leads to a situation where case (2) again needs to be divided into two subcases, and somehow unexpectedly necessitates three clauses to handle the two basic cases. This obviously runs counter to our intuitive expectation that two clauses should suffice. Indeed they do, but we need to be careful not to accidentally lose solutions. In this case, the first two clauses above are both subsumed by the fact:
list_with_element(Ls, E, [E|Ls]).
Every experienced Prolog coder will write such predicates in this way, or just, as in this case, use select/3 directly. This is what #lurker sensed and hinted at, and #tas correctly shows that a different clause (which is easy to come up with accidentally) does not fully subsume all cases we want to express.
Thus, I still find it a lot easier to think first about the empty list explicitly, make sure to get that case correct, then continue with more complex cases, and then see if you can write the existing program more compactly. This is the way I also used for this sample code, but I did not make it as short as possible. Note that with monotonic code, it is completely OK to have redundant facts!
Note that is is specifically not OK to just replace the first two clauses by:
list_with_element([L|Ls], E, [E|Ls]).
because this clause does not subsume case (1) above.
I guess that one answer that the question might be looking for goes along these lines:
insert(List, Element, NewList) :-
append(Front, Back, List), % split list in two
append(Front, [Element|Back], NewList). % reassemble list
If you would like a declarative reading:
NewList has Element between the front and the back of List.
Check carefully if append/3 or a predicate with the same semantics appears in the earlier questions or the study material.
And note that this is in essence the exact same solution as the suggestion by #mat, if I understand it correctly. Consult the textbook definition of append/3 for details. Or even better, look at the textbook definition of append/3 and adapt it to use if for "inserting".
There is a built-in predicate select/3 that does the same thing, although with the arguments in a different order.
Remember that (if defined correctly) a predicate can work in different directions. For instance, it can tell you what a list would look like after removing an element, it can (although it's fairly trivial) tell you what element to remove from one list to get another, or it can tell you what lists, after having a given element removed, would resemble a given list.
(Hint: you may want to look into that last one).

Prolog Insert the number in the list by the tail

How can I build a predicate in prolog that receives a number and a list, I must insert the number in the list by the tail
I tried inserting the number in the list by the head: insert(H,[P|Q],[H,P|Q]). and it works, but how can I do it by the tail?
Simply use append/3 like this:
?- append([a,b,c,d],[x],List).
List = [a,b,c,d,x].
Inserting at the tail can be done with a two-part recursive rule:
When the list is empty, unify the result to a single-element list with the item being inserted
When the list is not empty, unify the result to a head followed by the result of inserting into the tail of a tail.
English description is much longer than its Prolog equivalent:
ins_tail([], N, [N]).
ins_tail([H|T], N, [H|R]) :- ins_tail(T, N, R).
Demo.
Nobody talked about difference lists yet.
Difference lists
Difference lists are denoted L-E, which is just a convenient notation for a couple made of a list L whose last cons-cell has E for its tail:
L = [ V1, ..., Vn | E]
The empty difference list is E-E, with E a variable. You unify E whenever you want to refine the list.
For example, if you want to add an element X, you can unify as follows:
E = [X|F]
And then, L-F is the new list. Likewise, you can append lists in constant time. If you unify F with a "normal" list, in particular [], you close your open-ended list. During all operations, you retain a reference to the whole list through L. Of course, you can still add elements in front of L with the ususal [W1, ..., Wm |L]-E notation.
Whether or not you need difference lists is another question. They are intereseting if adding an element at the end is effectively a common operation for you and if you are manipulating large lists.
Definite clause grammars
DCG are a convenient way of writing grammar rules in Prolog. They are typically implemented as reader macros, translating --> forms into actual predicates. Since the purpose of grammars is to build structures during parsing (a.k.a. productions), the translation to actual predicates involves difference lists. So, even though both concepts are theoretically unrelated, difference lists are generally the building material for DCGs.
The example on wikipedia starts with:
sentence --> noun_phrase, verb_phrase.
... which gets translated as:
sentence(S1,S3) :- noun_phrase(S1,S2), verb_phrase(S2,S3).
A lot of "plumbing" is provided by the syntax (a little like monads). The object being "built" by sentence/2 is S1, which is built from different parts joined together by the predicates. S1 is passed down to noun_phrase, which builds/extends it as necessary and "returns" S2, which can be seen as "whatever extends S1". This value is passed to verb_phrase which updates it and gives S3, a.k.a. whatever extends S2. S3 is an argument of sentence, because it is also "whatever extends S1", given the rule we have. But, this is Prolog, so S1, S2 and S3 are not necessarly inputs or outputs, they are unified during the whole process, during which backtracking takes place too (you can parse ambiguous grammars). They are eventually unified with lists.
Difference lists come to play when we encounter lists on the right-hand side of the arrow:
det --> [the].
The above rule is translated as:
det([the|X], X).
That means that det/2 unifies its first argument with an open-ended list which tail is X; other rules will unify X. Generally, you find epsilon rules which are associated with [].
All the above is done with macros, and a typical error is to try to call an auxiliary predicate on your data, which fails because the transformation add two arguments (a call to helper(X) is in fact a call to helper(X,V,W)). You must enclose actual bodies between braces { ... } to avoid treating prediates as rules.
Here is an another option.
insert(N,[],[N]).
insert(N,[H|T],[H|Q]) :- conc([H|T],[N],[H|Q]).
conc([],L,L).
conc([H|T],L,[H|Q]) :- conc(T,L,Q).

Prolog create list of lists

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.

SWI Prolog scalar multiplying with accumulators

so I've been working on the following question:
Write a 3-place predicate scalarMult whose first argument is an
integer, whose second argument is a list of integers, and whose third
argument is the result of scalar multiplying the second argument by
the first. For example, the query
?- scalarMult(3,[2,7,4],Result).
should yield
Result = [6,21,12]
Do this with the help of an accumulator and a wrapper predicate.
This is what I have done:
scalarMult(I, List1, List2):- scalarMult1(I, List1, [], List2).
scalarMult1(I,[], A, A).
scalarMult1(I,[H|T], A, Result):- H1 is H*I, scalarMult1(I,T,[H1|A],Result).
The only trouble with this is that it's putting the new elements at the head of the accumulator so I kind of end up with a reversed list (so for the example above, I would get Result = [12,21,6]). Is there any way I could work around this? I tried using reverse in my code but all my attempts fails.
Thanks
using reverse/2 works, actually:
scalarMult(I, List1, List2):- scalarMult1(I, List1, [], T), reverse(T, List2).
but I think the requirement to use an accumulator (really useless here) could be on purpose to verify your level of lists handling.
Noting Carlo's remark about the use of accumulators being for didactical purposes, no accumulator is required for a straight-forward definition of the scalar_multiplication/3 predicate (renamed from scalarMult/3; camel case is not considered good programming style in Prolog):
% first exchange argument orders to take advantage of the first-argument
% indexing that is provided in most Prolog implementations
scalar_multiplication(Scalar, Numbers, ScaledNumbers) :-
scalar_multiplication_(Numbers, Scalar, ScaledNumbers).
% base case; either input list was empty or we finished traversing the list
scalar_multiplication_([], _, []).
% recursive case
scalar_multiplication_([Number| Numbers], Scalar, [ScaledNumber| ScaledNumbers]) :-
ScaledNumber is Number * Scalar,
scalar_multiplication_(Numbers, Scalar, ScaledNumbers).
This is an instance of a common pattern for processing lists. So common that several Prolog implementations provide a second-order predicate (or meta-predicate), usually named map/3 or maplist/3, to handle it.