Related
Consider the following graph
and that it is described by the below Prolog term :
graph([connected(a,[b,c]), connected(b,[a,c]), connected(c,[a,b,d]), connected(d,[c]) ]).
I would like to define a predicate which transforms the above connections into a list of the corresponding pairs. In other words, a predicate which yields
[[a,b],[a,c],[b,c],[c,d]] for the above term-graph.
Could you please advise how to do it ?
My attempt so far is the following :
map 2-neighbor vertex to pairs :
map2ne(adjacent(H,[K|T]),Pair) :-
append([H],[K],L),
append([H],T,M),
append([L],[M],Pair).
This runs ok.
map 3-neighbor vertex to pairs :
map3n(adjacent(H,[K,L|T]),Pair) :-
append([H],[K],A1),
append([H],[L],A2),
append([A1],[A2],Z),
append([H],T,M),
append(Z,[M],Pair).
This also runs ok.
But when I try to extend it to n-neighbor vertex, then it fails :
mapmany(adjacent(H, [K|_]),Pair) :-
append([H],[K],L),
append(L,[],Pair),
mapmany(adjacent(H,[K|_]),M),
append(M,Pair,Pair).
And also the below fails, which was intented to map many n-neighbor vertices to pairs :
mapping(Map,Pairs) :-
select(X,Map,Y),
mapmany(X,PairX),
append([PairX],Pairs),
mapping(Y,Pairs).
If you're going to use a solution based on setof/3, I strongly recommend defining an auxiliary predicate. This predicate should define exactly what we want a set of. When we want to define "the set of all edges in the graph", mathematically we might say something like "Edges is the set of all Edge terms where Edge is an edge in Graph".
We can write this very directly as follows:
graph_edges(Graph, Edges) :-
setof( Edge,
graph_edge(Graph, Edge),
Edges ).
It remains to define graph_edge/2 itself. The core of this can be lifted from slago's solution:
graph_edge(Graph, Edge) :-
member(connected(V, Ns), Graph),
member(W, Ns),
edge(V, W, Edge).
The advantages of having this as a separate predicate are:
the setof call is easier to read
the predicate itself has a nice descriptive name
the predicate can be tested in isolation
the predicate can be reused
no ^ signs anywhere, which have no meaning in Prolog except for complicating setof calls that don't use an auxiliary predicate
no worrying about "existential quantification", which has no meaning in Prolog except for complicating setof calls that don't use an auxiliary predicate
There are too many flaws in your code:
The adjacency list defined by graph/1 is composed of terms of the form connected(Vertex, Neighbors); however, your code deals with an adjacency list of terms of the form adjacent(Vertex, Neighbors).
Predicate append/3 should not be used to create all lists; for example, instead of append([H], [K], L), you should use L = [H, K].
In Prolog, it is more idiomatic to represent a pair of items V and W as V-W, instead of [V,W].
By the answer you expect for the example given (i.e., [a-b,a-c,b-c,c-d]), a single term V-W (i.e., {V,W}) represents both the edges (V,W) and (W,V). So, to avoid redundancy, you must exclusively choose V-W or W-V to put in your answer (without loss of generality, you can choose the term where V precedes W).
To to create an edge, you can do the following:
edge(V, W, Edge) :-
( V #< W
-> Edge = V-W
; Edge = W-V ).
Examples:
?- edge(a, b, Edge).
Edge = a-b.
?- edge(b, a, Edge).
Edge = a-b.
To create all edges connecting a vertex V to its neighbors Ns, without duplicates, just ask:
?- V=a, Ns=[b,c,d], setof(E, W^Ns^(member(W,Ns), edge(V,W,E)), Edges).
V = a,
Ns = [b, c, d],
Edges = [a-b, a-c, a-d].
Notice that the construct Var^Goal tells setof/3 not to bind variable Var in Goal (in other words, indicates that Var is existentially quantified).
Generalizing this idea, we have:
graph_edges(Graph, Edges) :-
setof( Edge,
V^Ns^W^( member(connected(V, Ns), Graph),
member(W, Ns),
edge(V, W, Edge)),
Edges ).
graph([connected(a, [b, c]),
connected(b, [a, c]),
connected(c, [a, b, d]),
connected(d, [c])]).
Example:
?- graph(G), graph_edges(G, E).
G = [connected(a, [b, c]), connected(b, [a, c]), connected(c, [a, b, d]), connected(d, [c])],
E = [a-b, a-c, b-c, c-d].
LIBRARY UGRAPHS
In SWI-Prolog, a trivial solution would be to use the predicate edges/2 from library(ugraphs). Be careful though, because the representation of undirected graphs on which the predicate edge/2 is based is different from the one you are considering (an undirected graph in the library(ugraphs) is represented by a list of vertex pairs where the order of the vertices in these pairs matters). For example:
?- edges([a-[b,c], b-[a,c], c-[a,b,d], d-[c]], E).
E = [a-b, a-c, b-a, b-c, c-a, c-b, c-d, d-c].
i m doing associative list in prolog
i seen this topic but i dont understand the code.
Associative Lists in Prolog
For checking list is associative isn't enough do this:
lists([_X, _Y]).
lists([[H|_T]|L],[H|T]):- lists(L,T).
Because for first /1 i check if have element in this way [a,3]
and /2 take list of list [[a,4],[a,3]] in this way.
so first pass call list/2 on [a,3], and check true for base case, and after call [a,4] and call true for base case too.
I wrong something, but i don't see,
Anyone can clarify me?
OP's update of 2019-01-01 10:40:47Z:
I try to resolve in this way:
islist([_X,_Y]).
islist([_X|T]):- islist(T).
In this case accept just input in this way
[[k,v],[k,v],[k,v]]
but accept all input like this:
[a]
[k,v,v,v]
[[k,v],[k,v],[k,v,v]]
So my problem remains.
From the linked question:
"[] is the list ; [also, if] k is a key, v is a value and a is an
associative list, then [[k, v] | a] is an associative list."
Just write this down in Prolog:
associative_list(L) :- L = [].
associative_list(L) :- K=K, V=V, associative_list(A), L = [[K, V] | A].
Of course Prolog as a programming language has operational concerns as well as its logical semantics, so the last line is better written instead as
associative_list(L) :- L = [[_K, _V] | A], associative_list(A).
An idiomatic way to write this is
associative_list([]).
associative_list([[_, _] | A]) :- associative_list(A).
I have a matrix, where every element should be unique. To be honest, every element can take an integer value in [1, 19], but I got confused on handling list with variables with length(List, 3), so for now I have this:
matrix([[a,b,c],[d,e,f],[g,h,i]]).
row(M, N, Row) :-
nth1(N, M, Row).
column(M, N, Col) :-
transpose(M, MT),
row(MT, N, Col).
get_row(N, Row) :-
matrix(M),
row(M, N, Row).
diff_matrix(M) :-
matrix(M),
foo(M).
foo([]).
foo([H|T]) :-
length(H, Len),
write(Len),
foo(T).
different_from([], _).
different_from([H|T], E) :-
E \= H,
different_from(T, E).
Any idea to proceed with this code, or maybe another approach? I mean if my attempt is not good enough, I do not have problem replacing it.
EDIT:
I have atoms, because I do not know how to constraint variables
inside [1, 19], so I am trying to make it work with atoms, for now!
I want my code to test if matrix contains unique elements, i.e., for
every element found in the matrix, there is no duplicate element in
the matrix.
So far, I have only predicates that should help, nothing more, since
I am stuck.
A possible query: diff_matrix([[1,2,3],[4,5,6],[7,8,9]]).
A very compact, maybe inefficient, method based on indexing
rc(M,R,C,E) :- nth1(R,M,Row),nth1(C,Row,E).
diff_matrix(M) :-
forall((rc(M,I,J,X),rc(M,U,V,Y)), ((I\=U;J\=V)->X\=Y;true)).
edit
rc/4 is the relation among matrix M, row index R (1 based), column index C, and element E.
forall(Cond,Action) documentation states:
For all alternative bindings of Cond, Action can be proven.
So we can read diff_matrix/1 as
for all elements X (let's say, M[I,J]) and Y (M[U,V]) either I=U and J=V or X \= Y (doesn't unify)
currently learning about logic in computing as well as the foundations of Prolog. Please bear with me in my fumbling speech!
I've been faced with a problem where, given an query of a list of lists containing integers, one must devise a way to calculate the highest sum of all the lists using recursion.
For example:
?- getSum([[1,3,6],[9,5,2],[3,4,7]], X).
X = 16.
Should be the output.
I believe the correct way to find the sum of a list is:
sum([],0).
sum([Head|Body], Output) :- sum(Body, BodySum),
Output is Head + BodySum.
However I need to compare the sums before displaying the result, do I have to call to another conditional inside the sum recursion?
Thanks
Several comments first:
Naming: you probably want to name your predicate so that it is obvious what it does. And, Prolog prefers names_like_this to namesInCamelCase. So maybe, call it max_sublist_sum, maybe?
Implementation: in your question you say, "using recursion". Must you use recursion, or do you think that using recursion is your only choice? Since this is a trivial problem, it can be solved using library predicates and avoiding recursion altogether. For example, to find the sums of each sub-list:
maplist(sum_list, List_of_lists, Sums)
Now you have reduced your list of lists to a list of sums. You can find the largest of a list of numbers:
max_list(List_of_numbers, Max_number)
So, your problem becomes:
?- maplist(sum_list, [[1,3,6],[9,5,2],[3,4,7]], Sums),
max_list(Sums, Max_sum).
Sums = [10, 16, 14],
Max_sum = 16.
Now, it may seem as a good exercise to implement each of sum_list/2 and max_list/2, but a good starting point would be to look at the library implementation of these two. Same goes for the definition of maplist/3
You can also intertwine the two:
max_sublist_sum0([H|T], Max) :-
sum_list(H, Sum),
max_sublist_sum0_(T, Sum, Max).
max_sublist_sum0_([], Max, Max).
max_sublist_sum0_([H|T], M0, Max) :-
sum_list(H, Sum),
( Sum > M0
-> max_sublist_sum0_(T, Sum, Max)
; max_sublist_sum0_(T, M0, Max)
).
The helper predicate max_sublist_sum_/3 is in practice a fold:
max_sum(L, M0, M) :-
sum_list(L, Sum),
M is max(M0, Sum).
max_sublist_sum1([H|T], Max) :-
sum_list(H, Sum),
foldl(max_sum, T, Sum, Max).
However, this is still much more code than the original suggestion:
max_sublist_sum(L, M) :-
maplist(list_sum, L, S),
max_list(S, M).
Interestingly, on my computer this last version is also fastest for somewhat larger lists, and takes about the same time as the faster of the other two.
You don't need to call another condition inside the recursion, you have to decompose the problem into calculating the sum and the maximum. Following a classic implementation of a max predicate, where the second argument is the current maximum, this would be something like:
max([], X, X).
max([H|T], X, Y) :-
sum(H, S),
S < X,
max(T, X, Y).
max([H|T], X, Y) :-
sum(H, S),
S >= X,
max(T, S, Y).
getSum(L, X) :- max(L, 0, X).
You could make this code more efficient and elegant by using an if-construct or a cut, I leave this to you.
This is a followup to an answer to a question about sorting on a particular argument of a term, without creating a new list for a keysort (if I understood the original question correctly).
Say we wanted predsort/3 to behave exactly as sort/2: if I understand correctly, this would mean calling it as:
?- predsort(compare, List, Sorted).
Now say that we wanted to use predsort/3 to sort as implemented by msort/2 (see also this question). One way to do it would be to define a comparison predicate Pred(-Delta, +A, +B) that does not unify Delta with = when the elements are actually equal:
mcompare(Delta, A, B) :-
compare(Delta0, A, B),
( Delta0 == (=)
-> Delta = (<)
; Delta = Delta0
).
?- predsort(mcompare, List, Sorted).
Question: does that really simply sort without removing duplicates, as msort/2 does? It seems like it should.
Moving on: say we wanted to sort terms with arity > n, on the standard order of the nth argument in the term. The clean way to do it would be:
sort_argn(N, List, Sorted) :-
map_list_to_pairs(arg(N), List, Pairs),
keysort(Pairs, Sorted_pairs),
pairs_values(Sorted_pairs, Sorted).
If we wanted to use predsort/3 to achieve the same effect, we could try using a comparison predicate as follows:
compare_argn(N, Delta, A, B) :-
arg(N, A, AN),
arg(N, B, BN),
compare(Delta, AN-A, BN-B).
And to sort on the second argument:
?- predsort(compare_argn(2), List, Sorted).
However, this is not the same as sort_argn/3 above that uses keysort/2. It will remove duplicates, and it will order compound terms according to the standard order of the original full term if the second arguments of two terms happen to be equal:
?- predsort(compare_argn(2), [f(b,2), f(a,1), f(a,1), f(a,2)], Sorted).
Sorted = [f(a, 1), f(a, 2), f(b, 2)].
?- sort_argn(2, [f(b,2), f(a,1), f(a,1), f(a,2)], Sorted).
Sorted = [f(a, 1), f(a, 1), f(b, 2), f(a, 2)].
Making the assumption that for every pair of A and B passed to the comparison predicate Pred(Delta, A, B), A comes before B in the original list. Can we define a comparison:
compare_argn_stable(N, Delta, A, B) :-
arg(N, A, AN),
arg(N, B, BN),
compare(Delta0, AN, BN),
( Delta0 == (=)
-> Delta = (<)
; Delta = Delta0
).
At this point, if and only if any two elements A and B are always passed to the comparison predicate in the same order as they were in the original list, this should behave identically to sort_argn/3 above:
?- predsort(compare_argn_stable(N), List, Sorted).
Now of course it is important that compare_argn_stable/4 unifies Delta with < when the two "keys" are equal. Furthermore, the behavior is implementation dependent, and only identical to the keysort example iff predsort/3 keeps the original order of elements when passing them to the comparison predicate.
Question Is that correct?
Question Is there any standard that covers this aspect of predsort/3?
Since no one has answered, and since I am quite certain about it now:
Yes, you could use predsort/3 to emulate any of the other sorts. The question describes in some detail how.
However: this is a bad idea for several reasons.
The "stability" depends on the implementation of predsort/3 (see the question)
The predsort/3 itself is not part of any standard (as far as I can tell)
The chances are, your Prolog implementation provides an msort/2 or keysort/2 that is far more efficient than predsort/3
There might be rare cases where the size of the elements of the list is much bigger than the length of the list we are sorting, and this little dance:
list_to_keyval_pairs(List, Pairs), % defined by the user as necessary
keysort(Pairs, Sorted_pairs),
pairs_values(Sorted_pairs, Sorted)
(see here) is actually more expensive (slower) than using predsort(keycmp, List, Sorted), with keycmp/3 defined by the user. Even then, the order of results with equivalent keys depends not only on the (user) definition of keycmp/3, but also on the implementation of predsort/3.
In other words, a "stable" sort with predsort/3 is a bad idea.