If I want to make sure that two variables do not instantiate to the same term, what is the preferred way to do it?
Let's say I need to find directed edges in a graph, and a node cannot have an edge to itself:
node(a, x, y). node(b, z, x). node(c, y, y).
(the edges here are a -> c, b -> a, but not c -> c)
The following works:
edge(A, B) :- node(A, _, X), node(B, X, _), A \== B.
This works too [swi-prolog]:
edge(A, B) :- dif(A, B), node(A, _, X), node(B, X, _).
This does not work, apparently (because neither A nor B are instantiated yet?):
edge(A, B) :- A \== B, node(A, _, X), node(B, X, _).
I guess my problem with the first solution is that, with a more complex node predicate, a lot of unnecessary unifications might take place before edge fails. The dif on the other hand is in a library, which suggests that it is not meant to be used in such a simple case (although it has the exact function that I seem to be looking for).
For elegance and didactic reasons alone, dif/2 is clearly preferable here and also in the vast majority of other cases, since as you already note "a lot of unnecessary unifications might take place" otherwise, and also because dif/2 is a pure and nicely declarative predicate that can be used in all directions and at any place in the clause body without changing the meaning of the program, in contrast to (\==)/2. dif/2 is also an autoloaded predicate in SWI-Prolog, meaning that you need not import any library explicitly to use it, and dif/2 is available like any built-in predicate.
If you use dif/2 you can reason much more easily about your code. For example, in your case, you start with:
edge(A, B) :- node(A, _, X), node(B, X, _), dif(A, B).
and then, as you know that dif/2 is a completely pure predicate, you know that you can also write this as:
edge(A, B) :- dif(A, B), node(A, _, X), node(B, X, _).
Further, since you know that dif/2 always terminates, you know that this change can at most improve the termination properties of your program.
Like all constraints, dif/2 is meant to be used. I highly recommend it instead of impure predicates that are not commutative.
In case you are worried about performance, here is a small comparison, just comparing dif/2 against the non-declarative (\==)/2 in a use case where the two predicates can be used interchangeably:
?- N = 1_000_000, time((between(1,N,_),dif(a,b),false)).
% 11,000,005 inferences, 0.352 CPU in 0.353 seconds (100% CPU, 31281029 Lips)
?- N = 1_000_000, time((between(1,N,_),a\==b,false)).
%# % 3,000,001 inferences, 0.107 CPU in 0.107 seconds (99% CPU, 28167437 Lips)
So, there are sometimes performance benefits when using (\==)/2. However, there are also much more severe drawbacks when using such a low-level predicate: It is harder to understand, more error-prone, and not declarative.
I therefore recommend to simply use dif/2 to express that two terms are different.
The queries are meta-interpreted and the overhead may outweigh the differences of dif(X,Y) and X\==Y. You should compare these two predicates:
t1:-
1000=I,
time(t1(I)).
t1(I):-
dif(X,Y),
between(1,I,X),
between(1,I,Y),
false.
t2:-
1000=I,
time(t2(I)).
t2(I):-
between(1,I,X),
between(1,I,Y),
X\==Y,
false.
On B-Prolog, I got the following results:
| ?- cl(t)
Compiling::t.pl
compiled in 0 milliseconds
loading::t.out
yes
| ?- t1
CPU time 0.14 seconds.
no
| ?- t2
CPU time 0.078 seconds.
no
| ?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false )).
CPU time 0.234 seconds.
no
| ?- 1000=I,time(( between(1,I,X), between(1,I,Y), X \== Y, false )).
CPU time 0.218 seconds.
First of all, dif/2 and (\==)/2 mean the same when both arguments are ground, that is variable free. So if you can ensure that the arguments will be ground — or rather sufficiently instantiated such that further instantiations will not affect the outcome of (\==)/2 — then it does not make a difference.
In your example, we would need to know for sure that answers for node/3 contain always a ground first argument. In that case, the (\==)/2 program is fine. In rare cases it might be less efficient than the dif/2 version. Think of the goal edge(X, X).
In many situations, the (\==)/2 or even (\=)/2 is significantly more efficient. On the other hand, how important is efficiency when compared to correctness?
Another way of seeing this, is to consider (\==)/2 and (\=)/2 as approximations from two sides: Only if both agree, do we have a safe final outcome.
Historically, dif/2 is one of the oldest built-in predicates. It was present in the very first Prolog system which is sometimes called Prolog 0 to distinguish it from the next version which is often perceived to be the first Prolog — the Marseille Prolog — Prolog 1. Prolog 1 did no longer have dif/2 and it is in this shape that Prolog came to Edinburgh. Also,dif/2 is not part of the ISO standard (currently) since it requires some coroutining-like mechanism. And many (rather older) Prolog systems do not have such a mechanism. However, even in ISO Prolog one could do better:
iso_dif(X, Y) :-
X == Y,
!,
fail.
iso_dif(X, Y) :-
X \= Y,
!.
iso_dif(X, Y) :-
throw(error(instantiation_error,iso_dif/2)).
(Here is another, probably more efficient implementation)
Note how the problematic cases are covered by an error that stops the entire computation.
Current Prolog systems that support dif/2 right out of the box are B, SICStus, SWI, YAP. It is in a library of IF, Ciao, XSB, Scryer.
See also this answer.
To support my claim about the overheads, here is a test in various Prologs on the same machine. In SWI, there is an overhead of a factor of 10, in B, there is no overhead. As has been noted by #nfz, numbers are slightly different when compiling things. So your mileage may vary.
SWI 6.3.4-55
?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false )).
% 22,999,020 inferences, 5.162 CPU in 5.192 seconds (99% CPU, 4455477 Lips)
false.
?- 1000=I,time(( between(1,I,X), between(1,I,Y), X \== Y, false )).
% 2,000,001 inferences, 0.511 CPU in 0.521 seconds (98% CPU, 3912566 Lips)
false.
B 7.8
| ?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false )).
CPU time 0.364 seconds.
no
| ?- 1000=I,time(( between(1,I,X), between(1,I,Y), X \== Y, false )).
CPU time 0.356 seconds.
no
YAP
?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false )).
% 2.528 CPU in 2.566 seconds ( 98% CPU)
no
?- 1000=I,time(( between(1,I,X), between(1,I,Y), X \== Y, false )).
% 0.929 CPU in 0.963 seconds ( 96% CPU)
no
Related
If for example, I have a Prolog predicate like
a(A, B).
Is it possible to collect, given a value of A, is it possible to collect all values of B that succeeds the predicate a, into a list, without using built in predicates such as bagof/3 or findall/3.
You have two obvious options (obvious to me; it seems there is more). One is to indeed use the database to save the state. This has at least one pitfall: depending on the name you decide to use for the temporary state, you might destroy some other state your program is keeping. This is the same old "global state"/"global variable" problem that all languages suffer from.
The other option would be to use a "local variable" and non-backtracking assignment to it to keep the temporary state. This is most probably going to be implementation dependent. For starters, you can look at nb_setarg/3 for SWI-Prolog.
However, both solutions are silly, given that you have findall, bagof, setof. You must motivate the need for something else to replace those. Just saying "is it possible" is not good enough since it is possible, but completely unnecessary, unless you know something else that you aren't telling us.
Here's a sketch of a stupid setof that uses other builtins, though not assert, and not exactly the ones listed by #false in a comment.
We'll use a list accumulator to collect solutions:
stupid_setof(Template, Goal, Set) :-
stupid_setof(Template, Goal, [], Set).
There are two cases to consider: Either the Goal can enumerate a solution we have not seen so far, or the only ones it can enumerate are already in our accumulator.
First, the case where there are no solutions we haven't seen. In this case we're done.
stupid_setof(Template, Goal, SolutionsSeen, Set) :-
\+ ( call(Goal),
\+ member(Template, SolutionsSeen) ),
!,
sort(SolutionsSeen, Set).
Now for the stupid part. Consider:
foo(a).
foo(b).
foo(c).
?- SolutionsSeen = [], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [],
X = a.
?- SolutionsSeen = [a], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [a],
X = b.
?- SolutionsSeen = [a, b], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [a, b],
X = c.
?- SolutionsSeen = [a, b, c], foo(X), \+ member(X, SolutionsSeen), !.
false.
So given a list of solutions we've seen before, we can force Goal to backtrack until it gives us one that we haven't seen before. Note that these queries are independent: In each one we have a completely fresh copy of the foo(X) goal that starts enumerating from a.
We can do the same thing programmatically by copying the original goal before calling it, forcing it to start a fresh enumeration from a fresh instance of the Goal. If this finds a new solution, we can add it to our solutions, then repeat with another fresh copy of the goal, forcing it to enumerate yet another new solution, and so on:
stupid_setof(Template, Goal, SolutionsSeen, Set) :-
copy_term(Goal-Template, GoalInstance-Solution),
call(GoalInstance),
\+ member(Solution, SolutionsSeen),
!,
stupid_setof(Template, Goal, [Solution | SolutionsSeen], Set).
If Goal has N answers, this will enumerate on the order of N**2 of them and do corresponding linear searches in the solutions list. It will also perform any side effects that Goal has multiple times.
But it "works":
?- stupid_setof(X, foo(X), Xs).
Xs = [a, b, c].
And, despite all of its stupidity, this is still less stupid than the standard setof/3 if Goal has no solutions:
:- dynamic bar/1. % no clauses
?- setof(X, bar(X), Set).
false.
?- stupid_setof(X, bar(X), Set).
Set = [].
There is a lot of hype around the dif/2 constraint, especially as a rescue for some non-declarativity of (\=)/2 and (\==)/2. This non-declarativity is often characterized as non-monotonicity and examples of non-communtativity are given.
But what would be the means to test whether test cases involving dif/2 are commutative. Here is a meta explanation what I want to do:
I make a commutativity test, and I want to probe that both variants
give the same result:
?- A, B.
-- versus --
?- B, A.
So usually you can check monotonicity, if it boils down to checking commutativity, with the (==)/2 built-in predicate. Since this predicate follows instantiated variables.
But if you are testing cases that produce constraints, call_with_residue/2
is not enough, you need also to have equality of constraints. Which can
be tricky, as the following example shows:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.23)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- dif(f(X,X),f(a(U,g(T)),a(g(Z),U))), X=a(g(Z),U).
X = a(g(Z), U),
dif(f(a(g(Z), U), U, Z, U, T), f(a(U, g(T)), g(Z), T, g(Z), Z)).
?- X=a(g(Z),U), dif(f(X,X),f(a(U,g(T)),a(g(Z),U))).
X = a(g(Z), U),
dif(f(U, T), f(g(Z), Z)).
Any ideas how to proceed?
Disclaimer, its a trap:
I don't endorse commutativity testing as a good testing method, where you can separate good and bad predicates versus a specification. Since usually both the good and bad predicates might have no problems with commutativity.
I am using commutativity testing as a vehicle to find out about methods for equality of dif/2 constraints. This equality can then be used in more traditional test cases as a validation point.
There are several ways. Maybe the easiest in this case is to simply re-post the collected residual constraints.
In this example, we get:
?- X = a(g(Z), U),
dif(f(a(g(Z), U), U, Z, U, T), f(a(U, g(T)), g(Z), T, g(Z), Z)).
X = a(g(Z), U),
dif(f(U, T), f(g(Z), Z)).
The goal is now much simpler!
You can collect residual goals with copy_term/3 and call_residue_vars/2.
Are Hilog terms (i.e. compounds having as functors arbitrary terms) still regarded as a powerful feature in XSB Prolog (or any other Prolog) ?
Are there many XSB projects currently using this feature ? which of them for example ?
I ask since as far as I understand higher order programming is equally possible using the ISO built-in call/N.
Specifically, I would like to understand if XSB is using Hilog terms just for historical reasons or if Hilog terms have considerable advantages in comparison to the current ISO standard.
Within XSB, Hilog terms are very strongly connected to the module system which is unique to XSB. XSB has a functor based module system. That is, within the same scope length(X) might belong to one module, whereas length(L, N) might belong to another. As a consequence, call(length(L), N) might refer to one module and call(length(L, N)) to another:
[Patch date: 2013/02/20 06:17:59]
| ?- use_module(basics,length/2).
yes
| ?- length(Xs,2).
Xs = [_h201,_h203]
yes
| ?- call(length(Xs),2).
Xs = [_h217,_h219]
yes
| ?- use_module(inex,length/1).
yes
| ?- length(Xs,2).
Xs = [_h201,_h203]
yes
| ?- call(length(Xs),2).
++Error[XSB/Runtime/P]: [Existence (No module inex exists)] in arg 1 of predicate load
| ?- call(call(length,Xs),2).
Xs = [_h228,_h230];
It might be that in such a context there are differences between call/N and Hilog terms. I have, however, so far not found one.
Historically, Hilog terms have been introduced 1987-1989. At that point in time, call/N already existed as built-ins in NU and as library(call) in Quintus Prolog with only cursory documentation. It has been proposed 1984 by Richard O'Keefe. On the other hand, call/N was clearly unknown to the authors of Hilog, as is exemplified on p.1101 of Weidong Chen, Michael Kifer, David Scott Warren: HiLog: A First-Order
Semantics for Higher-Order Logic Programming Constructs. NACLP
1989. 1090-1114. MIT-Press.
... Generic transitive closure can also be defined in Prolog:
closure(R, X, Y) :- C =.. [R, X, Y], call(C).
closure(R, X, Y) :- C =.. [R, X, Z], call(C), closure(R, Z, Y).
However, this is obviously inelegant compared to HiLog (see Section 2.1), since this involves both constructing a term out of a list and reflecting this term into an atomic formula using "call". The point of this example is that the lack of theoretical foundations for higher-order constructs in Prolog resulted in an obscure syntax, which partially explains why Prolog programs involving such constructs are notoriously hard to understand.
Now, this can be done with call/N like so:
closure(R, X, Y) :- call(R, X, Y).
closure(R, X, Y) :- call(R, X, Z), closure(R, Z, Y).
Which is even more general than the (=..)/2-version because R is no longer restricted to being an atom. As an aside, I'd rather prefer to write:
closure(R_2, X0,X) :- call(R_2, X0,X1), closure0(R_2, X1,X).
closure0(_R_2, X,X).
closure0(R_2, X0,X) :- call(R_2, X0,X1), closure0(R_2, X1,X).
HiLog allows goals such as
foo(X(a, Y(b))).
and ISO Prolog does not. In ISO Prolog, you'd have to write
foo(T), T=..[X, a, R], R=..[Y, b].
which is less convenient and might be slower.
How to implement rule1 that succeeds iff rule2 returns two or more results?
rule1(X) :-
rule2(X, _).
How can I count the results, and then set a minimum for when to succeed?
How can I count the results, and then set a minimum for when it's true?
It is not clear what you mean by results. So I will make some guesses. A result might be:
A solution. For example, the goal member(X,[1,2,1]) has two solutions. Not three. In this case consider using either setof/3 or a similar predicate. In any case, you should first understand setof/3 before addressing the problem you have.
An answer. The goal member(X,[1,2,1]) has three answers. The goal member(X,[Y,Z]) has two answers, but infinitely many solutions.
So if you want to ensure that there are at least a certain number of answers, define:
at_least(Goal, N) :-
\+ \+ call_nth(Goal, N).
with call_nth/2 defined in another SO-answer.
Note that the other SO-answers are not correct: They either do not terminate or produce unexpected instantiations.
you can use library(aggregate) to count solutions
:- use_module(library(aggregate)).
% it's useful to declare this for modularization
:- meta_predicate at_least(0, +).
at_least(Predicate, Minimum) :-
aggregate_all(count, Predicate, N),
N >= Minimum.
example:
?- at_least(member(_,[1,2,3]),3).
true.
?- at_least(member(_,[1,2,3]),4).
false.
edit here is a more efficient way, using SWI-Prolog facilities for global variables
at_least(P, N) :-
nb_setval(at_least, 0),
P,
nb_getval(at_least, C),
S is C + 1,
( S >= N, ! ; nb_setval(at_least, S), fail ).
with this definition, P is called just N times. (I introduce a service predicate m/2 that displays what it returns)
m(X, L) :- member(X, L), writeln(x:X).
?- at_least(m(X,[1,2,3]),2).
x:1
x:2
X = 2.
edit accounting for #false comment, I tried
?- call_nth(m(X,[1,2,3]),2).
x:1
x:2
X = 2 ;
x:3
false.
with call_nth from here.
From the practical point of view, I think nb_setval (vs nb_setarg) suffers the usual tradeoffs between global and local variables. I.e. for some task could be handly to know what's the limit hit to accept the condition. If this is not required, nb_setarg it's more clean.
Bottom line: the better way to do would clearly be using call_nth, with the 'trick' of double negation solving the undue variable instantiation.
How can I express next 3 sentences in Prolog?
All summers are warm. If it not summer, then it is winter. Now it is winter.
Nice question.
As #larsman (well, #FredFoo now, I think) rightly said, can be a large thema. And his answer is very good indeed.
As your question could be driven by necessity of a custom language (one of main Prolog' uses), here I propose the syntax sugar for a dummy DSL (what that's means it's totally empty now...)
:- op(500, fx, all).
:- op(500, fx, now).
:- op(600, xfx, are).
:- op(700, fx, if).
:- op(399, fx, it).
:- op(398, fx, is).
:- op(397, fx, not).
:- op(701, xfx, then).
all summers are warm.
if it is not summer then it is winter.
now it is winter.
SWI-Prolog is kind enough to make red those op that get stored, i.e. can be queried easily. These are the higher precedence words declared: i.e. are,then,now.
?- now X.
X = it is winter.
How to represent this depends on what inferences you want to make. One of the simplest ways is
warm :- summer.
winter.
The "if not summer then winter" rule does not actually allow you to make any useful inferences, so you could just as well skip it. If you were to include it, it might be something like
winter :- \+ summer.
but since negation in Prolog is negation as failure, this might not do what you think it does if you expect the semantics of vanilla propositional logic.
winter(now).
warm(X) :- summer(X).
summer(X) :- \+ winter(X).
winter(X) :- \+ summer(X).
Would be one of the ways to do this.
In action:
6 ?- summer(now).
false.
7 ?- summer(tomorrow).
ERROR: Out of local stack
8 ?- warm(now).
false.
Here a solution without using negation, instead the universe of seasons is
specified.
season(summer).
season(winter).
now(winter).
warm(S) :-
season(S),
S = summer.
Some example queries:
?- now(S).
S = winter ;
false.
?- now(S), warm(S).
false.
?- warm(S).
S = summer ;
false.