"NOT EXISTS" in swi-prolog - prolog

I'm stuck on a simple problem in prolog.
Let's consider the program
worker(bill).
worker(smitt).
worker(fred).
worker(dany).
worker(john).
car(bmw).
car(mazda).
car(audi).
owner(fred,mazda).
owner(dany,bmw).
owner(john,audi).
I need to add one more predicate no_car(X),that will be true if the worker X has no cars,i.e,if we input a query
?:- no_car(X).
the prolog should answer
X=smitt,
X=bill,
yes
What i have done is
hascar(X):-owner(X,_).
nocar(X):- worker(X),not hascar(X).
But this approach does not work because anonimous variables are avaliable only for queries.
So,i'm really stuck on this.
I know there are "NOT EXISTS" words in SQL which allow to express this logic in a query,but is there something similar to them in prolog?

The following works for me and provides the expected result:
no_car(W):-
worker(W),
\+ owner(W, _).
Now this is close to what you have. For one thing, you can of course use _ in predicates; it is not restricted to queries. I usually use \* for negation, and not gives me a syntax error here!?
EDIT:
Ah! In my, albeit dated, version of Prolog you have to use not(hascar(X)) to make it work, so not/1 needs to be used as a term, not an operator. But the manual also says not is deprecated in favor of \+.

Related

How to get all the clauses defined/loaded from a file in Prolog

I am using SWI Prolog and am surprised to find no obvious way to do this in Prolog. What I'm after is something similar to clause/2 but allows uninstantiated first argument (and is specific to the clauses in a given file, ie I don't want the entire Prolog library!). Here is what I wrote to find all the clauses
clauseX(H,B) :-
current_predicate(P/Arity),
functor(H,P,Arity),
absolute_file_name('filname.pl', AbsFileName),
predicate_property(H, file(AbsFileName)),
clause(H,B).
Is there a more concise way of doing this?
OK, so I've been able to shorten it somewhat, the first two literals aren't required, this will return clauses in the file filename.pl
clauseX(H,B) :-
absolute_file_name('filname.pl', AbsFileName),
predicate_property(H, file(AbsFileName)),
clause(H,B).
However I am still concerned about the efficiency of this and whether it has to consult the file every time clauseX is called

Visual Prolog error c502: The expression does not produce a value

I am trying to translate a simple Turbo Prolog problem to Visual Prolog 7.1
The original Turbo Prolog code is the following.
DOMAINS
s=string sl=s* sll=sl*
PREDICATES
select(sl,s,sl)
solve(sll)
CLAUSES
select([A|B],A,B).
select([A|B],C,[A|D]):- select(B,C,D).
solve([["Anna",A,A],["Kate",Vp,Vt], ["Natasha",Np,"green"]]):-
select(["white","green","blue"],A,ColPl),
select(["white","blue"],A,[Vt]), Vt<>"white",
select(ColPl,Vp,[Np]), Vp<>"white", Np<>"green".
And its resulting list is outputted with solve(Out) with provides a correct result to the Turbo Prolog console.
When trying to translate this to Visual Prolog, I get error c502 in line 33.
implement main
open core
constants
className = "main".
classVersion = "".
domains
s=string.
sl=s*.
sll=sl*.
%
class predicates
select:(sl,s,sl) nondeterm anyflow.
solve:(sll) nondeterm anyflow.
%
clauses
%
select([A|B],A,B).
select([A|B],C,[A|D]):- select(B,C,D).
%
solve([["Anna",A,A],["Kate",Vp,Vt],["Natasha",Np,"green"]]):-
select(["white","green","blue"],A,ColPl),
select(["white","blue"],A,[Vt]), Vt<>"white",
select(ColPl,Vp,[Np]), Vp<>"white", Np<>"green".
clauses
classInfo(className, classVersion).
clauses
run():-
console::init(),
%ERROR AFTER THIS LINE
stdIO::writef("%", solve(Out)),fail().
end implement main
goal
mainExe::run(main::run).
What I get from this error is that solve(Out) does not give anything to print. What I do not know is how to change the code to produce something to print.
I am a beginner in Prolog and I cannot figure out how to fix this problem and Google is not much of a help either, this seems to be very obscure problem.
Thank you!
I'm not familiar with Visual Prolog, but could you rewrite the offending line as:
solve(Out), stdIO::writef("%", Out),fail().
and try again?
Remember that predicates are not functions like in other programming languages; they do not have a return value.
EDIT to answer comment: a procedure predicate should succeed exactly one time. Here, main is calling your solve function which my fail or succeeds several time. To ensure that, you can try to wrap the call to solve into another predicate:
wrap_solve(S) :- solve(S), !.
wrap_solve([]).
The cut after the call to solve should ensure that you get only one solution if it succeeds.
If there's no solution (i.e., the call to solve fails), then the second clause will give a default value (an empty list in that case).
In main, you should call wrap_solve instead of solve.

disjunctive syllogism in prolog

I am using swi-prolog. I want to model following statements in program.
"Either a or b is criminal. b is not criminal."
After modeling these statements. following query should work.
?-c(X).
X=a.
But,
when I wrote above statements in prolog:
c(a);c(b).
not(c(b)).
this code does not compile and shows error:
No permission to modify static procedure `(;)/2'
How to model above two statements in prolog?
afaik Prolog does not work this way. It tries to match your expression with all statements. So if you want to model "a is a criminal and b is not", then you can write
criminal(a).
not(criminal(b)).
but you can't say criminal(b) and in the next line not(criminal(b)), because this would lead to a contradiction.
the second line of my code ('not(criminal(b))') is actually redundant, because if Prolog doesn't find any matches of your term it will result in false, and backtrack for another solution. This means that you can simply omit all facts of not-criminals in this case.
you can then just ask Prolog which atoms it knows as criminals:
criminal(X).
and it will clearly tell you that
X=a.
whereas b is not part of the solution.

Circular Prolog

I have the following prolog code:
equiAngularTriangle(T) :-
equiLateralTriangle(T).
equiLateralTriangle(T) :-
equiAngularTriangle(T).
Is there a way to keep the interpreter from asking the same question twice? For instance, if I ask equiAngularTriangle(t), then it's going to ask equiLateralTriangle(t), then ask equiLateralTriangle(t), but it should know not to pursue that last one again, because the same question is on the "query stack".
Is there an option or some special syntax that lets Prolog behave the way I want it to?
If the prolog implementation supports tabling or you are using XSB then you could use it and get the desired behaviour.
You could also add a state argument:
%State = [Checked_for_equiAngular, Checked_for_equiLateral]
equiAngularTriangle(T, [_,false]) :-
equiLateralTriangle(T, [true,true]).
equiLateralTriangle(T, [false,_]) :-
equiAngularTriangle(T, [true,true]).
of course you will need to modify the rest of the clauses.
The last (and best imo) option is to rewrite your predicates. I guess that your code will be similar to this example:
ang(T):-
foo(T).
ang(T):-
lat(T).
lat(T):-
bar(T).
lat(T):-
ang(T).
so you could simply write:
ang(T):-
foo(T).
ang(T):-
bar(T).
lat(T):-
ang(T).
normally you will use some wrapper predicates if instead of foo(T) you had foo1(T),foo2(T) etc
Try XSB Prolog. It implements tabling which will short-circuit evaluation like in your case. You need to tell it which predicates should be tabled, though.

Can I use variables with assert/1?

What I have now checks that X(Y) is not an accepted fact in my small DB. Since X(Y) returns false it will attempt to assert it. (I realize this presents problems when X is a rule and not a fact)
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
assert(X(Y)).
For example, let's say that this fact is in the DB
mammal(dolphin).
I ask
ifNotAdd(mammal, elephant).
I want it to see that ? mammal(elephant). is false and then assert mammal(elephant).
Obviously the "assert(X(Y))." line is wrong but what do I replace it with? I'm trawling prolog documentation and forums for the answer but no luck so far. I'm also trying to write something that will do this on my own.
EDIT
I need to edit the DB in order to have a dynamic database the user can interact with. I'm building an argument machine and I need to allow the user to tell the system that they "know the fact for sure" so that the system can deal with knowledge outside of it's domain.
In the vein of http://en.wikipedia.org/wiki/Reason_maintenance
Cheers,
You can use the univ operator =../2 to construct the term before asserting it (note that the predicate in question has to be declared dynamic for it to work) :
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
Term =.. [X, Y],
assert(Term).
BTW if you want ifNotAdd/2 not to fail when it doesn't need to add the fact to the db, you should wrap that in a if structure, plus, not/1 is deprecated, (\+)/1 is preferred :
:- dynamic(mammal/1).
mammal(dolphin).
ifNotAdd(X, Y):-
( \+ call(X, Y)
-> Term =.. [X, Y],
assert(Term)
; true).
But I'm not sure what you're trying to do is right there. Quite often when a beginner in prolog wants to manipulate the database it's because a particular prolog mechanism isn't properly understood. Then again you might not be a beginner and my remark could be dumb, in which case, just forget it ! But if you do are a beginner, you may want to precise what you're trying to achieve here so that we can confirm that those manipulations are needed !

Resources