1
votes

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!!

3
I thought it'll be likes(erin, reading). likes(john, erin). :) just kidding. :) ... joel76 is right - you can't use the same name for the new predicate. This is what causes the runaway recursion and hence out of local stack error. You already have a predicate named girl, it defines a fact girl(erin) in your database. Now you define new predicate, report_whether_it_is_a_girl(X):- girl(X) -> write('IS A GIRL') ; write('IS NOT'). Just using a different name for a different predicate is enough, and it makes sense to. One succeeds or fails ; the other writes a message.Will Ness
@WillNess thanks. I 've already tried out what joel76 suggested. As you can see in the question i asked, I m doing these as to echo the true/false value that prolog returns but for some reason does not get echoed when i execute a query trough windows command prompt.Erin
I've added an answer. If this doesn't help, please edit your question and show us a transcript of what's going on.Will Ness
this stackoverflow.com/q/11759336/849891 seems to be related. :)Will Ness
@WillNess :) yes it is related! :) thanks ONCE again. You are the best!! :)Erin

3 Answers

1
votes

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. :)

2
votes

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).
1
votes
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.