Prolog list of transitive pairs - list

I've been trying to solve the following problem for a while now, but can't seem to find the right solution.
Lets say there is a function test(X,Y,Z) such that X is a single pair of numbers, Y is a list of pairs, and Z is the resulting list of transitive pairs.
For example:
test((1,5), [(7,3),(5,2),(5,9)], Z).
Z = [(1,2),(1,9)]
(because of transitivity 1->5->2 and 1->5->9)
So far I've managed to create the following code:
test(_,[],_):- false.
test((X1,C),[(C,Y2)|_],(X1,Y2)).
test((X1,X2),[_|YT],Result) :- test((X1,X2),YT,Result).
It returns each individual result pair like so:
Z = (1, 2) ;
Z = (1, 9) ;
But I can't seem to return them all into a single list like in the example above:
Z = [(1,2),(1,9)]
Any help would be greatly appreciated.

I think the problem is that you're not building the list of transitive pairs. You're just returning a single pair as the third argument of test/3.
Here's one possible solution:
I made a predicate to handle comparing pairs and describing their transitive marriage, so that i didn't have to juggle those tuples in the subsequent rules:
transit((X,T), (T,Y), (X,Y)).
Then it's just a matter of standard list processing with recursive predicates:
t(_, [], []).
t(X, [T|ToTransit], [Y|Transited]) :-
transit(X,T,Y),
t(X,ToTransit,Transited).
t(X, [T|ToTransit], Transited) :-
\+ transit(X,T,_),
t(X,ToTransit, Transited).
Of course, once you have a predicate like transit/3 that defines the relation, you can also do something like
findall( TP,
( member(T, [(2,2), (2,5), (1,5)]), transit((1,2), T, TP) ),
Tps).

Related

Confused about workings of a Haskell list comprehension

I'm a new programmer and using Haskell. I've found a line of code called find that matches up a String with its corresponding pair in a list. Like so
find a b = [x|(y,x) <- b, a==y]
I don't understand fully what this program is saying, for the list comprehension, as I've never seen the x|(y,x) used in such a way before, I've mainly seen it used as x|x or x|x^2. So, does this mean that find the string A, from your input list B = a list comprehension of x, where x is a pair of (String, Char) from your B, and for which the y equals your inputted a? A little confused here.
I would pronounce that comprehension
The list of all x such that (y, x) is drawn from b and a == y.
Another way to read it, more sequentially:
Draw pairs (y, x) from b. For each such pair, check whether a == y. If so, produce x; otherwise, move on to the next one.
I should also note that the variable names are a bit confusing. It's idiomatic in Haskell to give lists or other containers plural names. So something more like
find a abs = [x | (y, x) <- abs, a == y]
You seem to view "x|x" as a thing. Rather, list comprehensions work like this:
[ expression to return | stuff to iterate over ]
What your example basically says is "draw (x, y) from b, throw away anything which doesn't satisfy a == y, and then return x".
Lets give you an example in order to visualize it:
find a b = [x|(y,x) <- b, a==y]
Let a=2, b=[(1,3),(2,4),(3,5),(2,7)]
(y,x) will get each of (1,3),(2,4),(3,5),(2,7) as a couple and check if the first element equals 2 (we said that a equals 2). If True, the function will return the second element of that couple - x, and put it in a list with the rest of the answers.
So the output for that function would be [4,7]

Prolog- Mappings (Associative Arrays)

I am studying prolog and was wondering if anybody give me guidance on how to go about doing this question, It's the first of many in this area and knowing how to do this question will really help me progress. Thank-you in advance.
Using Prolog define a predicate mapof(K, M, V) such that, when invoked with K instantiated to a key, and M instantiated to a mapping, mapof will instantiate the variable V to the value (or one of the values) associated with K in mapping M. The predicate should fail if K does not appear as a key in mapping M.
It really depends how you want to represent your "mapping". In Prolog, a table of facts is the most obvious approach. For two mappings m and n:
m(a, 1).
m(b, 2).
m(c, 3). % and so on
n(a, foo).
n(b, bar).
n(c, baz). % and so on
Then, your mapof would be something along the lines of:
mapof(K, m, V) :- m(K, V).
mapof(K, n, V) :- n(K, V).
or maybe:
mapof(K, M, V) :- call(M, K, V).
A list can be used to represent a mapping, as shown by #Yasel, but a list [a, b, c] in Prolog is a nested term like .(a, .(b, .(c, []))). You don't usually represent an associative array as a singly linked list, right?
In SWI-Prolog there is a library that is better than using a simple list for a backtrackable associative array represented as a Prolog term: library(assoc). With it, you can do:
mapof(K, M, V) :- gen_assoc(K, M, V).
This library represents the associative array as an AVL tree. You can find in the SWI-Prolog code source two more associative array implementations: one using RB-trees, and one that uses non-backtrackable RB-trees.
All three libraries mentioned here are probably more efficient than a simple list of key-value pairs [k1-v1, k2-v2...] if your associative array has more than say around 100 key-value pairs in it. This doesn't mean that using a list of pairs and doing member(Key-Value, List_of_pairs) is wrong; it is the cheapest solution for simple cases.
Using the built-in predicate member/2 you can build your predicate mapof/3 like this:
mapof(K, M, V):- member((K,V), M).
Consult:
?- mapof(k1, [(k, a),(k1,b),(k2,c),(k1,d)], V).
V = b ;
V = d.

Prolog Calling predicates within predicates correctly

I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
N is getDotProd(List, MH, _),
vecTimesMatrix(List, Mtail, N).
Updated Code thus far now:
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Your remaining problem is in your vecTimesMatrix predicate:
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Issues:
In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].
Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):
get_dot_prod([], [], 0.0). % Dot product of empty vectors is 0.0
% (Dot prod of vectors of unequal length
% is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :- % N is dot product of [H1|T1] [H2|T2] if...
get_dot_prod(T1, T2, N1), % N1 is dot product of T1 T2, and
N is N1 + (H1 * H2). % N is N1 + (H1*H2) [evaluated]
vec_times_matrix(_, [], []). % Product of any vector with
% empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
% [N|Ntail] is List x [MH|Mtail] if...
get_dot_prod(List, MH, N), % N is dot product of List and MH, and
vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
This will yield:
| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
M = [1.0,2.0] ? a
no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
M = [1.0,2.0,3.0] ? a
(1 ms) no
I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.
Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)
There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:
getDotProd([], [], 0).
Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:
N is getDotProd(List, MH, _)
You cannot define your own functions on standard Prolog. You need to replace that goal with:
getDotProd(List, MH, N)
There are other problems but this should help you progress.

How to add and compare members in a list

I'm trying to write a predicate is_multi(M), defined as:
every element of M has the form X / N, where X is an atom, and N is an integer greater than 0;
M does not contain two elements with the same atom, for what
is_multi([]).
is_multi([a / 2, b / 2]).
are satisfied, but
is_multi([a, b/2]).
is_multi([a/0, b/2]).
is_multi([a/2, 2/4])
is_multi([a/2, b/3, a/2])
is_multi([a/3, b/-4, c/1])
are not.
Here's what I have written so far:
is_multi(M) :- M = [].
is_multi(M) :-
M = [Head|Tail],
Head = X/N,
integer(N),
N > 0,
is_multi(Tail).
But it does not compare two elements if with the same atom. For example, is_multi([a/2, a/3]) is not satisfied. I got stuck for one day with this; could somebody give me some hints?
First, you can simplify your code considerably by moving some of your unifications from the body to the head.
is_multi([]).
is_multi([X/N|Tail]) :-
integer(N), N > 0,
is_multi(Tail).
Cleaning it up reveals one thing you're not doing here which is in your spec is checking that X is an atom. Fix by adding atom(X) to the body.
OK, so this takes care of the basic form, but doesn't ensure that the atoms do not repeat. The simplest thing to do would be to split this into two checks, one that checks that each item is well-formed, and one that checks that the list is well-formed. In fact, I would be inclined to use maplist/2 with a predicate that checks a single element. But all you really have to do is something like this:
is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).
This just says that the empty list is valid, and if the tail is valid, a list is valid if X over something doesn't occur in the tail.
If that's all you wanted, stop reading there. If you want to refactor, this is how I would approach it:
well_formed(X/N) :- atom(X), integer(N), N > 0.
no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).
is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
Just to complete Daniel's instructive answer (+1 by me), I want to showcase how your task could be solved by means of some library predicates:
is_multi(L) :-
forall(select(E, L, R),
(E = A/N, atom(A), integer(N), N > 0, \+memberchk(A/_, R))).

How can we denote list of tuples in argument

In sml, we define lists of integers or strings as arguments by l::ls which helps us to define lists of arbitrary length and then we can compare with = or > or <. How can we denote tuples in similar manner?
e.g.
I can write,
fun delete(x,l::ls)=if x=l then delete(x,ls) else l::delete(x,ls)
how can I write similarly for tuples?
Note, I even need to compare the individual elements of the tuple: i.e. (a1,b1)>(a2,b2) if b1>b2 so some sortcut that can merely delete like above will not be sufficient.
Tons of Thank You.
You can do pattern matching directly on tuples using the usual form (x, y).
Your delete function works on any 'a list so it is correct for lists of tuples as well. Here is an example which filters a list based on the first values in tuples:
fun deleteByFirst(x0, []) = []
| deleteByFirst(x0, (x, y)::ls) =
if x = x0
then deleteByFirst(x0, ls)
else (x, y)::deleteByFirst(x0, ls)