What is the difference \= and \+?
because
?- 15\=14.
?- \+ 15=14.<--- this gives an error while the above does not.
Why?Aren't they the same?
Edit: here's the error:
Compiling the file:
D:\Program Files\Strawberry Prolog Beta\Games\WarCraft.pro
Warning 4: The string \+ is not an operator. (line 1, before the first clause)
Error 16: Instead of the integer 15 what is expected here is something like an infix operator or a full stop. (line 1, before the first clause)
1 error, 1 warning.
Also I'm using Strawberry prolog I also tried it on SWI prolog still the same.
I think you are putting queries into Prolog source files. That is not where they should go:
predicate definitions go into Prolog source files
queries are typed into the interactive Prolog toplevel
Try running the SWI-Prolog program without an input file. You should get a window with some informational messages about the SWI-Prolog version and then a prompt ?-. That is the toplevel. Try typing your query there. All queries should go there.
I don't know about Strawberry Prolog, but I suspect it's the same there.
Related
I have the following lines in the program:
findFlight(DepartureP,ArrivalP,FinalResult) :-
findall([Flight,DepartureP,ArrivalP,DepartureTime,ArrivalTime],
flight(Flight,DepartureP,ArrivalP,DepartureTime,ArrivalTime),
Result),
bubblesort(Result, FinalResult).
but my compiler gives the following warning:
E;Test_Goal, pos: 969, 410 Variable expected
and the cursor is here when I click on the warning:
findall(|[
what is the problem? this program on swi prolog worked fine, but the visual prolog environment issues a warning..
I've never used Visual Prolog, but it looks like it needs a variable at the start of its findall, e.g.
findFlight(DepartureP,ArrivalP,FinalResult) :-
findall(F,
(flight(Flight,DepartureP,ArrivalP,DepartureTime,ArrivalTime),
F = [Flight,DepartureP,ArrivalP,DepartureTime,ArrivalTime]),
Result),
bubblesort(Result, FinalResult).
In SWI-Prolog, if I use assert and retract at the prompt, I get
?- assert(at(1)).
true.
?- retract(at(1)).
true.
However, if I put these statements into a program file called "test" as
assert(at(1)).
retract(at(1)).
and run SWI-Prolog as
> swipl
?- [test].
I get
ERROR: /....../test:2:
No permission to modify static procedure `retract/1'
true.
What does this mean and how should I deal with it?
Put statements within a predicate, e.g.:
:- dynamic at/1.
test_assert :-
assert(at(1)).
test_retract :-
retract(at(1)).
Load the program, and then run:
?- test_assert.
true.
?- at(X).
X = 1.
?- test_retract.
true.
?- at(X).
false.
The prompt and source code files are different environments with slightly different behaviours. It's like the difference between calling Python len(x) in the repl and writing function len(x): in Python source code - you would be overriding the builtin len() with your own one. Python lets you do that, SWI Prolog also does but not easily.
When you type them at the prompt, you call the existing predicate assert/1 and actually do insert the fact at(1). into the database. When you type retract/1 you actually do retract the fact at(1) from the database.
In a fresh prompt, try ?- listing(at). and get an error, then ?- assert(at(1)). then do the listing again and see the fact, then retract it and try the listing and see only the remains of the dynamic declaration and the fact is gone.
When you put them in a source code file, you would be trying to override the existing builtin predicates with your new ones. Your new ones say "assert/1 is a predicate which succeeds when its arugment unifies with at(1)" and "retract/1 is a predicate which succeeds when its arugment unifies with at(1)".
That is, they don't do any asserting or retracting or database changes.
In your test file, put this:
:- redefine_system_predicate(assert(_)).
:- redefine_system_predicate(retract(_)).
assert(at(1)) :- true.
retract(at(1)) :- true.
Then save and consult it:
?- [testing].
true.
?- listing(at). % <-- your code ran, but did not insert `at(1)`.
ERROR: procedure `at' does not exist (DWIM could not correct goal)
^ Exception: (13) setup_call_catcher_cleanup(system:true, prolog_listing:listing_(user:at, []), _19450, prolog_listing:close_sources) ? abort
% Execution Aborted
?- assert(P). % <-- it's now behaving
P = at(1). % <-- like any other predicate.
Typing "prolog" in terminal gets:
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?-
Typing:
| ?- member(2, [1,2,3]).
Gets:
true ?
Then pressing enter gets:
yes
Typing:
| ?- member(4, [1,2,3]).
gets:
no
When i write a file; test.pl consisting of this:
:- member(4, [1,2,3]), nl, halt.
And then write in the terminal:
| ?- [test2].
I get:
compiling /path/test.pl for byte code...
/path/test.pl:1: warning: unknown directive (',')/2 - maybe use initialization/1 - directive ignored
/path/test.pl compiled, 1 lines read - 139 bytes written, 11 ms
yes
Shouldnt the answer here be no? What am i doing wrong. Also, how would you do this in prolog:
if (testInPrologTerminal(member(4, [1,2,3])) { do this; }
I.e, i want to send queries to the prolog top level, and get an answer
When you type the query member(2, [1,2,3]), GNU Prolog prompts you for a possible additional solution (hence the true ? prompt) as only by backtracking (and looking to the last element in the list, 3) it could check for it. When you press enter, you're telling the top-level interpreter that you are satisfied with the current solution (the element 2 in the list second position). The second query, member(4, [1,2,3]), have no solutions so you get a no.
To execute a query when a file is loaded, the standard and portable way of doing it, is to use the standard initialization/1 directive. In this case, you would write:
:- initialization((member(4, [1,2,3]), nl, halt)).
Note the ()'s surrounding the query, otherwise you may get a warning about an unknown initialization/3 standard, built-in, control construct. If you have more complex queries to be executed when a file is loaded, then define a predicate that makes the queries a call this predicate from the initialization/1 directive. For example:
main :-
( member(4, [1,2,3]) ->
write('Query succeeded!'), nl
; write('Query failed!'), nl
).
:- initialization(main).
Writing arbitrary queries as directives in a source file is legacy practice and thus accepted by several Prolog implementations but using the initialization/1 directive is the more clean, standard, and portable alternative.
I have successfully connected PHP with Prolog and managed to query the desired knowledge base that resides in knowledge_base.pl file and managed to echo the results via php exec function.
I encountered a problem in echoing the true/false value that Prolog returns after each query execution (see previous question) so I came up with a solution that I have trouble implementing.
Let's assume I have a simple knowledge_base.pl file with these facts and rules:
girl(erin).
boy(john).
likes(erin, reading).
likes(john, reading).
hangs_out_with(erin, X) :-
likes(X, reading),
boy(X),
writeln('Someone s got a new friend!!').
Lets say that I want to see if erin is a girl and if so, write that it is true, or else write that it is false. I added this to my knowledge_base.pl file:
girl(erin) :-
girl(erin)
-> write('it is true')
; write('it is not true').
When I enter the query: ?- girl(erin). I get an out of local stack error. I searched the Web and found out that this is due to infinite recursion.
Can someone give me a hint in how to write
girl(X) :-
( girl(X)
-> write('it is true')
; write('it is not true')).
in Prolog? Thanks in advance.
As a new user I'm not allowed to post pictures.
SWI-Prolog's output:
1 ?-hangs_out_with(erin,kosta).
false.
2 ?-hangs_out_with(erin,john).
Someone s got a new friend!!
true.
Command prompt's output:
C:\(directory)>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,kosta),halt.
1 ?-halt. (the halt is inputted by me.)
C:\(directory)>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,john),halt.
Someone s got a new friend!!
The first query fails and the second succeds. As you can see, prolog after the query executions outputs true/false but when i execute the same query in command prompt the true/false values do not get echoed!!
I think you should ask
is_girl(X) :-
girl(X) -> write('t is true') ; write('it is not true').
EDIT
Do you mean this kind of thing ?
is_type(Type, X) :-
call(Type, X) -> writeln(yes); writeln(no).
so you "connect PHP to Prolog" by executing a Prolog query in command shell and capturing and analyzing its output. http://www.swi-prolog.org/man/quickstart.html says
"2.1.1.1 Starting SWI-Prolog on Unix
By default, SWI-Prolog is installed as 'swipl'. The command-line arguments of SWI-Prolog itself and its utility programs are documented using standard Unix man pages."
So do consult a man page about "-q" switch. Is it the "-q" for quiet perhaps? What does "-f" mean (ok, that's probably "file")? But the solution is the same - just use a different name for the new predicate.
Notice that in your first attempt,
C:>swipl -q -f knowledge_database.pl -g hangs_out_with(erin,kosta),halt.
1 ?-halt. (the halt is inputted by me.)
halt isn't executed, precisely because hangs_out_with(erin,kosta) has failed. A comma signifies conjunction (an "and").
All you need to do is create a new predicate that reports whether the goal is true or false, and succeeds always:
report_hangs_out_with(A,B):-
hangs_out_with(A,B)- > writeln(['YES',A,B]) ; writeln('NO').
and use it instead:
C:>swipl -q -f knowledge_database.pl -g report_hangs_out_with(erin,kosta),halt.
Also, Prolog echoing "true" or "false" is part of its interactive session. But you terminate it with halt!
edit: you posted:
1 ?-hangs_out_with(erin,kosta).
false.
So, when you run that query in interactive Prolog shell, it reports the failure. halt/0 exits the Prolog shell. When you run it with a goal specified through command line switch, apparently it does not report the success of failure. That's the fact of nature as far as we users are concerned (a.o.t. the compiler writers). It is easily addressable with what I've shown you. And you yourself say that it works, too. For each predicate that can fail or succeed, define another, reporting predicate, just as I've shown you.
Here's a sample transcript (in Windows, but that's irrelevant). That should clear up your doubts:
C:\Program Files\pl\bin>plcon -q -g (writeln('****'),halt).
**** // didn't say Yes, right??
C:\Program Files\pl\bin>plcon -q
1 ?- writeln('****'),halt.
**** // didn't say Yes here either
C:\Program Files\pl\bin>plcon -q
1 ?- writeln('****').
****
Yes // does say Yes as part of interaction
2 ?- halt.
C:\Program Files\pl\bin>
So that's the way it is. Deal with it. :) Or write Jan and ask him to change it. :)
girl(erin) :-
girl(erin)
-> write('it is true')
; write('it is not true').
This is wrong for two reasons. Prolog tries to resolve the body taking the left-most literal.
So it basically goes in a loop "is erin girl? yes, if erin is girl. Is erin girl?..."
The second reason is you are mixing two different things. Try to keep your knowledge representation part separated from the way you use it.
In Prolog you just say:
girl(erin)
And then query
?- girl(erin)
Prolog will just say "yes". If you want to print it, probably the easiest way is adding a predicate.
check_and_print(X) :- X, write(X), write(" is true").
Probably you need a call(X) instead of X, depending on the implementation you are using.
I'm not sure about the command prompt out, I suspect the outcome is returned in a different way.
I'm brand new to Prolog. I am simply trying to get some output from Prolog on Windows Vista.
I have downloaded and installed Prolog 5.1; I chose the .pro file extension when installing (not to confuse with Perl files).
I created a file called test.pro.
Inside this file I put the following:
inside(tom).
?-inside(tom).
I double clicked the file and a command line interface popped up. On this interface (after a bunch of generic Prolog version/copyright info) the only output is:
1 ?-
OK, for starters, I did not expect it to ask a question; I expected it to answer a question (something along the line of 'yes').
Anyway, I tried to respond to the query with the following:
In the command line I re-inserted 'inside(tom).', so the whole line looks like:
1 ?- inside(tom).
I pressed Enter and got an error message:
ERROR: toplevel: Undefined procedure: inside/1 (DWIM could not correct goal)
Prolog doesn't answer questions if you haven't told it facts. (Except for some built-in facts such as member(1, [1,2,3]).)
You can tell it who is inside by (comment follow a %):
1 ?- [user]. % get facts and rules from user input
|: inside(mary). % Mary and John are explicitly inside
|: inside(john).
|: inside(X) :- location(X, house). % rule: anyone in the house is inside
|: inside(X) :- location(X, office). % (variables start with a capital letter)
|:
|: location(tom, house).
|: location(bernard, house).
|: location(anne, office).
|: % type Ctrl+D
% user://1 compiled 0.00 sec, 1,220 bytes
true.
2 ?- inside(tom). % Prolog deduces that Tom is inside
true .
If you want to learn Prolog, Learn Prolog Now is a good, free tutorial.
You need to compile this first (also called "consult" in prolog). If I knew which version of prolog you have I could find out the exact key entry for this command (Ctrl-L may work). By the way, welcome to the wonderful world of prolog- I love it :) As soon as you're over this hurdle, it gets a lot better. :)
Quick and dirty. What was missing was 'compiling' the file, known as consult
and the syntax is as follows, all characters in the line are relevant.
?- [filename].
then you can ask questions and do other things with what the database.(the source code in prolog)
http://www.swi-prolog.org/pldoc/man?section=quickstart