I'm working on a validator that validates turtle files. When working on a function to check if the cardinality that's stated is correct for each object, I can't figure out how to access the value of a literal.
The literal value is Card=literal(type(xsd:nonNegativeInteger, '1')) (or 1^^'http://www.w3.org/2001/XMLSchema#nonNegativeInteger').
I find a bag of properties of length L. How can I check that L == Card?
I already tried the following:
% L and Card are both 1
rdf_canonical_literal(L, LiteralL), rdf_compare(=, LiteralL, Card).
% false
rdf_canonical_literal(L, LiteralL).
% LiteralL = 1^^'http://www.w3.org/2001/XMLSchema#integer'.
The problem is that xsd:integer and xsd:nonNegativeInteger don't compare as equal.
However, the easiest thing to me would seem to get the value of Card but I really don't see how to do it. Any solutions or pointers where to find an example of this would be much appreciated!!
If you use library rdf11 then most common datatype IRIs are automatically interpreted as Prolog values. In other words: there is no need to convert from RDF literals to Prolog values at all. Example:
?- [library(semweb/rdf11)].
?- rdf_assert(rdf:a, rdf:b, 1^^xsd:int).
?- rdf(_S, _P, N^^xsd:int).
N = 1.
You can extend library rdf11 with a hook for less common datatype IRIs, e.g., I use a lot of geographic data (datatype IRI geo:wktLiteral) which I let rdf/[3,4] interpret as Prolog Well-Known Text (WKT) notation automatically.
Related
It is not uncommon to see data in Prolog written with a functor, e.g.
note("This is a note")
but Prolog can also process the data with the name moved to an argument, e.g.
(note,"This is a note")
When moving the data name from the functor into an argument, is there a name used to describe this process?
I have some code that will have the data converted as such and would like to include in the documentation a standard name to describe this change if it exist.
EDIT
The current specific reason for doing this is so I don't have to use =../2 and can also make comparison on many datum with anonymous variable, e.g.
(_,A,B,C)
or write more general predicates, e.g.
do(_)
do(_,A)
do(_,A,B)
instead of
do(note(A))
do(note(A,B))
do(note(A,B,C))
do(comment(A))
do(comment(A,B))
do(comment(A,B,C))
do(text(A))
do(text(A,B))
do(text(A,B,C))
EDIT
Below is a comment by #repeat with reasons not to do what is demonstrated in this question by changing a compound term note(A,B) into a comma list (A,B), as opposed to a regular list [A,B]. It is good advise but sometimes there are reasons for breaking such advise. I can not say at present for my current need if doing this in Prolog is one of those cases, but as the question asks, it would be nice to have a name for the process so that it can be searched for research.
#repeat You can edit this and add notes as it is all Creative Commons.
Actually, (note, "this is a note") is a term with functor , and arity 2 (first argument note, and second argument "this is a note").
You can see this issuing the following queries:
?- write_canonical(note("This is a note")).
note("This is a note")
?- write_canonical((note,"This is a note")).
','(note,"This is a note")
So what you are doing by "moving" the principal functor of a term of arity N to a term of arity N+1 with principal function , adding the previous functor name as the first argument and shifting the other arguments is some sort of generalization, though I don't know if there is a more suitable name for this.
You could see it as a restricted way to write an applicative encoding of a higher-order logic fragment into first order logic. An applicative encoding uses constants to represent functions and uses a binary function symbol app to express that f is applied to an argument list. For example, the applicative encoding of f(g(a),b) is app(f, [app(g,[a]),b ]). In your case, the ,/N operator plays this role but as you have probably noticed, without an argument list you need to know the number of arguments when you are matching against such a term.
An example where this encoding is used in a Prolog context is the higher-order automated theorem prover input format TPTP THF. They use an infix operator # to represent application. There, they also use the standard encoding which uses nested apps. The term representation is not as beautiful (the example term is written (f # (g # a))) # b) but it has the advantage that constants only have one representation. With the list encoding, you have to take into account that c = app(c, []).
I'm trying to write a DCG for a command interface. The idea is to read a string of input, split it on spaces, and hand the resulting list of tokens to a DCG to parse it into a command and arguments. The result of parsing should be a list of terms which I can use with =.. to construct a goal to call. However, I've become really confused by the string type situation in SWI-Prolog (ver. 7.2.3). SWI-Prolog includes a library of basic DCG functionality, including a goal integer//1 which is supposed to parse an integer. It fails due to a type error, but the bigger problem is that I can't figure out how to make a DCG work nicely in SWI-Prolog with "lists of tokens".
Here's what I'm trying to do:
:- use_module(library(dcg/basics)).
% integer//1 is from the dcg/basics lib
amount(X) --> integer(X), { X > 0 }.
cmd([show,all]) --> ["show"],["all"].
cmd([show,false]) --> ["show"].
cmd([skip,X]) --> ["skip"], amount(X).
% now in the interpreter:
?- phrase(cmd(L), ["show","all"]).
L = [show, all].
% what is the problem with this next query?
?- phrase(cmd(L), ["skip", "50"]).
ERROR: code_type/2: Type error: `character' expected, found `"50"' (a string)
I have read Section 5.2 of the SWI manual, but it didn't quite answer my questions:
What type is expected by integer//1 in the dcg/basics library? The error message says "character", but I can't find any useful reference as to what exactly this means and how to provide it with "proper" input.
How do I pass a list of strings (tokens) to phrase/2 such that I can use integer//1 to parse a token as an integer?
If there's no way to use the integer//1 primitive to parse a string of digits into an integer, how should I accomplish this?
I did quite a bit of expermenting with using different values for the double_quote flag in SWI-Prolog, plus different input formats, such as using a list of atoms, using a single string as the input, i.e. "skip 50" rather than ["skip", "50"], and so on, but I feel like there are assumptions about how DCGs work that I don't understand.
I have studied these three pages as well, which have lots of examples but none quite address my issues (some links omitted since I don't have enough reputation to post all of them):
The tutorial "Using Definite Clause Grammars in SWI-Prolog" by Anne Ogborn
A tutorial from Amzi! Prolog about writing command interfaces as DCGs.
Section 7.3 of J. R. Fisher's Prolog tutorial
A third, more broad question is how to generate an error message if an integer is expected but cannot be parsed as one, something like this:
% the user types:
> skip 50x
I didn't understand that number.
One approach is to set the variable X in the DCG above to some kind of error value and then check for that later (like in the hypothetical skip/1 goal that is supposed to get called by the command), but perhaps there's a better/more idiomatic way? Most of my experience in writing parsers comes from using Haskell's Parsec and Attoparsec libraries, which are fairly declarative but work somewhat differently, especially as regards error handling.
Prolog doesn't have strings. The traditional representation of a double quoted character sequence is a list of codes (integers). For efficiency reasons, SWI-Prolog ver. >= 7 introduced strings as new atomic data type:
?- atomic("a string").
true.
and backquoted literals have now the role previously held by strings:
?- X=`123`.
X = [49, 50, 51].
Needless to say, this caused some confusion, also given the weakly typed nature of Prolog...
Anyway, a DCG still works on (difference) lists of character codes, just the translator has been extended to accept strings as terminals. Your code could be
cmd([show,all]) --> whites,"show",whites,"all",blanks_to_nl.
cmd([show,false]) --> whites,"show",blanks_to_nl.
cmd([skip,X]) --> whites,"skip",whites,amount(X),blanks_to_nl.
and can be called like
?- phrase(cmd(C), ` skip 2300 `).
C = [skip, 2300].
edit
how to generate an error message if an integer is expected
I would try:
...
cmd([skip,X]) --> whites,"skip",whites,amount(X).
% integer//1 is from the dcg/basics lib
amount(X) --> integer(X), { X > 0 }, blanks_to_nl, !.
amount(unknown) --> string(S), eos, {print_message(error, invalid_int_arg(S))}.
prolog:message(invalid_int_arg(_)) --> ['I didn\'t understand that number.'].
test:
?- phrase(cmd(C), ` skip 2300x `).
ERROR: I didn't understand that number.
C = [skip, unknown] ;
false.
It will be quite a miracle if someone could help with the following...
I'm using SWI-Prolog to perform queries in a triples RDF file. The values can be queried, but instead of just a number, the word Literal shows up in front of them (e.g [literal(500000)] shows up for the value 500000). Now, the problem arises when I have a list of numbers that I want to add. I try to convert these Literals into atoms so that Prolog can recognize them as numbers, but get the following error
ERROR: atom_number/2: Type error: atom' expected, found [literal(500000)]'
Any clues would be appreciated. Thanks.
Just use unification to get the number. For instance
?- [literal(500000)] = [literal(N)].
N = 500000.
I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject and Object.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
Using it works like this:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
So, here's what you should notice about this code:
We're using =../2, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.
I've swapped subject and object, because doing it the other way is almost certainly not what you want.
The predicate you want is assertz/1 or asserta/1, not assert/2. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.
Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
Prolog predicates do not return values. So assert(term_to_atom(... wasn't even on the right track, because you seemed to think that term_to_atom would "return" a value and it would get substituted into the assert call like in a functional or imperative language. Prolog just plain works completely differently from that.
I'm not sure why you have an empty variable in your term_to_atom predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.
There is an assert/2, but it doesn't do what you want. It should be clear why assert normally only takes one argument.
Prolog facts should look like property(subject...). It is not easy to construct facts and then query them, which is what you'd have to do using man(tall). What you want to say is that there is a property, being tall, and man satisfies it.
I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
If you want to isolate the first and last and create the fact, you have to use univ again:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though:
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
is_a(john, man).
property(man, tall).
property(john, thin).
(think SQL tables in a normal form). Then you can use simple assertz/1 to update the database:
add_property(X, Y) :- assertz(property(X, Y)).
i know there is a build-in function findall/3 in prolog,
and im trying to find the total numbers of hours(Thrs) and store them in a list, then sum the list up. but it doesnt work for me. here is my code:
totalLecHrs(LN,THrs) :-
lecturer(LN,LId),
findall(Thrs, lectureSegmentHrs(CC,LId,B,E,THrs),L),
sumList(L,Thrs).
could you tell me what's wrong with it? thanks a lot.
You need to use a "dummy" variable for Hours in the findall/3 subgoal. What you wrote uses THrs both as the return value for sumList/2 and as the variable to be listed in L by findall/3. Use X as the first argument of findall and in the corresponding subgoal lectureSegmentHrs/5 as the last argument.
It looks like the problem is that you're using the same variable (Thrs) twice for different things. However it's hard to tell as you've also used different capitalisation in different places. Change the findall line so that the initial variable has the same capitalisation in the lectureSegmentHrs call. Then use a different variable completely to get the final output value (ie the one that appears in sumList and in the return slot of the entire predicate).
You need to use a different variable because Prolog does not support variable reassignment. In a logical language, the notion of reassigning a variable is inherently impossible. Something like the following may seem sensible...
...
X = 10,
X = 11,
...
But you have to remember that , in Prolog is the conjunction operator. You're effectively telling Prolog to find a solution to your problem where X is both 10 and 11 at the same time. So it's obviously going to tell you that that can't be done.
Instead you have to just make up new variable names as you go along. Sometimes this does get a bit annoying but it's just goes with the territory of a logical languages.