I'm trying to "translate" a file that contains dcg's. in particular i am trying to transform all dcg into normal definite clauses using expand_term/2, however i would like to avoid manually translating all dcgs, so i would try to translate all clauses of the file at once (e.g. passing the whole file) . is there any way to do it?
for example, suppose we have a temp.pl file which contains some dcg:
a(X,Y) --> b(X), c(Y).
d([A | Ax]) --> b(A).
....
....
instead of using expand_term/2 individually for each term, like:
?- expand_term((a(X,Y) --> b(X), c(Y)), Clause).
Clause = [(:-non_terminal(user:a/4)), (a(X, Y, _A, _B):-b(X, _A, _C), c(Y, _C, _B))].
And then replace the dcg with definite clause in file.
I would like to pass for example the whole file (to a clause for example
) which contains the dcg, and translate all the dcg at once and print in a file or as an output, I don't know.
If I understand your question correctly then you are missing the obvious which is that what you seek is already in the SWI-Prolog code. The translation is done as the module is loaded. If you use listing/1 on a DCG predicate the code will list as normal Prolog and not DCGs.
See
dcg.pl
load.pl
expand.pl
apply_macros.pl
Demonstration of listing/1 with DCG
Directory: C:/Users/Groot
File: example.pl (Based on this SO answer )
:- module(example,
[
monlangage/2
]).
:- set_prolog_flag(double_quotes, chars).
monlangage --> "ab" | "a", monlangage.
Example run
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.3)
...
?- working_directory(_,'C:/Users/Groot').
true.
?- [example].
true.
?- listing(example:_).
monlangage(A, B) :-
( A=[a, b|B]
; A=[a|C],
monlangage(C, B)
).
true.
Notice that the source code is DCG with --> and the listing is not DCG with :-. Also notice that the rewritten clause has two extra arguments.
Related
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.
I have a prolog file that classifies a given predicate bongard(A, X) with given background facts.
Snippet of the rules:
bongard(A,[neg]) :- triangle(A,C), \+ in(A,C,D), !.
bongard(A,[neg]) :- \+ triangle(A,C), !.
...
I am executing this program like so: swipl -s file.pl -g "bongard(a, X), write(X)", to obtain the classification for this predicate.
Now I would also like to know which rule triggered and actually bounded the variable. Is there any neat way to do this? Right now I need to keep an additional n files for an original prolog file with n rules. File1 has the first rule, file2 has the first 2 rules.. You get the idea. This way if File2 classifies the rule, I know the second rule fired.
Does anyone have any better suggestions for this?
EDIT: What about giving the predicate a unique number "bongard(A, X, nr)" I could then both write(X) and write(Nr) so I know which predicate fired?
Can you not just add an id number:
bongard(1,A,[neg]) :- triangle(A,C), \+ in(A,C,D), !.
bongard(2,A,[neg]) :- \+ triangle(A,C), !.
...
and then do (eg)
swipl -s file.pl -g "bongard(N,a,X), format('~w (rule ~w)~n',X,N)"
I'm trying to write output from make_tests to a file, but nothing I've tried seems to insert the correct information in the output file.
I've looked at SWI documentaion at http://www.complang.tuwien.ac.at/SWI-Prolog/Manual/IO.html and have tried a whole bunch of those predicates but none have worked.
Here's what I'm trying to do:
:- use_module(library(test_wizard)).
init_test_file(FILE) :-
set_prolog_flag(log_query_file, FILE).
gen_test_in(FILE) :-
make_tests(lists, FILE, current_output).
So running this (in console) for example:
init_test_file('mytest.pro').
member(a, [a,b]).
gen_test_in('mytest.pro').
I get the following output (in console):
true.
6 ?- gen_test_in('r.pro').
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
:- end_tests(lists).
true.
How do I get this same output (starting at begin_tests and ending at end_tests in a text file?
I tried doing things like modifying gen_test_in to:
gen_test_in(FILE) :-
open(FILE, write, Out),
make_tests(lists, FILE, Out),
close(Out).
But I just get an empty text file.
You are messing up the arguments here. The library you are using, library(test_wizard), is meant for generating tests from queries. In the predicate you are using, make_tests/3, you have the following three arguments:
The module
The file from which the queries are read
The stream to which the generated tests are written
In the examples you use, you either set your output stream to be current_output (so standard output if you are on the top level), or, in the last example you give, you are opening the file you want to read for writing, and then pass the file and its handle to make_tests/3. Instead, if you have a file called queries.pl:
$ cat queries.pl
member(a, [a,b]).
member(X, [a,b]).
Then:
$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16-36-g42820df)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
?- use_module(library(test_wizard)).
true.
?- setup_call_cleanup(open('lists.plt', write, Out),
make_tests(lists, 'queries.pl', Out),
close(Out)).
Out = <stream>(0xe59ef0).
?- halt.
$ cat lists.plt
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
test(member, [all(A==[a, b])]) :-
member(A, [a, b]).
:- end_tests(lists).
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.
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.