How to test binary trees in prolog - prolog

I want to test this prolog program:
#
binary_tree(void).
binary_tree(tree(_Element,Left,Right)):-binary_tree(Left),binary_tree(Right).
test(tree(a,tree(b,tree(d,void,void),void),tree(c,void,void))).
#
When I execute it with:
test(X), binary_tree(X).
I get
X = tree(a, tree(b, tree(d, void, void), void), tree(c, void, void)).
(and I should get "true" instead)
What am I doing wrong?
Thanks

Who says you should just get true instead? Calls to Prolog predicates may succeed or fail. On success, they answer with a variable substitution, as in your case. Your Prolog system's answer says that your test succeeded, as you expected.
You will usually only get true if no variable substitution can be given because the query does not contain any variables. If the query fails, you will get false or fail but no variable substitution.

Related

Prolog what's the difference between \+ and \=

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.

Why does CMake syntax have redundant parentheses everywhere?

CMake's ifs go like this:
if (condition)
...
else if (...)
...
else (...)
...
endif (...)
With else if (...) the (...) tests for a separate condition.
Why else (...) and not just else? Why endif (...) and not endif?
Cmake's functions go like this:
function(funcname ...)
...
endfunction(funcname ...)
Why endfunction(funcname ...) and not simply endfunction?
I can omit the contents of the redundant parenthesis where they appear, like so: endif (). What's the purpose of this construct?
I believe the initial intention was that, by repeating at each clause (for example, else statement) the initial expression (for example, the one at the if statement) it would make more clear which statement was actually closed, and the parser could verify and warn nothing wrong was going on.
However, it turned out that you would have expression like:
if (VARIABLE matches "something")
[...] #This is executed when above condition is true
else (VARIABLE matches "something") #Looks very much like an elseif...
[...] #This is executed when above condition is false!
endif (VARIABLE matches "something")
Which turned out to be confusing. I am speaking about my every day experience, e.g. I write something and somebody else come to ask me "What does this does?"
So, now CMake allows also to put empty parenthesis, the above can be rewritten as:
if (VARIABLE matches "something")
[...] #This is executed when above condition is true
else ()
[...] #This is executed when above condition is false
endif ()
Which can be considered clearer. The grammar above can still be used.
To completely answer to your question, the parenthesis stay also with empty arguments because conceptually else and endif in CMake are macros like if, and therefore they are invoked with this grammar, a little bit (but not at all exactly) as functions.
Basically the same explanation is available in CMake FAQs: Isn't the "Expression" in the "ELSE (Expression)" confusing?.
To add a little bit of history, in CMake 2.4 repeating the expression was obligatory, and still in CMake 2.6, at least according to the documentation. The documentation was ambiguous on else, but adamant on endif:
Note that the same expression must be given to if, and endif.
The first try to remove this constraint was introduced already with CMake 2.4.3 (year 2006), where it was possible to deactivate it by writing:
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
This constraint became fully optional with CMake 2.8
Note that the expression in the else and endif clause is optional.

Swi prolog Error: Showing true but not false

Just installed SWI-Prolog on my W8 machine and it's throwing an error.
Here's the error:
ERROR: toplevel: Undefined procedure: mark/0 (DWIM could not correct goal)
Let's say my prolog source file contains one fact:
Prolog source...
it_is_monday. //The fact
So I compile the buffer, and get:
.../documents/prolog/prologSource compiled 0.00 sec, 2 clauses
Now when I input
it_is_monday.
The output as expected is true. However when I input say,
some_other_statement.
I get the error posted above as opposed to false. Can anyone tell me what's going on here?
Solution: Different prolog version.
There's a standard Prolog flag, unknown, that is set by default in SWI-Prolog and other modern Prolog compilers to error, meaning that an attempt to call an unknown predicate will result in an exception. This flag can be set (using the standard set_prolog_flag/2 predicate) instead to fail to get the behavior that you seem to be expecting but that's not advisable as it may make debugging harder. E.g. a simply typo in a predicate name will result in a failure which, in a complex program, could be difficult to trace down while a predicate existence error would pinpoint the culprit at the spot.
You get the error
ERROR: toplevel: Undefined procedure: mark/0 (DWIM could not correct goal)
because you haven't defined the procedure you tried to execute. (that's why it says undefined)
If you define it, by editing your .pl file and writing
some_other_statement.
and you run it again, you'll get
1 ?- some_other_statement.
true.
In Prolog you need to define every procedure you want to execute.
When you try to execute an undefined procedure, the name of the procedure will show up in the error. So, if you haven't defined some_other_statement., the error will be:
2 ?- some_other_statement.
ERROR: toplevel: Undefined procedure: some_other_statement/0 (DWIM could not correct goal)
notice that some_other_statement/0 is being shown on the error that I got.
EDIT : If you wanted to get a false message, you would have to define something like some_other_statement(1). and then execute a query like some_other_statement(12).
2 ?- some_other_statement(12).
false.
if you want to receive false from that you can add the directive
:- dynamic(some_other_statement/0).
at the beggining of the file, so when you execute the query
?- some_other_statement.
you will get false

Writing recursion in swi-prolog

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.

Using logical OR (||) in C-Shell

I have a C-Shell code where I use the following command:
if($#arr == 0 || $arr[1] == "test1") then
It outputs an error message saying "tcsh: arr: Subscript out of range." obviously because the first condition is true. Is it possible to force it to ignore the second condition if the first condition is true?
csh parses the entire line and substitutes variables before evaluating the expression. so in this case, you'd need a nested if because the or condition does not implement short-circuit evaluation with respect to variables.

Resources