Prolog : Never Ending Process - prolog

I am trying to use get_coeff_value() but the process never end.
get_coeff_value(Val,[],[]).
get_coeff_value(Val, [X|T],Coeff_List):-
get_coeff_value(Val,T,Coeff_List1),
get_val(Val,[X], Coeff),
insert_end(Coeff_List1, Coeff, Coeff_List).
command : get_coeff_value('H', ['H'-5, 'C'-2], Coeff).
I tried get_val() and insert_end() both end perfectly.
However this one display :
command result
It gives me the answer I am waiting for but it never stops the process.

This looks the same as what happens if you query e.g. ?- member(X, [1,2,3]). ; your code has left choicepoints and the Prolog toplevel has found one solution but has not explored the whole search space of your code, so it is waiting for your input.
Press ? to see the help, ; or space to continue searching for more answers, or a to abort the search and stop there.
SWI Prolog help on pressing ?
Possible actions:
; (n,r,space,TAB): redo | t: trace&redo
*: show choicepoint | c (a,RET): stop
w: write | p: print
b: break | h (?): help

Related

at_end_of_stream on stdin in Prolog

I ask SICStus Prolog ?- at_end_of_stream. on the top-level and immediately I get: no.
GNU Prolog and Scryer Prolog do the same.
Traella Prolog and SWI-Prolog, however, choose to wait for input before answering, and rumor has it that behaving like this has been quite common among Prolog systems—especially in the past.
If I look at the ISO-Prolog standard, that behavior becomes spurious:
8.11.8.5 Bootstrapped built-in predicates
The built-in predicates at_end_of_stream/0 and at_the_of_stream/1 examine the single stream-property end_of_stream/1.
A goal at_end_of_stream is true iff the current input has a stream position end-of-stream or past-end-of-stream (7.10.2.9, 7.10.2.13).
A goal at_end_of_stream(S_or_a) is true iff the stream associated with stream or alias S_or_a has a stream position end-of-stream.
at_end_of_stream :-
current_input(S),
stream_property(S, end_of_stream(E)),
!,
(E = at ; E = past).
[The the sake of brevity, I omitted the code for at_end_of_stream/1.]
So it appears that the standard is quite clearly on the side of SICStus Prolog and GNU Prolog.
So my question boils down to this:
Is this "waiting" behavior simply non-conformance, a kind of anachronism justified on the basis of practicality / compatibility—or is there more to it?
Handling end of stream is hard, on the top-level it's even harder.
A very simple and basic top-level is like sh (dash). Prolog top-level is a bit similar, it differs by having auto-completion/choice (like Scryer Prolog, SWI-Prolog), not accepting input with ctrl-D but it could be like sh.
A query to test and better understand top-level is ?- get_char(C).%a (where C binds to %, source) and ?- get_char(C). (when submitting with enter, C binds to \n, if submitting with ctrl-D then waits or binds C to end_of_file).
Why those query?
The top-level can be model as read_term(user_input, Goal, []), call(Goal):
Case get_char(C).%a submitted with enter: The query is parsed and the user_input is %a\n thus C binds to % and if get_char(C) is replaced by at_end_of_stream then at_end_of_stream/0 fails.
Case get_char(C). submitted with enter: The query is parsed and the user_input is \n thus C binds to \n and if get_char(C) is replaced by at_end_of_stream then at_end_of_stream/0 fails.
Case get_char(C). submitted with ctrl-D: The query is parsed and the user_input is empty. Now the stream position of user_input should be end-of-stream or past-end-of-stream if read_term/3 is executed as procedurally specified in 8.14.1.1:
If user_input doesn't have an end then with the note of 7.10.2.9 the stream postion can't be end-of-stream or past-end-of-stream. Is the stream reset and has end_of_stream property not? What happens if the stream doesn't have the property eof_action(reset)? In any case get_char/1 waits and if get_char(C) is replaced by at_end_of_stream then at_end_of_stream/0 fails (there is an opportunity for at_end_of_stream/0 to wait here).
Else user_input has a size but it's unknown (or variable but still unknown) then:
If stream position is end-of-stream then C binds to end_of_file and if get_char(C) is replaced by at_end_of_stream then at_end_of_stream/0 succeeds.
Else stream position is past-end-of-stream then get_char/1 waits and if get_char(C) is replaced by at_end_of_stream then at_end_of_stream/0 succeeds.
Sadly there is a bit of twisting at the end.
I might have missed/misread something if not then this undefinedness allows some optimization/simplification of the implementation, explains the difference between engine and also the actual top-level is more complicated that read_term(user_input, Goal, []), call(Goal) (even if it's the ideal one).
When it comes to at_end_of_stream/0, it doesn't seem like there is a reason to wait.
Digression
If at_end_of_stream/0 is implemented with peek_char/1 without executing eof_action then that might explain the wait.
On other operating system, it may be different. I use and test on Linux.
On GNU Prolog (version 1.5.0), there is the issue that a stream with property eof_action(reset) is never at end of stream. This explains why at_end_of_stream/0 fails.
$ echo -n | gprolog --init-goal "(at_end_of_stream, write(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
not(end_of_file)
$ echo | gprolog --init-goal "(at_end_of_stream, writeq(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
not('\n')
at_end_of_stream/0 fails even when the stdin is empty.
On Trealla Prolog (version v2.1.11):
$ echo -n | ./tpl -g "(at_end_of_stream, writeq(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
at
$ echo | ./tpl -g "(at_end_of_stream, writeq(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
not('\n')
$ echo -n | ./tpl -g "(stream_property(S, alias(user_input)), stream_property(S, end_of_stream(Eos)), at_end_of_stream(S), writeq(eos(Eos)), halt ; halt)"
eos(not)
The property end_of_stream doesn't agree with at_end_of_stream/1 (permuting stream_property/2 and at_end_of_stream/1 doesn't change the result).
On Scryer Prolog (on master (6b8e6204957bfc3136ea39ec659d30627775260d) or rebis-dev (c1945caf11c0d202f4121de446f1694854dcba47)):
$ echo -n | ./target/release/scryer-prolog -g "(at_end_of_stream, write(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
not('\x0\')
$ echo | ./target/release/scryer-prolog -g "(at_end_of_stream, write(at), nl, halt ; peek_char(C), writeq(not(C)), nl, halt)"
not('\n')
at_end_of_stream/0 fails even when the stdin is empty.
How to make the at_end_of_stream/0/stream_property/2 wait?
Using the top-level read_term(user_input, Goal, []), call(Goal), the query ?- get_char(C), at_end_of_stream. can wait.
The query ?- at_end_of_stream. doesn't wait because of read_term/3 since it needs to peek to determine the end token and it can update the stream position.
If user_input doesn't have an end then with the note of 7.10.2.9, at_end_of_stream/0 fails.
Else user_input has a size but it's unknown (or variable but still unknown) then at_end_stream/0 waits. The query get_char(C), at_end_of_stream. is submitted with enter. The query is parsed and user_input is \n. Now get_char/1 reads \n, user_input is empty and get_char/1 should update stream position as specified by 8.12.1.1. But get_char/1 can't update user_input and needs not do an update by peeking, it can be left for when the user tries to observe with at_end_of_stream/0. Now at_end_of_stream/0 waits.
Another way to make at_end_of_stream/0 waits is to use the top-level at_end_of_stream. The initial stream position of user_input is unknown (the size of the stream is unknown) thus at_end_of_stream/0 waits.
Small digression: get_char/1 can't update the stream position of user_input unless it reads end_of_file in which case user_input stream position is updated to past-end-of-stream.

How to output all solutions for Goal from non-interactive script

I have a Node.JS application that I want to do the following with:
1. Queries an API to read clauses and writes them to a file data.pro
2. Runs swipl as a command to output the result
3. Parses the result and continues the Node.JS execution.
I already have the swipl command as:
swipl -s triangular.pro -g "customRatio(A,C,D,1.05,T)." -t halt.
Now customRatio/5 has a ton of solutions that I would like to process further in my main application. An example output of running this in interactive mode would be:
A = (portugal, brazil, 656.1249261859458),
B = (brazil, germany, 5.36135535063264),
C = (germany, portugal, 0.0002993),
T = 1.0528532618885567 ;
I don't need it to be in this format, I just want the most straightforward way to get all the goals from adding something either to the command or my program. I've seen examples with findAll but couldn't get it to work with multiple outputs to the stream. I've also seen examples with dump and write.
I'm just thinking there must be a trivial way to just dump all the results to a file.
Thank you in advance.
Could your please elaborate, which problems did you encounter with forall?
The forall/2 based solution I can think is as follows (I've split it to multiple lines so it's more readable):
forall(
(Goal = customRatio(A, C, D, 1.05, T), call(Goal)),
(write(Goal), nl)
)
The command becomes:
swipl -s triangular.pro -g "forall((Goal = customRatio(A, C, D, 1.05, T), call(Goal)), (write(Goal), nl))." -t halt.
PS: you can put forall into helper predicate which takes Goal as an argument and then writes all results to screen or file, e.g.:
swipl -s triangular.pro -g "results_to_file(customRatio(A, C, D, 1.05, T))." -t halt.
So with the help of the comments from #DmitriChubarov and a similar reply from #code_x386 I got there.
Assuming we have a function that already provides the results:
customRatio(A,C,D,1.05,T)
We want all results for the Goal and write them to a file. I've done that using:
findOpportunities(MinRatio):-
open('output.txt',write, Stream),
findall((P1,P2,P3,Ratio),customRatio(P1,P2,P3, MinRatio, Ratio), List),
write(Stream, List),
close(Stream).
And then calling the following on the command line:
swipl -s triangular.pro -g "findOpportunities(1.02)." -t halt.
The solution proposed by code_x386 works but writes the clause as well as the results, for example:
customRatio((portugal,brazil,1707.3295658260913),(brazil,germany,0.03409),(germany,portugal,0.017399),1,1.0126716463779004)
customRatio((brazil,germany,0.03409),(germany,france,0.001601),(france,brazil,18663.68047779022),1,1.018628032848078)
customRatio((brazil,germany,0.03409),(germany,portugal,0.017399),(portugal,brazil,1707.3295658260913),1,1.0126716463779004)
Thank you both!

Read a file line by line error in prolog

For reading a file i'm using below code, but this code reads only lines where there is a '.' in the end of file, is there another way to read any kind of file and store in the list?
main :-
open('myFile.txt', read, Str),
read_file(Str,Lines),
close(Str),
write(Lines), nl.
read_file(Stream,[]) :-
at_end_of_stream(Stream).
read_file(Stream,[X|L]) :-
\+ at_end_of_stream(Stream),
read(Stream,X),
read_file(Stream,L).
I took this code from this link
Read a file line by line in Prolog
Please note that the code you wrote is inherently incorrect for the following reasons.
1mo, you are reading Prolog data, and not lines at all. Take a. b. c. which would make a list [a,b,c].
2do, testing for at_end_of_stream/1 is extremely tricky, and does not work as expected when reading Prolog data. Take the 3-line file:
first_fact.
second_fact.
% no comment - oh that's a comment nevertheless
This will give you the list [first_fact, second_fact, end_of_file]. For read/1 gives you a term end_of_file after having read the last line.
3tio, upon backtracking, main will always produce an error!
?- main.
[first_fact,second_fact,end_of_file]
true ;
ERROR: at_end_of_stream/1: stream `<stream>(0x1c38330)' does not exist
If you want to read just bytes use library(pio). And to use that, first learn the dcg formalism.
The following will succeed for each occurrence of magic in the file:
?- phrase_from_file((..., "magic", ...), filename).
using the following definition of ... //0:
... --> [] | [_], ... .
See this for more.

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.

How do I show the results of pattern-matching goals with several free variables in SWI-Prolog from a shell invocation?

Let's use the following prolog base :
father(anakinSkywalker, princessLeia).
father(anakinSkywalker, lukeSkywalker).
saysOhNo(lukeSkywalker).
sdesciencelover asked how to show the results of pattern-matching goals in swi-prolog from a shell invocation, and got an answer giving a manual transformation on the query, to isue a write.
swipl -q -s kb.pl -t "father(anakinSkywalker,X), writeln(X), false"
Result:
princessLeia
lukeSkywalker
This works fine when one only has a few queries with a single free variable, but manually transforming each one becomes tedious, and if we want proper output with the name of each variable along with its result, it soon becomes very annoying. For example to run the query father(AVariable, Another), one needs to write:
swipl -q -s kb.pl -t "father(AVariable,Another), write('AVariable='), write(AVariable), write(', Another='), writeln(Another), false"
Result:
AVariable=anakinSkywalker, Another=princessLeia
AVariable=anakinSkywalker, Another=lukeSkywalker
I tried to feed it the commands from a pipe, but it doesn't work great (I can't detect when it has finished writing the results, so it just hangs afterwards, and no newline separates the answers) :
(echo "father(X,Y)."; while true; do echo ";"; done) | swipl -q -s kb.pl
Result :
X = anakinSkywalker,
Y = princessLeia X = anakinSkywalker,
Y = lukeSkywalker.
swipl hangs here, and needs to be stopped with Control-C.
I know I could use a sed script to pre-process queries, adding the necessary code to print the variables in capital letters, but it would need a fair amount of work to work on complex queries, for example where two predicates must be satisfied :
father(X,Y), saysOhNo(Y).
To always give correct results, one would need to write a parser for prolog, which would be useless work since prolog already know how to do this interactively.
So here's my question : is there a way to tell GNU prolog or SWI prolog (or any other free version that can be easily installed on linux) to run some queries and print the results, just like they would do interactively, but without requiring me to type (or copy-paste) each query by hand ?
Edit : a way to store a series of queries in a file (either in the kb.pl file or an auxiliary file) and run them all, showing their results would be even better.
So far, here are the methods I found :
In gprolog
Using false's answer, I found that one must add a line at the top of the kb.pl file:
a(_) :- fail.
and then use ./query.sh kb.pl "father(X,Y), saysOhNo(Y)", where query.sh is:
#!/bin/sh
echo "a(fail)." | gprolog --query-goal "consult('$1'), $2"
When the query returns immediately (i.e. no results or a single result and gprolog managed to detect it was the last one), this will run the query consult('kb.pl'), actual_query., and then run the query a(fail). which will simply print an extraneous no on the console, thanks to the always-false predicate we added at the top of the file.
When gprolog asks what to do (i.e. several results, or a single result and gprolog couldn't detect it was the last one), this will run the query consult('kb.pl'), actual_query., read the a which asks gprolog to print all results, and then it will run the query (fail). which will simply print an extraneous no on the console, because these are just grouping parenthesis, so the query is equivalent to fail..
In xsb
One can use ./query.sh kb.pl "father(X,Y), saysOhNo(Y)", where query.sh is:
#!/bin/sh
(echo "consult('$1'), ${2%.}."; yes halt.) | xsb --noprompt --quietload --nobanner
When xsb asks what to do next, if the user types a non-empty string, followed by enter, it will print the next result, otherwise it will stop searching solutions to the current query. Therefore, with the yes halt. command, we type an infinite stream of non-empty lines. xsb will print all results to the query (each time reading halt., so as it is a non-empty string, it will continue with the next result), and return to its prompt. Then, the following halt. it receives will tell it to quit.
In swi-prolog
I haven't found a solution yet.
[rant]All this would be so much simpler, if the people building prolog implementations actually thought about using them non-interactively, like it's possible with most other languages.[/rant]
You can use the command-line option --query-goal in GNU. Like so:
$ echo a| gprolog --query-goal 'X = 1 ; X =2'
GNU Prolog 1.4.1
By Daniel Diaz
Copyright (C) 1999-2012 Daniel Diaz
| ?- X = 1 ; X =2.
X = 1 ? a
X = 2
yes
You may have found a solution for your problem but anyway, here goes my approach. You can always recurse to the bagof built-in predicate. You may read what it does in the docs, this way you will learn more about it.
swipl -q -s starwars.pl -t "bagof(X, Y^father(X,Y), BagOfFathers), bagof(Y, X^father(X,Y), BagOfChildren), writeln(BagOfFathers), writeln(BagOfChildren)."
[anakinSkywalker,anakinSkywalker]
[princessLeia,lukeSkywalker]
You can also process it later as a mapping or whatever you want, the relations are 1:1 (No sure if is the correct way of stating it but I hope you get it)
you can use the following bash script for swi-prolog:
#!/bin/sh
exec swipl -q -f none -g "load_files([interface],[silent(true)])" \
-t interface:get_args -- $*
this will load the file interface.pl and call the predicate get_args/0
to get the command line arguments you can call:
current_prolog_flag(argv, Arguments)
of course you can change the names of the predicates/files loaded.
the silent(true) arguments suppresses informational messages such as the intro text
edit:
the error message you get is cause you probably dont have an interface.pl file (neither a get_args/0 predicate).
you will have to replace interface with kb (or however you name the file) and interface:get_args with kb:father(X,Y), saysOhNo(Y) or use an auxiliary predicate within your prolog file such as run(X,Y):- father(X,Y), saysOhNo(Y) (which may be kinda cleaner)

Resources