Prolog: Related predicates with permuted arguments - prolog

Is there a way to declare the following in Prolog without being caught in an endless recursion?
left([X,Y], Z) :- left([Z,X], Y); left([Y,Z], X).
The semantics is that the list represents a vector given by two points and the second argument is a third point lying left of the vector.
A related question is, how one can declare the relation of "left" and "right" given by:
left([X,Y], Z) :- right([Y,X], Z).
without getting an endless recursion.

Unfortunately, you cannot do this directly in Prolog. You can express commutative relationships by introducing a predicate that enumerates the permutations for the fact, so for example:
left_of(A, B, C) :- left(A, B, C).
left_of(A, B, C) :- left(C, A, B).
left_of(A, B, C) :- left(B, C, A).
left(a, b, c).
Now the query should be
?- left_of(A, B, C).
Similarly, you should define right_of in terms of left.
Several things worth noting:
Keep the three arguments separate, as shown. It is good practice not to introduce unnecessary structures.
Prefer explicit clauses, instead of ;. It makes your code far more obvious. The ; is really easy to miss when reading the code; if you use it, put it at the beginning of the line, not in the middle somewhere or at the end
Prolog implementations that support tabling do not have this problem.

Related

Prolog - programming a board game called Adugo

In the past few days I have tried doing the game Adugo in a prolog program, but Logic programming is a bit hard for me. I'm trying do it simple as possible, the initial matrix is :
[[1,1,1,0,0,0,0],
[1,1,1,0,0,0,0],
[1,1,2,0,0,0,0],
[1,1,1,0,0,0,0],
[1,1,1,0,0,0,0]]).
1 is for the dogs
2 is the jaguar
0 is nothing
The user will only control the dogs and the jaguar will be a bot.I have done this game in C++, but in Prolog I don't know how to do.
The game is quite fun. I have not yet completed the development,
but the basic idea is to use a predicate set_arg/4 to change the board
state. A predicate arg/3 is already found in the ISO core standard, it simply picks an argument from a compound. If it were not already predefined one could bootstrap via univ (=..)/2 as follows:
arg(K, C, A) :-
C =.. [_|L],
nth1(K, L, A).
Now the predicate set_arg/3 works similarly but its aim is not to access an argument, but instead to modify an argument. But since in Prolog terms are immutable, we simply return a new modified term and thus retain declarativity. It can be bootstrapped as follows:
set_arg(K, C, A, D) :-
C =.. [F|L],
nth1(K, L, _, H),
nth1(K, R, A, H),
D =.. [F|R].
Prolog implementors will not like such a bootstrapping, the univ (=..)/2 is notoriously a predicate that slows down the Prolog interpreter. In Jekejeke Prolog we have native support for a built-in set_arg/4 which makes it less a burden for the Prolog interpreter.
With set_arg/4 we can then implement the Adugo game moves relatively simple. Here is an example move, when a Jaguar (*) eats a Dog (o) by jumping over it. The link predicate represents the board topology including "streets":
move(S, K, *, T, K-I) :-
link(K, J, M),
arg(J, S, o),
N is M+1,
link(J, I, N),
arg(I, S, +),
set_arg(J, S, +, H),
set_arg(K, H, +, L),
set_arg(I, L, *, T).
Here is a screenshot of the midst of our game development. A game session can be started by the predicate game/2. The game/2 predicate cannot yet correctly detect an end of a game. But we are working on it:
Efficiency is not so bad. Since the Prolog interpreter allows just in time multi-argument indexing the move search via the link/3 topology database is quite fast. Other areas could be maybe improved, like a counter for the dogs and some alpha/beta pruning.

Merging two ordered lists ProLog

Hey so this is my code so far. I am only a begginer in prolog but i need it for school
firstElement([_|_], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2, merge([Elem1] , List1, [Elem2|List2]);
merge([], [Elem2], List2).
merge([Head|Tail], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2,!, add(Elem1,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], List1, [Elem2|List2]);
add(Elem2,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], [Elem1|List1], List2).
merge([Head|Tail], [], [Elem2|List2]):-
add(Elem2,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [Elem1|List1], []):-
add(Elem1,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [], []).
add(X,[],[X]).
add(X,[Y|Tail],[Y|Tail1]):-
add(X,Tail,Tail1).
I found out that everytime it gets out of a merge it keeps forgetting the last number so it gets back to nothing in the end.
I think you’ve gotten very mixed up here with your code. A complete solution can be had without helpers and with only a few clauses.
First let us discuss the two base cases involving empty lists:
merge(X, [], X).
merge([], X, X).
You don’t quite have these, but I see some sort of recognition that you need to handle empty lists specially in your second and third clauses, but I think you got confused and overcomplicated them. There’s really three scenarios covered by these two clauses. The case where both lists are empty is a freebie covered by both of them, but since that case would work out to merge([], [], []), it’s covered. The big idea here is that if you exhaust either list, because they were sorted, what you have left in the other list is your result. Think about it.
This leaves the interesting case, which is one where we have some items in both lists. Essentially what you want to do is select the smaller of the two, and then recur on the entire other list and the remainder of the one you selected the smaller value from. This is one clause for that:
merge([L|Ls], [R|Rs], [L|Merged]) :-
L #< R,
merge(Ls, [R|Rs], Merged).
Here’s what you should note:
The “result” has L prepended to the recursively constructed remainder.
The recursive call to merge rebuilds the entire second list, using [R|Rs].
It should be possible to build the other clause by looking at this.
As an intermediate Prolog user, I would be naturally a bit suspicious of using two clauses to do this work, because it’s going to create unnecessary choice points. As a beginner, you will be tempted to erase those choice points using cuts, which will go badly for you. A more intermediate approach would be to subsume both of the necessary clauses into one using a conditional operator:
merge([L|Ls], [R|Rs], [N|Ns]) :-
( L #< R ->
N = L, merge(Ls, [R|Rs], Ns)
; —- other case goes here
).
An expert would probably build it using if_/3 instead:
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
merge([L|Ls], [R|Rs], [N|Ns]) :-
if_(#<(L,R),
(N = L, merge(Ls, [R|Rs], Ns)),
( -- other case here )).
Anyway, I hope this helps illustrate the situation.

Prolog - remove the non unique elements

I have a predicate to check if the element is member of list and looks the following:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
When I called: ?- member(1,[2,3,1,4])
I get: true.
And now I have to use it to write predicate which will remove all non unique elements from list of lists like the following:
remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]],X).
X = [[t],[w],[i,b,b],[z,c]]
How can I do that?
Using library(reif) for
SICStus|SWI:
lists_uniques(Xss, Yss) :-
maplist(tfilter(in_unique_t(Xss)), Xss, Yss).
in_unique_t(Xss, E, T) :-
tfilter(memberd_t(E), Xss, [_|Rs]),
=(Rs, [], T).
Remark that while there is no restriction how to name a predicate, a non-relational, imperative name often hides the pure relation behind. remove is a real imperative, but we only want a relation. A relation between a list of lists and a list of lists with only unique elements.
An example usage:
?- lists_uniques([[X,b],[b]], [[X],[]]).
dif(X, b).
So in this case we have left X an uninstantiated variable. Therefore, Prolog computes the most general answer possible, figuring out what X has to look like.
(Note that the answer you have accepted incorrectly fails in this case)
Going by your example and #false's comment, the actual problem seems to be something like removing elements from each sublist that occur in any other sublist. My difficulty conceptualizing this into words has led me to build what I consider a pretty messy and gross piece of code.
So first I want a little helper predicate to sort of move member/2 up to lists of sublists.
in_sublist(X, [Sublist|_]) :- member(X, Sublist).
in_sublist(X, [_|Sublists]) :- in_sublist(X, Sublists).
This is no great piece of work, and in truth I feel like it should be inlined somehow because I just can't see myself ever wanting to use this on its own.
Now, my initial solution wasn't correct and looked like this:
remove([Sub1|Subs], [Res1|Result]) :-
findall(X, (member(X, Sub1), \+ in_sublist(X, Subs)), Res1),
remove(Subs, Result).
remove([], []).
You can see the sort of theme I'm going for here though: let's use findall/3 to enumerate the elements of the sublist in here and then we can filter out the ones that occur in the other lists. This doesn't quite do the trick, the output looks like this.
?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [a, w], [i, k, b, b], [z, m, m, c]].
So, it starts off looking OK with [t] but then loses the plot with [a,w] because there is not visibility into the input [a,m,t,a] when we get to the first recursive call. There are several ways we could deal with it; a clever one would probably be to form a sort of zipper, where we have the preceding elements of the list and the succeeding ones together. Another approach would be to remove the elements in this list from all the succeeding lists before the recursive call. I went for a "simpler" solution which is messier and harder to read but took less time. I would strongly recommend you investigate the other options for readability.
remove(In, Out) :- remove(In, Out, []).
remove([Sub1|Subs], [Res1|Result], Seen) :-
findall(X, (member(X, Sub1),
\+ member(X, Seen),
\+ in_sublist(X, Subs)), Res1),
append(Sub1, Seen, Seen1),
remove(Subs, Result, Seen1).
remove([], [], _).
So basically now I'm keeping a "seen" list. Right before the recursive call, I stitch together the stuff I've seen so far and the elements of this list. This is not particularly efficient, but it seems to get the job done:
?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [w], [i, b, b], [z, c]].
This strikes me as a pretty nasty problem. I'm surprised how nasty it is, honestly. I'm hoping someone else can come along and find a better solution that reads better.
Another thing to investigate would be DCGs, which can be helpful for doing these kinds of list processing tasks.

How do I make a rule fail without proving that something is false?

I am trying to make an invert/2. I want it to ignore the order of its arguments, so that you don't need to worry about which half of the inversion is the one you know, and so that you don't have to repeat yourself when stating inversions as facts. I currently have
invert(Left, Right) :-
call_with_depth_limit(invert(Right, Left), 1, Result),
Result \= depth_limit_exceeded.
as the first invert rule. This mostly works, but if invert(a, b)., then ?- invert(b, X). gives both X = a and false, which is not what I want at all.
There are two things I'd consider. First, make sure that the predicate you create for establishing the symmetry of the relationship in your facts has a different name than your facts. Having the name be the same usually leads to issues such as infinite recursion. Secondly, if the facts are under your control to declare, be consistent about whether the facts explicitly declare the symmetrical case or not. If they do, then you don't need the extra predicate. If they don't, then you need an extra predicate.
For example, with symmetries explicitly declared:
opposite(a, b).
opposite(b, a).
opposite(c, d).
opposite(d, c).
You don't need an extra predicate to get the symmetrical solutions for opposite.
An example where the symmetries are not explicitly declared:
opposite(a, b).
opposite(c, d).
inverted(X, Y) :- opposite(X, Y).
inverted(X, Y) :- opposite(Y, X).
In this case, querying inverted/2 instead of opposite/2 will handle the symmetry in the relationships.

Proper Subset - Prolog

I am attempting to write a program that takes two lists as input and checks for proper subset. I started with:
proper([A],[]).
proper([],[A]).
proper([A|T1],[A|T2]) :- proper(T1,T2).
This works perfectly fine for inputs in the exact same order. for instance:
?- proper([a,b,c],[a,b,c,d]).
Yes
But doesn't for inputs such as:
?- proper([a,b,c],[b,d,a,c]).
No
After looking through the site I found this previously asked question:
Subset function in prolog
Which lead me to modify my code as such:
proper([A],[]).
proper([],[A]).
proper([A|T1],[A|T2) :- member(A,T2), proper(T1,T2).
proper([H1|T1], [H2|T2]) :- \+ member(H1, T2).
This works fine for subsets but not for proper subsets. Which I think my problem is arising from my understanding of how the second clause of proper/4 works. Any and all help is greatly appreciated.
Edit:
Realized I was trying to determine if the first list was a proper subset of the second and the second was a proper subset of the first. Cleaned up the code to be more precise.
proper([],_).
proper([A|T1],[A|T2) :- member(A,T2), proper(T1,T2).
proper([H1|T1], [H2|T2]) :- \+ member(H1, T2).
If I understand correctly, the first two declarations in your last attempt would mean that, both a list with 1 element is a proper subset of an empty list (false), and that an empty list is a proper subset of a list with one element (true); the first one should be problematic, because proper([1], []) will succeed as well as proper([],[1]), but the proper subset relation is asymmetric.
I believe the reason that your second attempt doesn't filter out identical subsets is that you have no declaration that requires A to be smaller than B.
Here are some possible solutions I came up with. I use smaller_set/2 a couple times for increased clarity and concision.
smaller_set(A, B) :-
length(A, LA),
length(B, LB),
LA < LB.
def_proper_subset/2 tries to capture the standard definition of a subset.
def_proper_subset(A, B) :-
smaller_set(A, B), % if A < B then there's some _e in B that isn't in A.
forall(member(_e, A), member(_e, B)).
An example with recursive definition, based on removeing each matching element of A and B. It assures that A < B by only succeeding if A runs out of elements before B.
rec_proper_subset1([], [_|_]).
rec_proper_subset1([_e|A], B) :-
select(_e, B, C), % C is B with _e removed. Only true if _e is in B.
rec_proper_subset1(A, C).
This one uses an auxiliarry predicate to check membership once the main predicate has already assured that A < B.
rec_proper_subset2(A, B) :-
smaller_set(A, B),
rec_proper_subset2_(A, B).
rec_proper_subset2_([], _).
rec_proper_subset2_([_e|A], B) :-
member(_e, B),
rec_proper_subset2_(A, B).
Edit:
You'll need to use list_to_set/2, sort/2, or something similar if you want to be sure that your lists don't have any duplicate elements. But these kinds of solutions will also work to find sub lists.
I think def_proper_subset/2 is a kind of crappy solution, because it will only work to check that A is a subset of B but can't generate a subset of B in A. The other two are able to thought.
(I screwed up and forgot to include the ground definition for rec_proper_subset2/2, but I have now fixed it).

Resources