clauses not being together in the source file warning - prolog

So basically i have this afirmations and rules and somehow the compiler is saying that the clauses are not in the source file and i dont get why, like the program is well written i think?
Program:
forne(f001,zé_dos_parafusos,fabricante,carregado).
forne(f002,branquinho,fabricante,lisboa).
forne(f003,lar_ideal,fabricante,lisboa).
tipo_prod(p001,parafuso).
tipo_prod(p002,broca).
tipo_prod(p003,lavatório).
tipo_prod(p004,sabonete).
tipo_prod(p005,detergente).
og_prod(f001,p001,30000).
og_prod(f001,p002,500).
og_prod(f002,p003,25).
og_prod(f002,p004,50000).
og_prod(f002,p005,50000).
og_prod(f003,p001,1000).
og_prod(f003,p002,50).
og_prod(f003,p003,5).
og_prod(f003,p005,500).
tipo_prod(X, _) :- og_prod(X, _, _).
og_prod(X, Y, _) :- tipo_prod(Y, _), forne(X, _, _, _).
Warnings:
Clauses of tipo_prod/2 are not together in the source-file
Clauses of og_prod/3 are not together in the source-file
Earlier definition at ex1 cap7.pl:11
Current predicate: tipo_prod/2
Use :- discontiguous og_prod/3. to suppress this message
If someone could explain to me whats wrong in this program i would appreciate it a lot.

Prolog doesn't care whether the clauses are facts or rules -- they're all just clauses (facts simply don't have a ":- ..." part; but you can also think of them as having :- true).
You have rules for tipo_prod/2 and og_prod/3 separate from the facts for those predicates. So, you're getting a warning, as that's often the indication of a typo.
BTW, your code probably won't do what you think it's doing. My guess is that you want to use different names for the rules tipo_prod/2 and og_prod/3 that's different from the names for the facts.

Related

Prolog solve Sudoku

I'm rather new at Prolog and found this example on swi-prolog.org to solve a sudoku. But I can't run it. I looked up same_length and there is only same_length/2 not same_length/1. Also all_distinct/2 and not all_distinct/0. http://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku
Here are my errors:
ERROR: d:/.../prolog/sudoku.pl:5:10: Syntax error: Operator expected
% d:/.../prolog/sudoku compiled 0.00 sec, 0 clauses
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning:
Warning: all_distinct/1, which is referenced by
Warning: d:/.../prolog/sudoku.pl:16:8: 2-nd clause of blocks/3
And here is the code of SWI-Prolog example:
use_module(library(clpfd)).
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs),
Vs in 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
I hope you can help me to find my mistake.
As far as I can tell, it now already works for you. However, I would still like to take the opportunity to show a few hints that may be useful for you:
Facts vs. directives
First, why doesn't the code that you post in your answer work?
The Prolog message already gives a pretty good indication:
Warning: The predicates below are not defined. ...
...
all_distinct/1, which is referenced by
This shows that you are in fact using all_distinct/1 (not all_distinct/2!) in your code somewhere, and it is not available.
Why? Because all_distinct/1 is available in library(clpfd), and you are not importing that library!
This is a pretty common error among beginners. Take a look at the following line in your program:
use_module(library(clpfd)).
Contrary to what you may believe, this does not import the library! Why? Because, as it stands, this is simply a Prolog fact of the form use_module/1, similar to the fact:
name(bob).
which, likewise, does not name bob, but simply states that name(bob) holds.
What you want instead is to use a directive to import a library.
Directives are terms of the form :-(D), which can also be written as :- D since (:-)/1 is a prefix operator.
Hence, what you meant to write is:
:- use_module(library(clpfd)).
This is a term of the form :-(T), and will be processed as a directive when the file is loaded.
Convenience definitions
Personally, I often write small Prolog programs, and most of them use CLP(FD) constraints. At some point, I got tired of adding :- use_module(library(clpfd)). to all my programs, so I added the following definition to my ~/.emacs:
(global-set-key "\C-cl" (lambda ()
(interactive)
(insert ":- use_module(library()).")
(forward-char -3)))
When you now press C-c l, the following snippet is inserted at point:
:- use_module(library()).
and point is placed within the () so that you only have to type the actual name of the library instead of the whose :- use_module...etc. directive.
So, to use library(clpfd), I would simply type:
C-c l clpfd
After a while, I got tired of that as well, and simply added :- use_module(library(clpfd)). to my ~/.swiplrc configuration file, because almost all programs I write perform integer arithmetic, and so it makes sense for me to make CLP(FD) constraints available in all Prolog programs I write. This is also already the case in systems like GNU Prolog and B-Prolog, for example.
However, I still have kept the .emacs definition, because sometimes I need to import other libraries, and I find typing the whole :- use_module... directive too cumbersome and error-prone.

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.

Pattern-matching: query returns 'no' even when base case provided

I have a simple Prolog-program that I need some help debugging.
The point is to extend the program by pattern-matching to create a proof checker for propositional logic. The problem I have is that I get no when I expect yes and my 'fix' (providing a base case for valid_proof_aux) still gives me two solutions and I don't know why.
Not sure how to go about debugging Prolog yet, sorry.
%call:
valid_proof([p],p,[[1, p, premise]])
%src:
reverse_it([],Z,Z).
reverse_it([H|T],Z,Acc) :- reverse_it(T,Z,[H|Acc]).
valid_proof(Prems,Goal,Proof):-
last(Proof, [_, Goal, _]),
reverse_it(Proof, RevP, []),
valid_proof_aux(Prems, RevP) .
valid_proof_aux(Prems,
[[_,Prop,premise] | T]):-
memberchk(Prop,Prems),
valid_proof_aux(Prems,T).
%my 'fix'
valid_proof_aux(_, []) :- true .
You don't really show how to run the program and what exactly you get (you should edit your question with and add this), so this answer is a bit of a guess, but anyway:
You need the base case either way (as you observe yourself), valid_proof_aux/2 would fail when the list becomes empty [] and does not match [[...]|T] anymore.
?- [] = [_|_]. % try to unify an empty list with a non-empty list
false.
What you need to do to get rid of the choice point is to put the list argument as the first argument.
valid_proof_aux([], _).
valid_proof_aux([[_,Prop,premise]|T], Prems) :-
memberchk(Prop, Prems),
valid_proof_aux(T, Prems).
Note that you don't need the :- true., this is implicit. Also, avoid leaving any blanks on the two sides of the | in [Head|Tail].

How can I ask questions on a family tree in Prolog?

I'm currently trying to learn how to use Prolog. I have SWI-Prolog version 6.2.6 installed.
It seems to run:
?- 3<4.
true.
?- 4<3.
false.
As a first example, I was trying to implement the possibility of asking questions about a family tree. So I've started with this, stored in family.pl:
father(bob,danna).
father(bob,fabienne).
father(bob,gabrielle).
mother(alice,danna).
mother(alice,fabienne).
mother(alice,gabrielle).
father(charlie,ida).
father(charlie,jake).
mother(danna,ida).
mother(danna,jake).
father(edgar,kahlan).
mother(fabienne,kahlan).
father(hager,luci).
mother(gabrielle,luci).
male(X) :- father(X,_).
female(X) :- mother(X,_).
But when I try to load this with consult(family). I get:
?- consult(family).
Warning: /home/moose/Desktop/family.pl:7:
Clauses of father/2 are not together in the source-file
Warning: /home/moose/Desktop/family.pl:9:
Clauses of mother/2 are not together in the source-file
Warning: /home/moose/Desktop/family.pl:11:
Clauses of father/2 are not together in the source-file
Warning: /home/moose/Desktop/family.pl:12:
Clauses of mother/2 are not together in the source-file
Warning: /home/moose/Desktop/family.pl:13:
Clauses of father/2 are not together in the source-file
Warning: /home/moose/Desktop/family.pl:14:
Clauses of mother/2 are not together in the source-file
% family compiled 0.00 sec, 17 clauses
true.
I don't understand what is the problem here. I've found some results that mentioned that - cannot be used in identifiers, but I didn't use - in an identifier.
Question 1: What causes the Warning from above? How can I fix it?
But there are only warnings, so I've continued with
?- female(fabienne).
true.
?- male(fabienne).
false.
Ok, this seems to work as expected.
Then I've added
male(jake).
female(ida).
female(kahlan).
female(luci).
brother(X,Y):-
male(X),
(mother(Z,X)=mother(Z,Y);father(Z,X)=father(Z,Y)).
and tried:
?- brother(jake,ida).
false.
Why isn't this true?
Question 2: What is the problem with my brother rule?
Your first question is answered here.
As for the second, you're thinking in terms of functions instead of relations.
mother(Z,X) = mother(Z,Y)
is the same as saying X = Y because it compares two terms, without interpreting them. If you want Z to be the mother of both X and Y, you need a conjunction:
mother(Z, X), mother(Z, Y)
the warrning can be fixed if you move all the father and mother declarations together (do not mix them)
In brother definition you use = and you should use a logical AND so use ,(comma)
also you need to tell prolog that jake is a male because he can't figure it out from those rules
I split the brother definition in 2 because is more clear and this is like a logical OR (the first definition is valid or the second one)
father(bob,danna).
father(bob,fabienne).
father(bob,gabrielle).
father(charlie,ida).
father(charlie,jake).
father(edgar,kahlan).
father(hager,luci).
mother(alice,danna).
mother(alice,fabienne).
mother(alice,gabrielle).
mother(danna,ida).
mother(danna,jake).
mother(fabienne,kahlan).
mother(gabrielle,luci).
male(jake).
male(X) :- father(X,_).
female(X) :- mother(X,_).
brother(X,Y):-
male(X),
mother(Z,X),mother(Z,Y).
brother(X,Y):-
male(X),
father(Z,X),father(Z,Y).
For test run
brother(X,Y).
for more results you need to add who is male opr female for those childs like I did for jake

State facts with unbound variables

How would I state things "in general" about the facts? Suppose I need to state "everyone likes the person who likes him/her", and I have a list of people who may or may not like each other.
This is what I tried so far, but it's sure not the way to do it:
likes(dana, cody).
hates(bess, dana).
hates(cody, abby).
likes(first(Girl, OtherGirl), first(OtherGirl, Girl)).
hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).
because this won't even compile.
everybody([dana, cody, bess, abby]).
likes_reflexive(dana, cody).
hates(bess, dana).
hates(cody, abby).
likes_reflexive(X, Y):- likes(X, Y), likes(Y, X).
hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).
%% likes_reflikes_reflexive(X, Y):- likes(X, Y), likes(Y, X).
%% user:6: warning: discontiguous predicate likes_reflexive/2 - clause ignored
%% hates(Girhates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).
%% user:8: warning: discontiguous predicate hates/2 - clause ignored
Unfortunately I don't understand what the warnings say. Hope it makes my intention more clear. I.e. by stating one fact, I also want to state the other related fact.
If you want to change your knowledge base dynamically, you can use asserts. If you want to modify existing predicate, you should define it as dynamic, e.g. :- dynamic(likes/2).. If predicate is undefined, you can omit it.
add_mutual_likes(X, Y) :- asserta(likes(X, Y)), asserta(likes(Y, X)).
:- initialization(add_mutual_likes(dana, cody)).
initialization/1 calls add_mutual_likes(data, cody) goal when file is loaded. add_mutual_likes/2 adds two facts to a database. asserta/1 converts it's argument into a clause and adds it to a database.
| ?- [my].
yes
| ?- listing(likes/2).
% file: user_input
likes(cody, dana).
likes(dana, cody).
yes
| ?- likes(cody, dana).
yes
| ?- likes(dana, cody).
yes
| ?- add_mutual_likes(oleg, semen).
yes
| ?- listing(likes/2).
% file: user_input
likes(semen, oleg).
likes(oleg, semen).
likes(cody, data).
likes(data, cody).
yes
I use gprolog.
Let's start with the warnings. They are merely "style" suggestions. They are telling you that all the definitions for likes and hates should be together. Trust me if you have a big Prolog program it becomes a nightmare to go around tour code to get the full definition of your predicate. It would be like writing half a function in C++ and finish it in another file.
Now, you want to say "everyone likes the person who likes him/her". I'm not sure why you are using that function "first" in the code. This would be sufficient:
likes(dana, cody).
likes(Girl, OtherGirl) :- likes(OtherGirl, Girl).
The second clause reads "Girl likes OtherGirl if OtherGirl likes Girl. This won't work.
If you ask your program "is it true that cody likes dana"
? likes(cody, dana)
Prolog will reason like this:
The answer is yes if dana likes cody (using the second clause).
Yes! Because dana likes cody (using the first clause).
This is not enough to make it a correct program. Since we are in Prolog you can say: "give me another solution" (usually by entering ";" in the prompt).
Prolog will think "I only used the first clause, I haven't tried the second".
The answer is Yes also if dana likes cody (using the second clause).
The answer is Yes according to the second clause, if cody likes dana.
But that's our initial query. Prolog will give you the same answer again and again, looping forever if you asked for all the solutions.
You can do two things here. The first is telling Prolog that one solution is enough. You do this adding a "!" (that basically says, clear all the open branches left to explore).
likes(dana, cody) :- !.
likes(Girl, OtherGirl) :- likes(OtherGirl, Girl).
Another alternative is to "stratify the program".
direct_likes(dana, cody).
likes(Girl, OtherGirl) :- direct_likes(OtherGirl, Girl), !.
likes(Girl, OtherGirl) :- direct_likes(Girl, OtherGirl).
What you want is a fact where Prolog does not care about the order of arguments. Alas, something like that does not exist. What you can do instead is define facts where the implied meaning is that it is valid for all argument orders (like_each in the example below). But of course, you cannot use these facts in that way. Instead, you define the actual predicate to try (hence the or ;) all possible argument orders.
Thus, the solution is:
%% bi-directional like
like_each(dana, cody).
likes(A, B) :- like_each(A, B); like_each(B, A).
%% optional: one-directional like
% likes(cody, sarah).
Also, be careful with
hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).
If both variables are unbound (e.g., ?- hates(A,B)), it will always fail. This happens because Prolog first tries to find a match for likes, which always succeeds for two variables, and then negates the result. Thus, you cannot use hates to find all pairs who don't like each other.

Resources