Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to represent logic expressions in RDF #2

Open
sandhawke opened this issue Dec 17, 2018 · 11 comments
Open

How to represent logic expressions in RDF #2

sandhawke opened this issue Dec 17, 2018 · 11 comments

Comments

@sandhawke
Copy link
Collaborator

@sandhawke sandhawke commented Dec 17, 2018

N3 doesn't necessarily have to be able to fit into RDF, but it seems like a nice feature, and the original implementation in cwm did it.

This is related to #1, which is about trying to use RDF Datasets for this. This issue is more like aside from Datasets, how could we do it?

We could separate this into:

  • How to represent graphs
  • How to represent triples
  • How to represent variables
  • How to represent other logic constructs

... but for now, let's keep them together.

Here are some options:

  • Lists Everywhere. This was shown in #1. A graph is a list of triples, a triple is a list of subject, predicate, object. Like this:

    and

    • (:forall :x (implies ((:x a :Man)) ((:x a :Mortal))))
  • List of RDF Statements. Here, instead of representing triples as an (s p o) list, we use the somewhat archaic RDF Reification Vocabulary.

  • RIF-in-RDF. We could use RIF in RDF. I'm not aware of any implementations except one I did while writing the spec, and I don't know of anyone using it.

@sandhawke

This comment has been minimized.

Copy link
Collaborator Author

@sandhawke sandhawke commented Dec 17, 2018

One feature of a good solution here, I think, is that removing triples from the representation of the ruleset shouldn't give you additional entailments.

So this representation would be bad:

:r1 a :Rule;
:if [ :a :b :c ];
:if [ :d :e :f ];
:then [ :g :h :i ].

because if we delete the { :r1 :if [ [:d :e :f] } triple, the rule fires more easily, and suddenly { a b c } entails {g h i}.

That's why I use lists of triples in all the options above, instead of just a repeated property.

The motivation here is about logical monotonicity, but I'm not sure I have a rock solid case that we need to do it with N3

@doerthe

This comment has been minimized.

Copy link
Contributor

@doerthe doerthe commented Jan 14, 2019

I am not entirely sure whether I agree with this issue here (but I can be convinced, maybe I simply don't see the whole picture?).

I see a general problem with representing N3 in pure RDF because the RDF constructs already have fixed meanings and we cannot "hijack" them for other purposes.

Take rdf reification as an example:

Suppose we have the N3 construct:
:Wikipedia :says {:Melville :wrote :MobyDick}.

which we "translate" as:
:Wikipedia :says _:x.
_:x a rdf:Statement; rdf:subject :Melville; rdf:predicate :wrote; rdf:object :MobyDick.
then we have the problem that we have a blank node there. According to rdf semantics this blanknode just means that a statement exists, this is not the same as having the concrete statement. We do not have this problem if we simply extend the syntax of RDF as it is done in the N3 statement above.

I just want to illustrate here that sometimes it makes sense to also extend the syntax if you extend the semantics. Especially in a case like ours, where the logic is meant as an extension of RDF and the already existing constructs should have the same meaning in both logics.

@doerthe

This comment has been minimized.

Copy link
Contributor

@doerthe doerthe commented Jan 14, 2019

Putting my concerns from above aside, some comments on the above:

  • I think that we should not go for option 2 since reification is not covered in RDF semantics ([https://www.w3.org/TR/rdf11-mt/#whatnot](see here)).

  • I would definitely try to keep monotonicity.

  • I agree that lists are a better solution for the problem you mention than the blank node construct. The only problem I see (despite aesthetic concerns) is that in a graph the order of statements does not matter, {:a :b :c. :d :e :f} is (we have no semantics, so maybe should be?) the same as {:d :e :f. :a :b :c} while the lists ((:a :b :c) (:d :e :f)) and ((:d :e :f) (:a :b :c)) are clearly different. So, there would not be a 1-to-one mapping between a graph notation and its list representation. But maybe that is ok for us?

@sandhawke

This comment has been minimized.

Copy link
Collaborator Author

@sandhawke sandhawke commented Jan 14, 2019

sometimes it makes sense to also extend the syntax if you extend the semantics

Absolutely. That's how it's usually done, as I understand it. It's just that RDF is flexible enough that we have another option here, if we want to take it. So one answer to this issue, "How to represent logic expressions in RDF" is "Let's not bother. Too difficult, not worthwhile."

According to rdf semantics this blanknode just means that a statement exists, this is not the same as having the concrete statement.

I don't understand this. Can you give an example of how this issue might manifest?

So, there would not be a 1-to-one mapping between a graph notation and its list representation. But maybe that is ok for us?

Yeah, I don't think that's a big problem. Similarly, when you write a graph down with { ... } notation, you still have to write the triples in order; we just define that order as not significant.

@doerthe

This comment has been minimized.

Copy link
Contributor

@doerthe doerthe commented Jan 23, 2019

Sorry, that I answer that late. I spent some time thinking about the issue I raised and was not able to come up with a good example here and I think that the discussion should be based on examples (so I keep searching).

A problem with all the representations proposed is that they don't keep the scoping of blank nodes.

In

:Wikipedia :denies {:Melville :wrote _:y}.

The blank node is scoped inside the graph. The formulas translates to something like:
"Wikipedia denies that there is something Melville wrote."

But if you have a representation like for example with reification, you would have:

:Wikipedia :denies _:x. _:x a rdf:Statement; rdf:subject :Melville; rdf:predicate :wrote; rdf:object _:y.

which would then mean: "There exists something of which Wikipedia denies that Melville wrote it".
The blank node is scoped on top level and the two statements clearly have different meanings.

So, if we want to come to one of the representations you propose here, we should either change the scoping of blank nodes in N3 or also have a good mechanism to express explicit quantification in RDF so that we can use this mechanism instead in my example.
These two statements are different and if we want to go to a

@gkellogg

This comment has been minimized.

Copy link
Member

@gkellogg gkellogg commented Feb 26, 2019

I touch on my idea for doing this on page 5 of my Data Workshop Presentation. Basically, I propose creating a new resource type for Universally Quantified Variables (@univar) and how an implication might be stated in JSON-LD, although it could be expressed in any suitably extended RDF dataset format.

{
  "@context": {
    "@version": 1.1,
    "@base": "http://example.com/",
    "@vocab": "http://example.com/",
    "=>": {"@id": "http://www.w3.org/2000/10/swap/log#implies", "@container": "@graph"},
    "?x": {"@univar": true},
    "?y": {"@univar": true}
  },
  "@graph": [
    {"@id": "Julie", "parent": {"@id": "Suzie"}},
    {
      "@graph": {"@id": "?x", "parent": "?y"},
      "=>": {"@id": "?y", "child": "?x"}
    } 
  ]
}

In TriG, this might look like the following:

@prefix log: <http://www.w3.org/2000/10/swap/log#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<http://example.com/Julie> <http://example.com/parent> <http://example.com/Suzie> .

_:b0 log:implies _:b1 .
_:b0 { <http://example.com/?x> <http://example.com/parent> "?y" .}
_:b1 {<http://example.com/?y> <http://example.com/child> "?x" .}

Note that this requires RDF be updated so that the blank nodes used in the implication can denote the graphs they label, which is not strictly allowed in RDF 1.1, but seems to be an emerging practice, thanks largely to the way they're serialized in JSON-LD.

@wwaites

This comment has been minimized.

Copy link
Collaborator

@wwaites wwaites commented Feb 27, 2019

Suppose we have the N3 construct:
:Wikipedia :says {:Melville :wrote :MobyDick}.

which we "translate" as:
:Wikipedia :says _:x.
_:x a rdf:Statement; rdf:subject :Melville; rdf:predicate :wrote; rdf:object :MobyDick.
then we have the problem that we have a blank node there. According to rdf semantics this blanknode just means that a statement exists, this is not the same as having the concrete statement. We do not have this problem if we simply extend the syntax of RDF as it is done in the N3 statement above.

(paste from public-n3-dev list)

I wanted to point out that though this is true if you only consider the

_:x a rdf:Statemnet

part, it is quite possible to have ’says’ govern the interpretation. We can give a
semantics of ’says’ (and abusing the notation a little) are such that,

{ ?alice says ?x. ?x rdf:subject ?s; rdf:predicate ?p; rdf:object ?o } =>
?g { ?s ?p ?o }, ?alice says ?g.

So we can get back the original bag of statements, blank nodes are not a
problem here.

More generally we can choose the semantics by choosing what rules to
apply. This might be an important insight, that semantics should be as far as
possible encoded as rules which we can choose to apply or not. The reason
that RDF reification is hard to use is that its semantics are deliberatively
underspecified — it is nearly meaningless. But we can add statements which
use language that comes with rules to give it meaning. That’s not a problem.

I think we do need a syntax extension of some kind to talk about graphs
explicitly in antecedents and consequents.

I also really like the LISP proposal. It is easy to see in the rule that I give
above that we really want to be able to have nested scopes.

(added here, not on the mailing list)

Another consequence of choosing which rules to apply is that we need to be
able to talk about rules. An annotation on a graph might specify which way
it is intended to be interpreted, under which rules it should be understood.
To do this, we refer to a graph containing rules (which themselves refer to
graphs on the left and right hand side). Maybe these rules also have names
and other metadata. These references truly are to the rules, and not to
representations of the rules or documents containing the representations.

@doerthe

This comment has been minimized.

Copy link
Contributor

@doerthe doerthe commented Feb 28, 2019

@wwaites I agree that reification is not really a problem for our rules. The problem I was referring to was, if I remember correctly, that rdf reification is not really a good way to express N3 graphs in RDF given that there is RDF semantics.

@gkellogg I think your representation using TriG looks good, but the problem you mention is a very big one: TriG has no semantics and we therefore do not know whether the _:b0 stands for exactly the graph { <http://example.com/?x> <http://example.com/parent> "?y" .}

I hope you are right that there is a common preference for the interpretation of named graphs, but I do not really see it (yet?).

Now that I am on it, one additional question: why are ?x and ?y represented in different ways?

@gkellogg

This comment has been minimized.

Copy link
Member

@gkellogg gkellogg commented Mar 1, 2019

As was brought up on my Data Workshop slides, the notion that _:b0 might be a stand in for the named graph is problematic on a couple of levels, but I think it's something that will need to be tackled eventually. IMHO, translating N3 to TriG, it makes sense that :Wikipedia :says {:Melville :wrote :MobyDick}. would be saying the same thing as :Wikipedia :says _:b0 . _b0 {:Melville :wrote :MobyDick}., but RDF 1.1 semantics don't really allow this, as the name and named graph actually form a tuple (b,g)

Regarding using reification for representing the meaning of a quoted graph, it becomes an issue when that graph has more than one statement; the team submission uses a list of statements, but that has it's own issues.

That said, I think the notion that when a blank node is used to name a graph and also used as the subject or object of other statements, that those statements are generally understood to be about the graph (at least the graph specifically named by the blank node, if not another equivalent graph named otherwise).

Now that I am on it, one additional question: why are ?x and ?y represented in different ways?

{
  "@context": {
    "@base": "http://example.com/",
    "@vocab": "http://example.com/",
    "=>": {
      "@id": "http://www.w3.org/2000/10/swap/log#implies",
      "@container": "@graph"
    },
    "?x": {"@univar": true},
    "?y": {"@univar": true}
  },
  "@graph": [
    {"@id": "Julie", "parent": {"@id": "Suzie"}},
    {
      "@graph": {"@id": "?x", "parent": "?y"},
      "=>": {"@id": "?y", "child": "?x"}
    }
  ]
}

They are represented the same, in the antecedent, the subject is ?x and the value of "parent" is ?y, while in the consequent, the subject is ?y and the value of "child" is ?x. The @univar is a bit of hand-waving to create a JSON-LD syntax for describing resources which are variable.

@william-vw

This comment has been minimized.

Copy link
Contributor

@william-vw william-vw commented Sep 2, 2019

@sandhawke we were discussing this issue shortly during today's Skype meeting. I suppose there are two ways of looking at this:

  1. Use RDF for (agnostically) representing N3 documents. An RDF system would simply see the N3-in-RDF document as a collection of triples and not understand the semantics of the (RDF-encoded) N3 constructs. Importantly however, loading this N3-in-RDF document back into an N3-cognizant system would not lose any information compared to the original N3 document. This N3-in-RDF representation would likely become very ugly but could technically work (?)

  2. Convert certain N3 constructs (such as cited graphs) into more-or-less equivalent RDF constructs (such as named graphs, using reification). As mentioned by Doerthe in previous posts, this may be quite problematic since RDF named graphs and reification are semantically underspecified - different RDF systems seem to interpret named graphs and reified triples in greatly different ways.

Any thoughts?

@sandhawke

This comment has been minimized.

Copy link
Collaborator Author

@sandhawke sandhawke commented Sep 2, 2019

I don't think I have much to add to the intro to this issue. There is this RDF* effort going on now that might help with the named-graph problems, but I'm not following it closely. Personally, I'm using a non-RDF syntax these days to solve these problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.