How to accept one of two configurations of predicate arguments - prolog

Say i have two variables A and B, and two predicates firstPred() and secondPred()
I'm trying to express something along the lines of:
(firstPred(A) && secondPred(B)) || (firstPred(B) && secondPred(A))
I currently have
firstPred(A),
secondPred(B).
but this only covers the first case. How can i add support for the second?

Reference to predicates in Prolog use the notation Name/Arity, where Arity is the number of arguments. Therefore, instead of writing firstPred() and secondPred(), write instead firstPred/1 and secondPred/1. Better yet, following Prolog coding guidelines, use underscores instead of CamelCase when naming predicate.
To answer your question, you need to define a predicate to check your condition. This predicate will take two arguments. A direct translation of your condition would be:
condition(A, B) :-
( first_predicate(A),
second_predicate(B)
; first_predicate(B),
second_predicate(A)
).
But this is not considered good style and it's preferable to use instead two clauses:
condition(A, B) :-
first_predicate(A),
second_predicate(B)
condition(A, B) :-
first_predicate(B),
second_predicate(A).
Note that this solution assumes that the disjunction in the condition is not an exclusive disjunction. Is that the case?

Related

current_predicate in SICStus Prolog

SICStus Prolog offers both current_predicate/1 and current_predicate/2.
The manual page states:
current_predicate(?PredSpec)
Unifies PredSpec with a predicate specifications of the form Name/Arity.
current_predicate(?Name, ?Term)
Unifies Name with the name of a user-defined predicate, and Term with the most general term corresponding to that predicate.
They appear to have the same features:
both predicates work for enumerating predicates, both work with modules.
The manual page comments:
current_predicate/1 is part of the ISO Prolog standard; current_predicate/2 is not.
Should I ever use current_predicate/2 in new (= non-legacy) code?
Short answer, no. Don't use it in new code.
The benefit of current_predicate/2 was to allow querying, using a predicate call template, if the predicate is defined, unlike current_predicate/1. E.g.
...,
( current_predicate(_, foo(_, _)) ->
foo(A, B)
; ...
),
...
But you can often use instead the standard predicate_property/2 predicate, which takes a template as first argument.
P.S. The Logtalk linter will scream at you (and suggest a more standard alternative) if it finds you calling current_predicate/2 :-)

How to check for empty Arguments in Prolog?

I'm new to prolog and could use some help.
Currently, I have to make a program that concat the last character of two strings.
For example,
?- termCat(with,spaghetti,T).
T=hi
I was wondering how can I account for one of the arguments being nonexistant.
For instance I'm hoping to catch something like this...
?- termCat( , spaghetti,T).
T = i
I use this pattern for 'default arguments' (the C++ feature, kind of). Depending on your use case and Prolog system, you should adapt as required. Beware that var/1, nonvar/1, !/0 are impure builtins that could interfere in unexpected ways with the resolution process. The cut (that is, !/0) is implicit in ->/2.
termCat(X,Y,T) :-
(var(X) -> X=with;true),
(var(Y) -> Y=spaghetti;true),
etc etc.
In SWI-Prolog, you can require arguments are not free - for instance - using assertion/1 from library(debug):
:- use_module(library(debug)).
termCat(X,Y,T) :-
assertion((nonvar(X),nonvar(Y))),
etc etc.

Is there a way to annotate the parameter and return value in Prolog?

parent(mel, joan).
parent(jane, betty).
parent(jane, tom).
parent(richard, adam).
parent(richard, rosa).
parent(joan, fran).
For example someone asks me to find all ancestors of a parent. I give him the code:
ancestor(P,C) :- parent(P, C).
ancestor(P,C) :- ancestor(P,P1), parent(P1, C).
But my friend still doesn't know how to use the predicate. Does he call it like
ancestor(richard, C) or ancestor(C, richard) ?
Is there a way to annotate that P is the parameter while C is the return value? And in a complex case, there will be predicates with different names, how should my user know which predicate is the final predicate he wants to use?
To help the human-readable meaning, you could add an extra predicate documenting the parameters as readable name/value pairs:
entry_ancestor_of(ancestor=P, descendent=C) :-
ancestor(P,C).
?- entry_ancestor_of(ancestor=richard, descendent=C).
C = adam .
Above, the suffix *ancestor_of* suggests param 1 is ancestor of param 2, so naming the predicate carefully can make it clearer.
Usually(convention), input parameters are the earlier parameters, and output parameters are later parameters, but where the predicate 'works both ways', ie. either could be input or output, this rule can't hold. This is the case for your predicate:
?- entry_ancestor_of(ancestor=X, descendent=adam).
X = richard .
Either parameter could be input or output, so there is no need to codify/explain them as such, although you might want to comment that it works both ways.
I would usually comment these 'flexible' predicates by putting an example of both of the above usages in a comment next to the predicate.
For entrypoint labelling, just do one or more of the following:
explicitly name the predicate as an entrypoint, as above
document using comments in the code which are the entrypoints
arrange the entrypoints in the same physical section with a comment
block saying that the predicates below are entrypoints.
Edit: Extra things re: coding guidelines / other answers.
In Coding guidelines for Prolog, section 3.8, it says 'For example, mother_of(A, B) is ambiguous;', so I gave bad advice on that.. perhaps acapelli's suggestion would be more useful on that.
In that document, also have a look at:
3.5 Choose sensible names for auxiliary predicates
3.8 Choose predicate names to help show the argument order
3.13 Decide whether predicate names should carry the types on which they operate
4.1 Begin every predicate (except perhaps auxiliary predicates) with an introductory comment in a well-defined format
The '?' system for identifying parameter types that will ness mentioned is on page 21.
a useful convention, sponsored for instance by Markus Triska, builds a predicate functor by joining the parameters 'names' - in a wide, applicable sense. Your example could be
parent_child(mel, joan).
...
ancestor_descendant(P, C) :- parent_child(P, C).
ancestor_descendant(A, D) :- ancestor_descendant(A, I), parent_child(I, D).
Also ISO-Prolog, and - for instance - SWI-Prolog library, attempt to follow this strategy.
For instance
atom_codes(Atom, Codes) :- ...
WRT to declare the type and status of arguments, some Prolog provide declarations - for instance Turbo Prolog, ECLiPSe, others... Sometime such declarations are required - usually to check correctness, often to speed up the computation.
SWI-Prolog offers 'just' structured comments, that IDE process automatically, and there has been a contribution aiming to exploit such declarations with runtime check.
Yes, with comments, and/or meaningful argument names,
% ancestor( ?Ancestor, ?Descendent).
ancestor(P,C) :- parent(P, C).
ancestor(P,C) :- ancestor(P,P1), parent(P1, C).
? means the argument can be used both as input (already set when the call is made), or for output (not yet set when the call is made).
The convention promoted in The Art of Prolog (I think) is that you place the name of the predicate after its first argument, to get at the intended argument ordering: P "is" ancestor C. Presumably "ancestor_of". But if you use that name, someone unfamiliar with that convention might read ancestor_of(P,C) as "ancestor of P is C", so it's a double-edged sword.

Redefined AND operator in Prolog

I want to redefine AND operator in SWI-Prolog . But I do not know how to do it.
I tried the following definition:
a & b = b & a
However, it is reported as recursive and does not work.
Wish people give me suggestions.
Thanks in advance!
You could define an operator in SWI-Prolog using op/3, such as by adding the following to your program:
:- op(1000, xfy, user:(&)).
Note that the precedence level (1000) and type (xfy) are the same as that for the conjunction operator which is already defined in SWI-Prolog (i.e., see ','/2).
Then, once declared, you can define the semantics of & as follows:
'&'(A,B) :- A, B.
Together, these two definitions will permit you to use & in-line as a replacement for , to mean conjunction in the program which incorporates them.
You can "define" and as follows:
and(t,X,X) :- bool(X).
and(f,X,f) :- bool(X).
bool(t).
bool(f).
The third argument is the result of the conjunction of the first and the second argument.
Of course, this is just an exercise, but indeed it is hard to answer your question as it is not very clear what your question is all about.

How to do this in one function

I was wondering how to do the answer (or first function) to this question in Prolog only using one predicate? The link I'm referring to is here.
Here's an example of what I mean by only calling one predicate:
reverse([X|Y],Z,W) :- reverse(Y,[X|Z],W).
reverse([],X,X).
What are you trying to do and why do you want just one clause for the predicate?
personally I believe that having the ability to write many clauses is one of the great things of prolog and the code is more elegant and readable that way
Anyway, you will probably want to use or. assuming that you have the following clauses:
foo(Arg11,Arg12,Arg13):-
(Body1).
foo(Arg21,Arg22,Arg23):-
(Body2).
foo(Arg31,Arg32,Arg33):-
(Body3).
you should first make sure that every clause has the same arguments (bye bye pattern matching there!):
foo(Arg1,Arg2,Arg3):-
(Body1b).
foo(Arg1,Arg2,Arg3):-
(Body2b).
foo(Arg1,Arg2,Arg3):-
(Body3b).
and then you will use or (;):
foo(Arg1,Arg2,Arg3):-
(Body1b)
; (Body2b)
; (Body3b).
for example,
reverse([X|Y],Z,W):-
reverse(Y,[X|Z],W).
reverse([],X,X).
will become:
reverse(X,Y,Z):-
X = [H|T],
reverse(T,[H|Y],X).
reverse(X,Y,Z):-
X = [],
Z = Y.
and then:
reverse(X,Y,Z):-
(X = [H|T],
reverse(T,[H|Y],X) )
; (X = [],
Z = Y). *%ew ew ugly!*
regarding the example on your first post, there are two different predicates, each having just one clause. the second predicate has 2 arguments while the first one has 1 therefore they are different. The only way to "merge" them would be by simply calling the second one as has_equal_sums(List, _) in the place of the first.
To be honest, I dont see the point of doing this; I doubt you will not get any significant speedup and the code becomes way messier.
Of course, it's your code and there can be restrictions we dont know (that's why I asked what you want to accomplish)

Resources