Prolog: inequality operator - prolog

I am using SICStus Prolog and have a set of facts:
student('John Henry', 'Maths').
student('Jim Henry', 'Maths').
student('John Alan', 'Maths').
student('Alan Smith', 'Computing').
student('Gary Henry', 'Maths').
I want to get the shared subject of two students where both students are different, so I got:
sharedSubject(S1, S2, Sub) :- S1 \== S2, student(S1, Sub), student(S2, Sub).
However, when I enter:
sharedSubject('John Henry', F, E).
I get F = 'John Henry'. Can someone point out where I am going wrong and what I need to do? Thanks.

Use dif/2 instead, or set the \== at the end of the rule - which is not as safe as dif/2. See also:
Difference between X\=Y and dif(X,Y)
What is the logical 'not' in Prolog?
Using \==/2 or dif/2

You must move the S1 \== S2 goal to the end as. If you call your sharedSubject/3 predicate with the second argument not instantiated, as in your sharedSubject('John Henry', F, E), the S1 \== S2 goal will always be true:
?- 'John Henry' \== S2.
true.
Also:
?- S1 \== S2.
true.
See the documentation of the standard (\==)/2 built-in predicate in your Prolog system documentation. In a nutshell, unless you want to test if two variables are the same, be sure that both arguments are instantiated when calling this term equality predicate.

Related

Are nested structures allowed in Prolog?

I'm working on defining the logical operators in Prolog as an exercise. The first few were pretty straight forward:
and(A, B) :-
A, B.
or(true).
or(A, _) :-
or(A).
or(_, B) :-
or(B).
neg(false).
But now I want to define nand and nor, and it would be nice to define them in terms of my other predicates. For example, maybe something like below:
nand(A, B) :-
neg(and(A, B)).
But the inner and expression doesn't evaluate. I'm guessing that Prolog interprets the and expression as an atom. Is there any way to force it to evaluate the nested predicate?
eval(true).
eval(or(A,_)):- eval(A),!.
eval(or(_,A)):- eval(A),!.
eval(and(A,B)):- eval(A),eval(B).
eval(neg(A)):- \+eval(A).
:- eval(true).
:- \+eval(and(true,false)).
:- eval(and(true,true)).
:- eval(neg(neg(true))).
:- halt.

Different order of interpretation depending on the context?

I have the following rules to convert a structure.
cmap(predicate(_,Verb,named(N)),[S1,S2]) :-
next_uid(NewVar),
S1 =.. [named,N,NewVar],
S2 =.. [Verb,NewVar].
cmap(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
the problem is that one rule needs clauses to be in one order and there is another rule that needs clauses to be in another order, as below :
cmap(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
cmap(predicate(_,Verb,named(N)),[S1,S2]) :-
next_uid(NewVar),
S1 =.. [named,N,NewVar],
S2 =.. [Verb,NewVar].
how can I do that ?
The problem fields are : named(N) <=> Subj
The reason I need different order is that case1(fact) I have value already assigned, in case2(question) I need the variable to be unbound, so that it can bind it later.
PS> if it make any difference the rule-call is two steps removed i.e. via another two rules.
here the exact usage . the diff is one does skolemization the other dont.
The question variables have to stay un-unified/free, so they can be used as a query.
In addition named(X), have to extracted as its own separate fact when it is in the structure /thats DRS weirdnes i have no control over/.
% provides/unifies ID for every Reference variable
skolem([]).
skolem([H|T]) :- next_uid(H), skolem(T).
convert([],[]).
% use the map to convert any Item
convert(Item-_,R) :- cmap(Item,R).
%processing Questions
convert(drs([], [question(drs(_Refs,Conds))]), Res) :- convert(Conds, Res).
%DRS processing
convert(drs(Refs,Conds),Res) :- skolem(Refs), convert(Conds,Res).
% process list of items
convert([H|T],[RH|RT]) :- convert(H,RH), convert(T,RT).
may be something along the lines of :
cmap(predicate(_,Verb,named(N)),[named(N,NewVar),S2]) :- next_uid(NewVar), cmap(predicate(_,Verb,?X?),S2).
You want to distinguish the cases by explicitly verifying whether the 3rd argument of predicate/3 is bound ("is a variable", to perform the standard language abuse). This is all very outside of first-order positive logic:
cmap(predicate(_,Verb,NN),[S1,S2]) :-
nonvar(NN),
!,
cmap_nonvar(predicate(_,Verb,NN),[S1,S2]).
Symmetrically (one can actually get rid of the var(NN),! as the test and the subsequent committement to the clause have already happened, but I like symmetry if it is not expensive:
cmap(predicate(_,Verb,NN),[S1,S2]) :-
var(NN),
!,
cmap_var(predicate(_,Verb,NN),[S1,S2]).
Modifications: Here we can get rid of one use of "univ", =../2 (don't use "univ" if you don't need it). Also, it's strange and unbalanced that the second argument is a list in one case and a non-list in the other case. Why not use a list in both cases?
"nonvar" case
Possible problem: for cmap_nonvar the second clause executes if the 3rd argument of predicate/3 does not unify with named(N) as well as if it unifies with named(N). Is that really wanted?
% if the 3rd argument of predicate/3 unifies with named(N)
cmap_nonvar(predicate(_,Verb,named(N)),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
cmap_nonvar(predicate(_,Verb,Subj),[S]) :-
S =.. [Verb,Subj].
"var" case
Possible problem: I suppose you do not want the second clause here, which is always executed as a second case with Subj unbound as Subj can be unified with named(N).
cmap_var(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
cmap_var(predicate(_,Verb,named(N)),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
Trick: tag the argument
"tagging" means enclosing a term into another term to be able to write Prolog code more idiomatically.
In this case, one can tag NN:
tag(X,var(X)) :- var(X),!.
tag(X,nonvar(X)) :- nonvar(X),!.
cmap(predicate(_,Verb,NN),[S1,S2]) :-
tag(NN,TaggedNN),
cmap_tag_aware(predicate(_,Verb,TaggedNN),[S1,S2]).
cmap can then match on the particular form of the passed term:
cmap_tag_aware(predicate(_,Verb,nonvar(named(N))),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
cmap_tag_aware(predicate(_,Verb,nonvar(Subj)),[S]) :-
S =.. [Verb,Subj].
cmap_tag_aware(predicate(_,Verb,var(Subj)),S) :-
S =.. [Verb,Subj].
cmap_tag_aware(predicate(_,Verb,var(named(N))),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].

Is there a way to do size comparison?

I have recently discovered the language Prolog and have been doing exercises on its basics. I am currently creating a database on animal classes like mammals, birds and reptiles, I want to expand the database by having a size comparison within the animals but not sure how.
Here is my database.
warm_blooded(bat).
warm_blooded(penguin).
cold_blooded(crocodile).
has_fur(bat).
has_feathers(penguin).
has_scales(crocodile).
gives_birth_live(bat).
lays_eggs(penguin).
lays_eggs(crocodile).
produces_milk(bat).
has_lungs(crocodile).
has_lungs(bat).
has_lungs(penguin).
%% if the being belongs to the mammalai class ,mammalia being the scientific word for mammal
mammalia(X) :-
warm_blooded(X),
produces_milk(X),
(
has_fur(X)
;
gives_birth_live(X)
),
format('~w ~s mammal ~n', [X, "is a"]).
%% if the being belongs to the aves class aves being the scientific word for bird
aves(X) :-
warm_blooded(X),
has_feathers(X),
lays_eggs(X),
has_lungs(X),
format('~w ~s bird ~n', [X, "is a"]).
%% if the being belongs to the reptillia class(reptillia being the scientific word for reptile
reptillia(X) :-
cold_blooded(X),
lays_eggs(X),
has_scales(X),
has_lungs(X),
format('~w ~s reptile ~n', [X, "is a"]).
I've tried adding sizes within the parameters but I keep getting compilation errors. I want to have an output wherein the user is able to determine which animal is bigger when compared with each other.
A simple an effective way is to just associate a size fact with each animal.
size(bat,1).
size(penguin,2).
size(crocodile,3).
Then add one predicate with two clauses to chose the larger of the two animals.
larger(A,B,A) :-
size(A,S1),
size(B,S2),
S1 > S2.
larger(A,B,B) :-
size(A,S1),
size(B,S2),
S2 >= S1.
Examples:
?- larger(penguin,crocodile,X).
X = crocodile.
?- larger(penguin,bat,X).
X = penguin ;
false.
?- larger(bat,bat,X).
X = bat.
Note that for examples where the the second animal is smaller, it tries the first clause and succeeds, but then has a choice point and so tries the second clause and fails. This is the pure solution.
If you want to use a cut to avoid the choice point, which is impure, you can do the following
larger_2(A,B,A) :-
size(A,S1),
size(B,S2),
S1 > S2,
!.
larger_2(A,B,B) :-
size(A,S1),
size(B,S2),
S2 >= S1,
!.
Examples:
?- larger_2(penguin,crocodile,X).
X = crocodile.
?- larger_2(penguin,bat,X).
X = penguin.
?- larger_2(bat,bat,X).
X = bat.
Another way as noted by Daniel Lyons is to use ->/2
larger_3(A,B,Larger) :-
size(A,SA),
size(B,SB),
(
SA > SB
->
Larger = A
;
Larger = B
).
This variation is not one operator of just ->/2 but a combination of both ->/2 and ;2.
This also does not leave a choice point and is impure because it too uses a cut (!). Using listing/1 we can see the implementation in Prolog.
?- listing('->'/2).
:- meta_predicate 0->0.
system:A->B :-
call(( A
-> B
)).
true.
?- listing(;/2).
:- meta_predicate 0;0.
system:A:B;A:C :- !,
call(A:(B;C)).
system:A:B;C:D :-
call(A:(B;C:D)).
true.
Notice the cut !.
How the two operators work together is noted in the SWI-Prolog documentation.
The combination ;/2 and ->/2 acts as if defined as:
If -> Then; _Else :- If, !, Then.
If -> _Then; Else :- !, Else.
If -> Then :- If, !, Then.
One other point to note about the use of ->/2 with ;/2 is that the syntactic layout among many Prolog programmers is to use () with the combination and offset the operators ->/2 and ;2 so that the ; stands out.
(
% condition
->
% true
;
% false
)
When a ; is used as an OR operator and not offset the ; is often overlooked in doing a quick scan of the source code as it is seen as a comma , instead of a ;.
Also note the absence of . or , after
SA > SB
and
Larger = A
and
Larger = B
but at the end an operator is needed,
).

Way to make Prolog syntax look like first order logic syntax?

I am looking for ways to make a Prolog program "look" more like first order logic. Things I would like to have are for example:
-> for implication
antecedent to the left of ->
^ for conjunction v for disjunction
Or is there other software that already implements this?
Thanks in advance!
/JC
Update 20190313
I followed the suggestions in the answers below and tried this:
:- op(1200, xfx, ==>).
:- op(1000, xfy, /\).
:- op(1100, xfy, \/).
term_expansion(A ==> B, B:- A).
term_expansion(A /\ B, A, B).
term_expansion(A \/ B, A; B).
man(X) /\ unmarried(X) ==> bachelor(X).
man(john).
man(peter).
unmarried(john).
main:-bachelor(X), writeln(X), nl, fail.
But i get the following error:
ERROR: bachelor/1: Undefined procedure: (/\)/2
Exception: (5) man(_1740)/\unmarried(_1740) ?
Only using the op/3 and term_expansion/3 for ==> however works as expected. Not sure why this is so...
Use term_expansion/2 that is macro of Prolog on SWI-Prolog:
% calc.pl
:- op(1200,xfx,--).
term_expansion(A--B,B:-A).
integer(I)
--%----------------------- (E-Int)
I => I.
E1=>I1, E2=>I2, I is I1+I2
--%----------------------- (E-Add)
E1+E2 => I.
:- 1+2+3=>6.
:- 1+2+3=>I,writeln(I).
:- halt.
and run
$ swipl calc.pl
6
Here are a few Unicode characters that can help you:
¬
→ ⇒
← ⇐
∨ ∧
∀ ∃
I leave defining suitable precedences as a challenge, using op/3.
Once you have these definitions, you can write first-order sentences with them. You can then convert these sentences to Prolog, or interpret them with Prolog.
This answer refers to your updated question ("Update 20190313").
Be careful when defining operators:
Don't redefine standard operators, changing their specifier/precedence.
This can introduce errors in existing code which are very hard to find.
Weigh benefits and costs upfront.
Aim at readability, shorter code, and fewer parentheses.
Keep in mind that using too many custom Prolog operators can also obfuscate code and confuse the reader.
Think twice before using standard operators in different domains.
Let's take the predefined (\/)/2 as an example.
It is an evaluable functor in arithmetic expressions—used with (is)/2, (=:=)/2, (<)/2, etc.
clpfd uses it for representing set unions like 1..3 \/ 5..7—fine!
However, using it for denoting list concatenation is questionable.
Let's get to your actual question!
Consider these queries decomposing some terms using (=..)/2 ("univ"):
?- term_expansion(A /\ B, A, B) =.. Xs.
Xs = [term_expansion, A/\B, A, B].
?- term_expansion(A \/ B, A; B) =.. Xs.
Xs = [term_expansion, A\/B, (A;B)].
So it's term_expansion/2 for (\/)/2, but term_expansion/3 for (/\)/2!
The bottom line: (',')/2 terms as arguments need parentheses.
?- term_expansion(A /\ B, (A,B)) =.. Xs.
Xs = [term_expansion, A/\B, (A,B)].

Prolog difference routine

I need some help with a routine that I am trying to create. I need to make a routine that will look something like this:
difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X).
X = [(b,c),(d,e)].
I really need help on this one..
I have written a method so far that can remove the first occurrence that it finds.. however I need it to remove all occurrences. Here is what I have so far...
memberOf(A, [A|_]).
memberOf(A, [_|B]) :-
memberOf(A, B).
mapdiff([], _, []) :- !.
mapdiff([A|C], B, D) :-
memberOf(A, B), !,
mapdiff(C, B, D).
mapdiff([A|B], C, [A|D]) :-
mapdiff(B, C, D).
I have taken this code from listing(subtract).
I don't fully understand what it does, however I know it's almost what I want. I didn't use subtract because my final code has to be compatible with WIN-Prolog... I am testing it on SWI Prolog.
Tricky one! humble coffee has the right idea. Here's a fancy solution using double negation:
difference([], _, []).
difference([E|Es], DL, Res) :-
\+ \+ member(E, DL), !,
difference(Es, DL, Res).
difference([E|Es], DL, [E|Res]) :-
difference(Es, DL, Res).
Works on SWI-PROLOG. Explanation:
Clause 1: Base case. Nothing to diff against!
Clause 2: If E is in the difference list DL, the member/2 subgoal evaluates to true, but we don't want to accept the bindings that member/2 makes between variables present in terms in either list, as we'd like, for example, the variable in the term (a,_) to be reusable across other terms, and not bound to the first solution. So, the 1st \+ removes the variable bindings created by a successful evaluation of member/2, and the second \+ reverses the evaluation state to true, as required. The cut occurs after the check, excluding the 3rd clause, and throwing away the unifiable element.
Clause 3: Keep any element not unifiable across both lists.
I am not sure, but something like this could work. You can use findall to find all elements which can't be unified with the pattern:
?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res).
gets the reply
Res = [ (b, c) ]
So
removeAll(Pattern, List, Result) :-
findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result).
should work, assuming ZZ109 isn't a variable in Pattern (I don't know a way to get a fresh variable for this, unfortunately. There may be a non-portable one in WIN-Prolog). And then difference can be defined recursively:
difference(List, [], List).
difference(List, [Pattern|Patterns], Result) :-
removeAll(Pattern, List, Result1),
difference(Result1, Patterns, Result).
Your code can be easily modified to work by making it so that the memberOF predicate just checks to see that there is an element in the list that can be unified without actually unifying it. In SWI Prolog this can be done this way:
memberOf(A, [B|_]) :- unifiable(A,B,_).
But I'm not familiar with WIN-PRolog so don't know whether it has a predicate or operator which only tests whether arguments can be unified.

Resources