Search code examples
prologwekaswi-prologarff

How to read a query from a text file, modify it, and call it


I have a Weka arff file, where the attributes are Prolog queries.

I want to read the query from the file, modify it, and then run the query.

The weka arff file begins like:

@relation propositionalization
@attribute 'link(_, A, _), link(A, _, _)' {'+'}
@attribute 'reaction(A, 0), link(A, B, _), link(B, C, _), reaction(C, 1), link(B, D, activation), reaction(D, 0), reaction(B, 0), link(A, E, _), link(E, F, follows), reaction(F, 1)' {'+','-'}
@attribute 'reaction(A, 0), link(A, B, _), link(B, C, _), reaction(C, 1), reaction(B, 1), link(A, D, _), link(D, E, follows), reaction(E, 0)' {'+','-'}

etc

I have a dcg made up of:

list([]) -->[].
list([L|Ls]) --> [L],list(Ls).
get_feature(Feature) --> "@attribute '",list(Feature), "'",list(_).

I read the file with:

read_my_file(File,Lines):-
open(File,read,Stream,[]),
    read_lines(Lines,Stream),!.

read_lines([H|T],Stream):-
  read_line_to_codes(Stream,H), H\=end_of_file, read_lines(T,Stream).

read_lines([],Stream):-close(Stream).

And use the following to call phrase/2 to extract the feature as a code list.

lineCodes_feature(Line,Feature):-
 phrase(get_feature(Feature),Line),!.

I then call:

read_my_file('my_file.arff',Lines), 
member(Line,Lines), 
lineCodes_feature(Line,Feature), 
atom_codes(Atom,Feature).

And back track to see each feature as an atom.

I am stuck at the next step of modifying and running this as a query. I want to change the reaction/2 terms to reaction/3 where the additional argument will be the same for each term.

So for example the atomic term

'reaction(A, 0), link(A, B, _), link(B, C, _), reaction(C, 1), reaction(B, 1), link(A, D, _), link(D, E, follows), reaction(E, 0)' 

Would I imagine become a list :

[reaction(newarg,A, 0), link(A, B, _), link(B, C, _), reaction(newarg,C, 1), reaction(newarg,B, 1), link(A, D, _), link(D, E, follows), reaction(newarg,E, 0)]

Which would allow me to somehow use call/1 to query the internal database?

Any help or comments on my approach appreciated.


Solution

  • I think you could use read_term_from_codes, then call the outcome term.

    ...
    read_term_from_codes(Feature, Callable, []),
    transform(Callable, Transformed),
    Transformed,
    ...
    

    An example, using library(dcg/basics) and phrase_from_file/2 to ease parsing

    :- use_module(library(dcg/basics)).
    
    sw :- phrase_from_file(arff_file, '/home/carlo/test/x.weka').
    
    arff_file --> [] ; arff_line, arff_file.
    
    arff_line -->
        "@relation propositionalization", eol.
    arff_line -->
        "@attribute '", string(Codes), "'",
        {read_term_from_codes(Codes, Prolog, []),
         transform_conjunction(Prolog,Transf),
         format('~w ->~n ~w~n', [Prolog, Transf])},
        string(_), eol.
    arff_line -->
        eol.
    
    eol --> "\n".
    
    transform_conjunction((A,B),(C,D)) :- transform_term(A,C), !, transform_conjunction(B,D).
    transform_conjunction(A,C) :- transform_term(A,C).
    
    transform_term(reaction(B,C), reaction(newArg,B,C)).
    transform_term(T, T).