singleton variables in prolog - prolog

I was testing my new version of SWI prolog and keep coming across the error :singleton variable.
Example:
member(X,[X|T]).
member(X,[X|T]) :- member(X,T).
finds the member of a list such as :
member(yolands,[yolanda,tim])
X = yes
but instead I get a singleton variables error for X and T
if I do the following:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
It works but looks ugly!
Can anyone explain why single variables ar enot allowed and if this ANSI standard?

Singleton variables are useless in Prolog, and are easily introduced by editing typos.
The warning is welcome to me, as it allows to easily spot such frequent cause of error.
Being a warning, you can run code containing singletons, but any value these eventually will assume will be lost.
I don't think that ISO standard (never heard about ANSI) forbids such variables.
You could rewrite your example in this way
member(X, [Y|T]) :- X = Y ; member(X, T).
and then forget about the singleton.

You have a bug here:
member(X,[X|T]) :- member(X,T).
What you're actually saying (as opposed to what you think you're saying) is that member/2 holds if X is at the head of the list and present in the tail of the list. This predicate will only ever be true for the first N copies of the same thing at the beginning of a list, so it's a very strange thing to say!
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
Now, you could correct the bug and still have a singleton warning by doing something like this:
member(X, [Y|T]) :- member(X, T).
But this is neither as good as the conventional definition with two heads or #CapelliC's version (+1) with an explicit OR. I think you should wait until you understand Prolog a little better before putting much stock in your sense of Prolog code aesthetics. If you stick with it for a while you'll come to appreciate this warning as well as the use of anonymous variables.
What makes singleton variables useless in Prolog is that they're named but nothing is known about them and they have no effect on the rest of the computation. The underscore highlights that absolutely anything could go in there without affecting the meaning. What makes
member(X, [X|T]).
true is that the X is position 1 is the same as the X at the head of the list in position 2. Lists must either be empty or have a head and a tail, but what's in the tail is not relevant here, what matters is that X is also the head. The T could be the rest of the list, or it could be an improper list, or it could be a breadbox or lightning or the smell of the air on a spring day. It has no bearing on the truth of member(X, [X|T]).
The singleton warning tells you "you've reserved a name for something here, but you never call anything by that name." The first thing I do when I get this message and it isn't an obvious typo is replace the name with _ and see if my code still makes sense. If it doesn't, I have a logic error. If it does, it was probably unnecessary.

You can read about it on the official page of SWI-Prolog FAQ
The most common cases this warning appears are:
Spelling mistakes in variables
Forget to use/bind a variable
SWI suggest some ways to ignore it:
Use anonymous variable named _ for this purpose.
Use your variable starting with _ (like _T, _X), to avoid warning and document what you ignore.
If you are aware of what you are doing, you can use :- style_check(-singleton). and all warnings should go away.

Related

Representing truth regarding beliefs in prolog

How to make this (or something similar) work in Prolog:
belief(john,red(apple)).
belief(peter,red(apple)).
X :- belief(john,X), belief(peter,X).
And get true. for the following query (while consulting above):-
?- red(apple).
First, it's useful to define a little helper to capture when all (relevant) persons believe something:
all_believe(Belief) :-
belief(john, Belief),
belief(peter, Belief).
Then you can define, for example:
red(Object) :-
all_believe(red(Object)).
green(Object) :-
all_believe(green(Object)).
And with your given set of beliefs you get:
?- red(apple).
true.
?- green(apple).
false.
This works. It requires you to define similar rules for any term that you want to use as a belief.
You can make this a bit shorter with macro definitions using term_expansion:
term_expansion(declare_belief(Belief),
Belief :- all_believe(Belief)).
This means that every top-level definition in your source code of the form declare_belief(Belief) should be treated as if you had written Belief :- all_believe(Belief) instead (with the variable Belief substituted appropriately).
So now you can just write this:
declare_belief(red(_)).
declare_belief(green(_)).
and it will be treated exactly like the longer definitions for red(Object) and red(Object) above. You will still have to write this kind of declaration for any term that you want to use as a possible belief.
Prolog does not allow the head of a rule to be just a variable. The head must be a nonvar term, whose functor (i.e., name and arity) identifies the predicate being defined. So, a possible solution would be something like this:
true_belief(X) :-
belief(john, X),
belief(peter, X).
belief(john, red(apple)).
belief(peter, red(apple)).
Examples:
?- true_belief(red(apple)).
true.
?- true_belief(X).
X = red(apple).

Prolog singleton variables in rule head causes program to output booleans for all queries

I have this prolog program.
red(rose).
red(anthurium).
white(rose).
white(gardenia).
white(jasmine).
like(Y,X) :-
red(X),!,
fail
;
white(X).
And below is how it responds to different queries.
?- like(rose,gardenia).
true.
?- like(rose,P).
false.
?- like(Val,anthurium).
false.
?- like(rose,X).
false
The problem I now have is this:
When querying with a variable within the query (Eg: ?- like(rose,X).), Prolog usually responds by returning a value, (something like X=some_val). Why I don't get any value for those variables, but either true or false?
All helpful answers are highly appreciated. Thanks in advance.
Think about what Prolog is doing here:
like(rose,P) succeeds if red(P), so it grabs a possible substitution for P, namely rose or anthurium. Then it traverses the cut and then it fails. But "failing" means that the proof search down that path didn't bring any solution, there are no successful bindings to report (the only fail to get information out of a failing branch is to side-effect to a log file and read check it later). In fact, all bindings will be undone on backtracking. The second branch is white(X), but rose is not white, so we fail here, too.
You can also write:
like(_,X) :- \+ red(X).
like(_,X) :- white(X).
which is a bit more readable. One notices that when calling like(_,X), the goal enclosed by the negation-as-failure operator \+ is nonground. This is bad, and causes a floundering query (in other words, don't do that). I have written this little page on "floundering".

How to get rid of Singleton variables errors?

I'm supposed to implement a little prolog program out of the Monty Python movie where the people are arguing whether a woman is a witch. Based on what the say, witches are burned, but wood is also burned, and wood floats, but ducks also float, so, if someone weighs the same as a duck, she's made of wood, therefore, she's a witch.
Based on that, I've come up with this:
witch(X) :- burns(X), female(X).
burns(X) :- wooden(X).
wooden(X) :- floats(X).
floats(X) :- sameWeight(duck, X).
female(X).
sameweight(duck, X).
But when I want to check if X is a witch, by trying witch(X). It actually prints "true", confiming the woman is a witch, but I also get a Singleton variables: [X] error message. So clearly I have a bug somewhere and I would like to fix it.
Those are warnings. It specifies that you use a variable once in clause. This is the case for X in:
female(X).
sameweight(duck, X).
Now this is rather "odd". Variables are typically used for passing values from head to body, or between two predicate calls in the body. But here you only use X once.
In Prolog one uses an underscore (_) if you "do not care" about the value. The underscore is an "anonymous variable": if you use two underscores in the same clause, those are two different variables.
So you can fix it like:
female(_).
sameweight(duck, _).
Note that now you have written that everything is a female, and that everything has the same weight as a duck.

turning off Redefined static procedure in prolog

anyone of you could tell me how to turn off "Redefined static procedure" warnings?
I red online documentation of swi-prolog and i found this predicate no_style_check(ultimate) that in principle should turn off these warnings, but when i execute this predicate
main:-
no_style_check(singleton),
no_style_check(discontiguous),
no_style_check(multiple),
require,
test_all.
i received this error
ERROR: Domain error: style_name' expected, foundmultiple'
Anyone knows an alternative way to do this or could tell me why i receive this error ?
Thanks in advance!
Prolog is a pretty loosey-goosey language, so by default it warns you when you do certain things that are not wrong per se, but tend to be a good indication that you've made a typo.
Now, suppose you write something like this:
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Then from the prompt you write this:
?- asserta(myfoo(7,9)).
ERROR: asserta/1: No permission to modify static procedure `myfoo/2'
ERROR: Defined at user://1:9
What's happening here is that you haven't told Prolog that it's OK for you to modify myfoo/2 so it is stopping you. The trick is to add a declaration:
:- dynamic myfoo/2.
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Now it will let you modify it just fine:
?- asserta(myfoo(7,9)).
true.
Now suppose you have three modules and they each advertise themselves by defining some predicate. For instance, you might have three files.
foo.pl
can_haz(foo).
bar.pl
can_haz(bar).
When you load them both you're going to get a warning:
?- [foo].
true.
?- [bar].
Warning: /home/fox/HOME/Projects/bar.pl:1:
Redefined static procedure can_haz/1
Previously defined at /home/fox/HOME/Projects/foo.pl:1
true.
And notice this:
?- can_haz(X).
X = bar.
The foo solution is gone.
The trick here is to tell Prolog that clauses of this predicate may be defined in different files. The trick is multifile:
foo.pl
:- multifile can_haz/1.
can_haz(foo).
bar.pl
:- multifile can_haz/1.
can_haz(bar).
In use:
?- [foo].
true.
?- [bar].
true.
?- can_haz(X).
X = foo ;
X = bar.
:- discontiguous does the same thing as multifile except in a single file; so you define clauses of the same predicate in different places in one file.
Again, singleton warnings are a completely different beast and I would absolutely not modify the warnings on them, they're too useful in debugging.

Prolog Relational Tracking without Lists

I am trying to get a predicate to relate from 1 fact to another fact and to keep going until a specified stopping point.
For example,
let's say I am doing a logistics record where I want to know who got a package from who, and where did they get it from until the end.
Prolog Code
mailRoom(m).
gotFrom(annie,brock).
gotFrom(brock,cara).
gotFrom(cara,daniel).
gotFrom(daniel,m).
gotFrom(X,Y) :- gotFrom(Y,_).
So what I am trying to do with the predicate gotFrom is for it to recursively go down the list from what ever point you start (ex: gotFrom(brock,Who)) and get to the end which is specified by m, which is the mail room.
Unfortunately when I run this predicate, it reads out,
Who = annie.
Who = brock.
Who = cara.
etc.etc....
I tried stepping through the whole thing but Im not sure where it goes from brock to annie, to cara and all the way down till it cycles through trues for infinity. I have a feeling that it has something to do with the wildcard in the function (_), but Im not sure how else I could express that part of the function in order for the predicate to search for the next fact in the program instead of skipping to the end.
I tried using a backcut (!) in my program but it gives me the same error.
Any help is greatly appreciated. I don't want code I just want to know what I am doing wrong so I can learn how to do it right.
Thanks.
I'm afraid this rule is meaningless:
gotFrom(X,Y) :- gotFrom(Y,_).
There is nothing here to constrain X or Y to any particular values. Also, the presence of singleton variable X and the anonymous variable _ means that basically anything will work. Try it:
?- gotFrom([1,2,3], dogbert).
true ;
true ;
What I think you're trying to establish here is some kind of transitive property. In that case, what you want is probably more like this:
gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).
This produces an interesting result:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack
The reason for the problem may not be immediately obvious. It's that there is unchecked recursion happening twice in that rule. We recursively unify gotFrom/2 and then we recursively unify it again. It would be better to break this into two predicates so that one of them can be used non-recursively.
got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).
gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).
This gives us the desired behavior:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.
Notice this one is resilient to my attack of meaningless data:
?- gotFrom([1,2,3], dogbert).
false.
Some general advice:
Never ignore singleton variable warnings. They are almost always a bug.
Never introduce a cut when you don't understand what's going on. The cut should be used only where you understand the behavior first and you understand how the cut will affect it. Ideally, you should try to restrict yourself to green cuts—cuts that only affect performance and have no observable effects. If you don't understand what Prolog is up to, adding a red cut is just going to make your problems more complex.

Resources