2

I would like to construct a mechanism that constructs different facts depending from txt file, imported in prolog. I already have found some examples where they directly assert the line that was read from the file, but I have to transform the data before assertion can take place.

To give an example:

man = {m1, m2}.

m1: w1 > w2.

should be read as:

man(m1).
man(m2).
prefer(m1, w1, 1).
prefer(m1, w2, 2).

Is it possible to construct these facts based on the symbols of the input?

false
  • 10,264
  • 13
  • 101
  • 209
JasperTack
  • 4,337
  • 5
  • 27
  • 39

3 Answers3

4

yes - you need to do what you'd do in any other language.

Open and read the file, parse the contents, and convert into terms that you can then assert.

Fortunately, you're in prolog, so 'parse the contents' is a task the language does for breakfast.

It turns out I've been writing a tutorial on how to do pretty much this exact task. It's not quite finished, but is online at

http://www.pathwayslms.com/swipltuts/dcg/

If your files are large, use the method described in the tutorial to read them. Otherwise, just bring the file into a 'codes' style string and go on with life.

Anniepoo
  • 2,152
  • 17
  • 17
3

thanks to the fact that data presented in example is valid Prolog syntax, this code will do

load_file_data(File) :-
    open(File, read, Stream),
    repeat,
    read(Stream, Term),
    (   Term = end_of_file
    ->  true
    ;   process(Term),
        fail
    ),
    close(Stream).

process(X = {L}) :-
    forall(arg(_, L, A), (F =.. [X, A], assert(F))).
process(X : A > B) :-
    assert(prefer(X, A, 1)),
    assert(prefer(X, B, 2)).

note that the precedence of operators in m1: w1 > w2 is not what we could expect, but it works anyway, thanks to complete pattern matching. Use

?- write_canonical(m1 : w1 > w2).
>(:(m1,w1),w2)

to check precedence when not sure.

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • oops, I wasn't paying close attention - yup, CapelliC's right, you can do it all with operator definitions. – Anniepoo Dec 24 '12 at 23:21
2

You can do any 'normal' prolog in a DCG by enclosing it in {}

some_nonterminal --> "fridge", blanks, [X], { % you can put any normal Prolog code in here assert(fridge_named(X)) }.

This looks for a sequence like

fridge G

and asserts fridge_named(0x47) in the database (Ascii G is 0x47)

Anniepoo
  • 2,152
  • 17
  • 17
  • but what I want is to add an atom to the database so when I have : some_nonterminal --> "fridge", blanks, atom(X), { assert(fridge_named(X)) }. Nothing is added ... how come? – Jeremy Knees Dec 31 '12 at 15:25
  • show a complete sample. I suspect you're not defining blanks, or not calling phrase properly or something. You can also put a writeln in the {} to prove you're getting there – Anniepoo Dec 31 '12 at 19:53
  • what I want is to bind my X to an atom instead of a string. Then assert the "name of the fridge" as an atom. – Jeremy Knees Jan 02 '13 at 09:18
  • atom_codes(AFridge, StringFridge), assert(fridge_named(AFridge)). – Anniepoo Jan 03 '13 at 03:48