Rdf: Arguments are not sufficiently instantiated?

I’m using: SWI-Prolog version 7.3.27

I want the code to:
I am creating a meta interpeter to reason over an rdf ontology. To make my rules a bit easier to read I abstract away the prefix. To this end I created a predicate to lookup fact in the ontology with the rdf/4 predicate which puts the prefixes back in.

But what I’m getting is:

For some reason prolog keep complaining about the arguments not being sufficiently instantiated. What I find weird is that it is complaining at compile time, not runtime as I would have expected for this type of error. Obviously I am missing something here.

15 ?- make.
ERROR: solver.pl:43:
Arguments are not sufficiently instantiated

My code looks like this:

fact(test(S-P-O)) :-
    literal(O), 
    rdf(test:S, test:P, O, tests).

The construct test:S won’t work. The prefix:local construct is expanded at compile time and thus must be known at compile time. Use rdf_global_id/2 to perform a runtime equivalent. AFAIK, recent versions of the RDF library do that for you.

That fixed it.

Thanks!

I spoke too early.

The fix seems to work quite well as long as I don’t included any variables.

I got it to work with variables but needed to make sure either the uri or the prefixed term was bound variable. This gave me the following code:

unpack_prefixed_uri(_Prefix, Term, Term) :-
    literal(Term).
unpack_prefixed_uri(Prefix, Term, Uri) :-
    var(Term),
    atom(Uri),
    rdf_global_id(Prefix:Term, Uri).
unpack_prefixed_uri(Prefix, Term, Uri) :-
    uri(Term),
    rdf_global_id(Prefix:Term, Uri).

fact(Prefix, S-P-O, Graph) :-
    nonvar(S), var(P), nonvar(O),
    unpack_prefixed_uri(Prefix, S, Suri),
    unpack_prefixed_uri(Prefix, O, Ouri),
    rdf(Suri, Puri, Ouri, Graph),
    unpack_prefixed_uri(Prefix, P, Puri).

I now have six different variations on this clause with nonvar Term called before rdf and var Term after. Is that the way it is supported to work? I have a feeling I’m still missing something.

You don’t really need that. You can make a predicate called before the rdf/3
that translates the input to a fully specified URI or object if the argument
is fully know and leave it unbound otherwise. Then after the rdf call, if the
argument is non-ground, you use rdf_global_id/2 (or rdf_global_object/2) to
fill in the unbound parts of the query.

So, before you get

prepare(Arg, Query) :-
    ground(Arg),
    !,
    rdf_global_id(Arg, Query).
prepare(_, _).

finalize(Arg, _) :-
    ground(Arg), !.
finalize(Arg, Query) :-
    rdf_global_id(Arg, Query).

dynrdf(S,O,P) :-
    prepare(S, QS),
    ...
    rdf(QS, ...),
    finalize(S, QS),
    ...

It does raise the question what you are doing though. I very rarely had
the need for something like this. For internal computation you do not
need this wrapper. You do want to specify prefix:local when you want to
specify constants in your code (e.g., rdfs:‘Resource’). In that case,
make sure the predicate where these constants are used as arguments are
declared using rdf_meta/1.

Reasoning such as myprefix:X is generally poor style and slow. Your
reasoning should consider URIs as atomic and you should use graph
properties to select the right data or (to me already second choice)
the 4th argument (graph name).

Hope this helps

Cheers --- Jan

The main reason I am trying this is to try to make my rules readable. I’m attempting to
connect rules like below to my ontology.

rule(one_more_person_rule,
        event(agent-saw_person_entering-Person)
    and
        believe(agent-sees_persons-Number)
    and
        NextNumber is Number + 1
    then 
        believe(agent-sees_persons-NextNumber)
).

It feels like requiring to use the full uri here would impact readability though I could perhaps transform the rules while loading them instead of the fact test during interpretation.

Yes, I think it is fine to have a default name space (or everything in the same) for your rules, but you should translate this into full URIs as early as you can. This both allows you to add namespace support to your rules if you need it and provides way better performance.

I changed the loader to transform the rules to conform to the rdf structure before executing them as you suggested. It works and seems a lot simpler.

Thanks!