Prolog Partial Matching - prolog

If there is a rule that cannot be satisfied with all parameters, is there a standard way to get a partial match with just some of the parameters?
For example, the following query can not find a solution:
?- query(A, B, C).
false.
But a solution can be found if we don't try to unify on C:
?- query_best_effort(A, B, C).
A = alfa,
B = bravo ;
I have the following code that implements this functionality. But is there a more Prolog-way to do this?
fact1(alfa).
fact2(bravo).
fact3(charlie).
rule1(A) :-
fact1(A).
rule2(B) :-
fact2(B).
rule3(C) :-
fact3(C),
C \== charlie.
query(A, B, C) :-
rule1(A),
rule2(B),
rule3(C).
query_best_effort(A, B, C) :-
query_chain3(A, B, C);
query_chain2(A, B);
query_chain1(A).
query_chain3(A, B, C) :-
query(A, B, C).
query_chain2(A, B) :-
\+query_chain3(A, B, _),
rule1(A),
rule2(B).
query_chain1(A) :-
\+query_chain2(A, _),
rule1(A).

First, a comment on programming style. When using disjunctions (;/2), always wrap them between parenthesis and avoid writing ; at the end of a line. In your case:
query_best_effort(A, B, C) :-
( query_chain3(A, B, C)
; query_chain2(A, B)
; query_chain1(A)
).
This recommended style contributes to code readability.
You can also avoid using negation (\+/1) by using instead the *->/2 soft-cut control construct implemented in several Prolog systems (a few systems, e.g. SICStus Prolog, implement it as an if/3 built-in predicate):
query_best_effort(A, B, C) :-
( query_chain3(A, B, C) *->
true
; query_chain2(A, B) *->
true
; query_chain1(A)
).
query_chain3(A, B, C) :-
query(A, B, C).
query_chain2(A, B) :-
rule1(A),
rule2(B).
query_chain1(A) :-
rule1(A).
The *->/2 control construct, unlike the standard ->/2 control construct, allows backtracking into the condition. When calling the query_best_effort/3 predicate, the query_chain2/2 predicate will only be called if there are no solutions for the query_chain3/3 goal and the query_chain1/1 predicate will only be called if there are no solutions for the query_chain3/3 and query_chain2/2 goals, which I assume was your intention with the use of disjunction and negation?
Sample call:
| ?- query_best_effort(A, B, C).
A = alfa
B = bravo
yes
Note, however, that *->/2 is, like negation, a non-logical control construct.

Related

Prolog: indicating which predicate is true in an OR rule

In SWI-Prolog I have some facts and I have rule that is composed of those facts in a disjunction like so:
father(a, b).
mother(a, c).
parent(A, X) :- father(A, X); mother(A, X).
This is all fine and all, and when I query I get this:
?- parent(a, X).
X = b ;
X = c.
I wonder if there's a way to write a rule that indicates which predicate was true for each result, like so:
?- parent(a, X).
X = b, R = father ;
X = c, R = mother.
Thank you!
Terms are an easy way to classify/categorize data, as an alternative to adding another variable, e.g.:
father(a, b).
mother(a, c).
parent(father(F), C) :- father(F, C).
parent(mother(M), C) :- mother(M, C).
Result in swi-prolog:
?- parent(P, C).
P = father(a),
C = b ;
P = mother(a),
C = c.
Here the parent has retained a categorization of father/mother rule, by creating the corresponding term.
You can also change your predicate to indicate if two persons are related, and how:
related(A, B, father(A,B)) :- father(A,B).
related(A, B, mother(A,B)) :- mother(A,B).
And maybe add a more general rule that indicates if there is a chain of relationships between to persons.
related(A, B, (R1,R2)) :- related(A,Z,R1), related(Z,B,R2).
If you don't want to rewrite your program you can trace it instead. This isn't in any way better than the other answers, it is just a different way to do it.
If I trace mother/2 and father/2, and only the exit port so I only see the success:
?- trace(mother/2, +exit), trace(father/2, +exit).
% mother/2: [exit]
% father/2: [exit]
true.
?- parent(a, X).
T [11] Exit: father(a, b)
X = b ;
T [11] Exit: mother(a, c)
X = c.
The predicates are documented here: https://www.swi-prolog.org/pldoc/man?section=debugger
There is a very nice tutorial-style overview here: https://www.swi-prolog.org/pldoc/man?section=debugoverview
I used this section in particular to answer your question: https://www.swi-prolog.org/pldoc/man?section=trace-mode-vs-point

(SWI)Prolog: Order of sub-goals

I have two, slightly different, implementations of a predicate, unique_element/2, in Prolog. The predicate succeeds when given an element X and a list L, the element X appears only once in the list. Below are the implementations and the results:
Implementation 1:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
member(Elem, T),
H\==Elem,
unique_element(Elem, T),
!.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
false.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Implementation 2:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
H\==Elem,
member(Elem, T),
unique_element(Elem, T),
!.
In case you didn't notice at first sight: H\==Elem and member(Elem, T) are flipped on the 2nd impl, rule 2.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
X = a.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Question: How does the order, in this case, affect the result? I realize that the order of the rules/facts/etc matters. The two specific rules that are flipped though, don't seem to be "connected" or affect each other somehow (e.g. a cut in the wrong place/order).
Note: We are talking about SWI-Prolog here.
Note 2: I am aware of, probably different and better implementations. My question here is about the order of sub-goals being changed.
H\==Elem is testing for syntactic inequality at the point in time when the goal is executed. But later unification might make variables identical:
?- H\==Elem, H = Elem.
H = Elem.
?- H\==Elem, H = Elem, H\==Elem.
false.
So here we test if they are (syntactically) different, and then they are unified nevertheless and thus are no longer different. It is thus just a temporary test.
The goal member(Elem, T) on the other hand is true if that Elem is actually an element of T. Consider:
?- member(Elem, [X]).
Elem = X.
Which can be read as
(When) does it hold that Elem is an element of the list [X]?
and the answer is
It holds under certain circumstances, namely when Elem = X.
If you now mix those different kinds of goals in your programs you get odd results that can only explained by inspecting your program in detail.
As a beginner, it is best to stick to the pure parts of Prolog only. In your case:
use dif/2 in place of \==
do not use cuts - in your case it limits the number of answers to two. As in
unique_element(X, [a,b,c])
do not use not/1 nor (\+)/1. It produces even more incorrectness. Consider unique_element(a,[a,X]),X=b. which incorrectly fails while X=b,unique_element(a,[a,X]) correctly succeeds.
Here is a directly purified version of your program. There is still room for improvement!
non_member(_X, []).
non_member(X, [E|Es]) :-
dif(X, E),
non_member(X, Es).
unique_element(Elem, [Elem|T]) :-
non_member(Elem, T).
unique_element(Elem, [H|T]) :-
dif(H,Elem),
% member(Elem, T), % makes unique_element(a,[b,a,a|Xs]) loop
unique_element(Elem, T).
?- unique_element(a,[a,X]).
dif(X, a)
; false. % superfluous
?- unique_element(X,[E1,E2,E3]).
X = E1, dif(E1, E3), dif(E1, E2)
; X = E2, dif(E2, E3), dif(E1, E2)
; X = E3, dif(E2, E3), dif(E1, E3)
; false.
Note how the last query reads?
When is X a unique element of (any) list [E1,E2,E3]?
The answer is threefold. Considering one element after the other:
X is E1 but only if it is different to E2 and E3
etc.
TL;DR: Read the documentation and figure out why:
?- X = a, X \== a.
false.
?- X \== a, X = a.
X = a.
I wonder why you stop so close from figuring it out yourself ;-)
There are too many ways to compare things in Prolog. At the very least, you have unification, which sometimes can compare, and sometimes does more; than you have equvalence, and its negation, the one you are using. So what does it do:
?- a \== b. % two different ground terms
true.
?- a \== a. % the same ground term
false.
Now it gets interesting:
?- X \== a. % a free variable and a ground term
true.
?- X \== X. % the same free variable
false.
?- X \== Y. % two different free variables
true.
I would suggest that you do the following: figure out how member/2 does its thing (does it use unification? equivalence? something else?) then replace whatever member/2 is using in all the examples above and see if the results are any different.
And since you are trying to make sure that things are different, try out what dif/2 does. As in:
?- dif(a, b).
or
?- dif(X, X).
or
?- dif(X, a).
and so on.
See also this question and answers: I think the answers are relevant to your question.
Hope that helps.
Here is another possibility do define unique_element/2 using if_/3 and maplist/2:
:- use_module(library(apply)).
unique_element(Y,[X|Xs]) :-
if_(Y=X,maplist(dif(Y),Xs),unique_element(Y,Xs)).
In contrast to #user27815's very elegant solution (+s(0)) this version does not build on clpfd (used by tcount/3). The example queries given by the OP work as expected:
?- unique_element(a,[a, a, b, c, c, b]).
no
?- unique_element(X,[a, b, c, c, b, d]).
X = a ? ;
X = d ? ;
no
The example provided by #false now succeeds without leaving a superfluous choicepoint:
?- unique_element(a,[a,X]).
dif(a,X)
The other more general query yields the same results:
?- unique_element(X,[E1,E2,E3]).
E1 = X,
dif(X,E3),
dif(X,E2) ? ;
E2 = X,
dif(X,E3),
dif(X,E1) ? ;
E3 = X,
dif(X,E2),
dif(X,E1) ? ;
no
Can you not define unique_element like tcount Prolog - count repetitions in list
unique_element(X, List):- tcount(=(X),List,1).

Prolog findall/3

Say I have a predicate pred containing several facts.
pred(a, b, c).
pred(a, d, f).
pred(x, y, z).
Can I use findall/3 to get a list of all facts which can be pattern matched?
for example, if I have
pred(a, _, _)
I would like to obtain
[pred(a, b, c), pred(a, d, f)]
Just summing up what #mbratch said in the comment section:
Yes, but you have to make sure that you either use named variables or construct a simple helper predicate that does that for you:
Named variables:
findall(pred(a,X,Y),pred(a,X,Y),List).
Helper predicate:
special_findall(X,List):-findall(X,X,List).
?-special_findall(pred(a,_,_),List).
List = [pred(a, b, c), pred(a, d, f)].
Note that this doesn't work:
findall(pred(a,_,_),pred(a,_,_),List).
Because it is equivalent to
findall(pred(a,A,B),pred(a,C,D),List).
And thus doesn't unify the Variables of Template with those of Goal.

Prolog , Append with no repititions

Hey I'm trying to append two list with no "double" members
for example
A = [a, b, c]
B = [x, c, q]
then ->
append2(A,B,P)
P= [a,b,c,x,q]
I write this code, but it doesn't work...
not_member(_, []).
not_member(X, [Y|Ys]) :- X \= Y, not_member(X, Ys).
append2(A, [], A).
append2([], A, A).
append2([h1|ls], B, [h1|P]) :- not_member(h1, B), !, append2(ls, B, P).
append2([h1|ls], B, P) :- member(h1, P), append2(ls, B, P).
Thanks for helping :)
Assuming there are no variables in your input lists, but allowing duplicates in each list you may write:
append2(A,B,C):-
findall(Item, append2_item(A,B,Item), C).
append2_item(A,_,ItemA):-
append(HeadA, [ItemA|_], A),
\+ member(ItemA, HeadA).
append2_item(A,B,ItemB):-
append(HeadB, [ItemB|_], B),
\+ member(ItemB, HeadB),
\+ member(ItemB, A).
First clause of append2_item/3 selects (ordered) distinct items from the first list. Second clause of append2_item/3 selects (ordered) distinct items from the second list which are not present in the first list.
append2/3 just collects those elements.
Test case:
?- append2([a,b,c,a],[x,c,q,x],C).
C = [a, b, c, x, q].
Check out the pure code in my answer
to the related question "intersection and union of 2 lists"!
Telling from your requirements, predicate list_list_union/3 is just what you are looking for:
?- list_list_union([a,b,c],[x,c,q],Ls).
Ls = [a,b,c,x,q]. % succeeds deterministically
list_list_union/3 is monotone, so we get sound answers
even when using non-ground terms:
?- As = [_,_,_], Bs = [_,_,_], list_list_union(As,Bs,Ls), As = [a,b,c], Bs = [x,c,q].
As = [a,b,c], Bs = [x,c,q], Ls = [a,b,c,x,q] ; % logically sound result
false.

setof in prolog

what is the source code of setof in prolog?
?- listing(setof).
:- meta_predicate setof(?,0,-).
setof(A, B, F) :-
free_variable_set(A, B, D, C),
( C==v
-> findall(A, D, E),
E\==[],
sort(E, F)
; findall(C-A, D, E),
( ground(E)
-> sort(E, G),
pick(G, C, F)
; bind_bagof_keys(E, _),
sort(E, G),
pick(G, C, H),
sort(H, F)
)
).
true.
In case you are looking for the Sicstus built-in predicate implementation, it can be found here: http://www.sics.se/sicstus/docs/4.2.1/html/sicstus/mpg_002dref_002dsetof.html as:
setof(+Template, +Generator, -Set)
Unlike findall/3 and bagof/3, setof does not return duplicates and does give sorted order.
I.

Resources