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

Model for 2 directions of a relationship #11

Closed
fosterlynn opened this issue Sep 9, 2015 · 34 comments
Closed

Model for 2 directions of a relationship #11

fosterlynn opened this issue Sep 9, 2015 · 34 comments

Comments

@fosterlynn
Copy link
Contributor

In issue #9 we discussed the obverse relationship and obverse relationship type, see that for the history of this discussion. I'm starting a new issue so we can continue to discuss while finalizing the minimum core Agent model and JSON-LD recommendations.

My concern: It really is only one relationship in many cases. Perhaps Friend is an exception? But in all the use cases we are dealing with in a value network, both have to agree for the relationship to exist, and the relationship is merely recorded. Activities could be recorded if wanted, such as Request to Join and Request Approved, or something like that. Or if it is a question of verification, some type of credentials could be added to the model to verify from both direction. But these things would relate to the relationship, not be a reverse direction relationship.

@ahdinosaur Thoughts?

@ahdinosaur
Copy link
Member

we're gonna try out the vocab i proposed in #10 with bi-directional relationships, i'll report back on how it goes.

@fosterlynn
Copy link
Contributor Author

we're gonna try out the vocab i proposed in #10 with bi-directional relationships, i'll report back on how it goes.

@ahdinosaur sounds good.

@ahdinosaur
Copy link
Member

although to be fair, our data only records one direction of the relationship, so i'm actually not sure what we'll do yet. i'm thinking either automatically generate the reverse or have a way to infer the obverse relationship, as i do think many relationshipTypes do make sense to have an obverse (especially to specify obverse labels, but also as a way to link in with query labels).

@bhaugen
Copy link
Contributor

bhaugen commented Sep 9, 2015

@ahdinosaur
Copy link
Member

@bhaugen corresponding, from the other side, symmetric, counterpart, ... idk.

i wasn't sure what word to pick, so i went with 'obverse'. better suggestions welcome, it might be easiest to go with 'reverse' which is an existing term, but it didn't feel semantically adequate and i'd rather alias to that later on.

@bhaugen
Copy link
Contributor

bhaugen commented Sep 9, 2015

corresponding, from the other side, symmetric, counterpart

That does not seem to be its dictionary definition. I had never encountered the word before, which is why I looked it up.

@ahdinosaur
Copy link
Member

ah i must have been under a wrong impression. what's a better word then? i'm not tied to obverse.

@fosterlynn
Copy link
Contributor Author

@ahdinosaur I'm wondering if the reason you are thinking of Relationship as 2 instances, one for each direction, is that you are thinking the 2 agents might reside on different platforms and possibly different servers? So from the perspective of the target (or object) agent, the relationship would be reversed? And the relationship might exist in duplicate anyhow, depending on the caching of that info.

@ahdinosaur
Copy link
Member

@fosterlynn nah, i've realized having multiples sources of truth is separate from bi-directional relationships.

the reason for bi-directional relationships, in my mind, is for semantic reasons. for a relationship like "mentors", it's important to be able to answer "what is the relationship between the mentee and the mentor" (i.e. "is mentored by")? i'm not saying we necessarily need to store separate objects for each direction, but i do think we should at least have RelationshipTypes in each direction and from there be able to infer Relationships in each direction.

our approach in Holodex so far has been to make bi-directional RelationshipTypes only when we feel the relationship is actually bi-directional (e.g. membership), so maybe we'll continue with that, but it's an open question as to which relationships needs two directions.

@ahdinosaur
Copy link
Member

although, if we look at @elf-pavlik's most recent example, even a uni-directional relationship like 'follows' has reverse RelationshipType (denoted by owl:inverseOf), so maybe as a rule every RelationshipType has a reverse.

@ahdinosaur
Copy link
Member

@elf-pavlik
Copy link
Member

Once again, why do you need to create sub classes of Relationship (rdfs:Class/owl:Class)?
Using instance of rdf:Property and swapping values of subject and object in a qualified relation (modeled after reification) seems to do the job to handle both ways.
https://github.com/w3c-social/social-vocab/wiki/Verbs---owl:Class-vs.-rdf:Property#qualified-relations
If we need to define labels, let's maybe work with concrete examples of member and mentor examples in JSON-LD and iterate on them?

Let's also make sure that we alwasy distinguish concept of classes in Object Oriented programming and classes in RDFS/OWL

@fosterlynn
Copy link
Contributor Author

although, if we look at @elf-pavlik's most recent example, even a uni-directional relationship like 'follows' has reverse RelationshipType (denoted by owl:inverseOf), so maybe as a rule every RelationshipType has a reverse.

Or more precisely, every relationship type label has a reverse label? This makes sense to me, because even in a one way relationship like follows, you might want to display all the followers of someone.

@fosterlynn
Copy link
Contributor Author

If we need to define labels, let's maybe work with concrete examples of member and mentor examples in JSON-LD and iterate on them?

Sounds good. This should flesh out where we might want 2 things (objects, whatever).

Once again, why do you need to create sub classes of Relationship (rdfs:Class/owl:Class)?

I don't think anyone is advocating for subclasses, as far as I can tell? Ha ha, remember all that early discussion on type classes vs subclasses for proliferating user-defined things? I'm glad to find a way we can do it without subclasses. Although I freely admit I do not get all the LOD think yet! Still learning!

@ahdinosaur
Copy link
Member

Once again, why do you need to create sub classes of Relationship (rdfs:Class/owl:Class)?

i'm not very learned about rdf or owl, so i'm mostly thinking in terms of logical models independent of how to formalize them with existing linked data specs. in my limited understanding, it seems like what you're suggesting is exactly our intention.

If we need to define labels, let's maybe work with concrete examples of member and mentor examples in JSON-LD and iterate on them?

here's an attempt to model in JSON-LD the relationship of @fosterlynn mentoring me within OpenVocab:

{
  "@context": {
    "open": "http://openvocab.is/#",
    "schema": "http://schema.org/"
    "ex": "http://holodex.example.com/api/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "owl": "http://www.w3.org/2002/07/owl#"
  },
  "@graph": [{
    "@id": "ex:agentTypes/agent",
    "@type": "AgentType"
  }, {
    "@id": "ex:agentTypes/person",
    "@type": "AgentType"
  }, {
    "@id": "ex:agentTypes/group",
    "@type": "AgentType"
  }, {
    "@id": "ex:relationshipTypes/mentors",
    "@type": "RelationshipType",
    "schema:name": "mentors",
    "open:sourceAgentType": "ex:agentTypes/person",
    "open:targetAgentType": "ex:agentTypes/person",
    "open:contextAgentType": "ex:agentTypes/group",
    "rdfs:label": "{source} mentors {target}",
    "owl:inverseOf": {
      "rdfs:label": "{target} is mentored by {source}"
    }
  }, {
    "@id": "ex:agents/mikey",
    "@type": "Agent",
    "open:agentType": "ex:agentTypes/person",
    "schema:name": "Mikey"
  }, {
    "@id": "ex:agents/lynn",
    "@type": "Agent",
    "open:agentType": "ex:agentTypes/person",
    "schema:name": "Lynn"
  }, {
    "@id": "ex:agents/openvocab",
    "@type": "Agent",
    "open:agentType": "ex:agentTypes/group",
    "schema:name": "OpenVocab"
  }, {
    "@id": "ex:relationships/b4dc56a7-2e07-411b-9bb7-794ed6ccb516",
    "@type": "Relationship",
    "open:relationshipType": "ex:relationshipTypes/mentors",
    "open:sourceAgent": "ex:agents/lynn",
    "open:targetAgent": "ex:agents/mikey",
    "open:contextAgent": "ex:agents/openvocab"
  }]
}

@ahdinosaur
Copy link
Member

here's a another attempt to model in JSON-LD the relationship of me as a member of Enspiral:

{
  "@context": {
    "open": "http://openvocab.is/#",
    "schema": "http://schema.org/"
    "ex": "http://holodex.example.com/api/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "owl": "http://www.w3.org/2002/07/owl#"
  },
  "@graph": [{
    "@id": "ex:agentTypes/agent",
    "@type": "AgentType"
  }, {
    "@id": "ex:agentTypes/person",
    "@type": "AgentType"
  }, {
    "@id": "ex:agentTypes/group",
    "@type": "AgentType"
  }, {
    "@id": "ex:relationshipTypes/is-member-of",
    "@type": "RelationshipType",
    "schema:name": "is member of",
    "open:sourceAgentType": "ex:agentTypes/agent",
    "open:targetAgentType": "ex:agentTypes/group",
    "rdfs:label": "{source} is member of {target}",
    "owl:inverseOf": "ex:relationshipTypes/has-member"
  }, {
    "@id": "ex:relationshipTypes/has-member",
    "@type": "RelationshipType",
    "schema:name": "has member",
    "open:sourceAgentType": "ex:agentTypes/group",
    "open:targetAgentType": "ex:agentTypes/agent",
    "rdfs:label": "{source} has member {target}",
    "owl:inverseOf": "ex:relationshipTypes/is-member-of"
  }, {
    "@id": "ex:agents/mikey",
    "@type": "Agent",
    "open:agentType": "ex:agentTypes/person",
    "schema:name": "Mikey"
  }, {
    "@id": "ex:agents/enspiral",
    "@type": "Agent",
    "open:agentType": "ex:agentTypes/group",
    "schema:name": "Enspiral"
  }, {
    "@id": "ex:relationships/8604bd82-a4b7-4aba-ba16-3c4917e7df48",
    "@type": "Relationship",
    "open:relationshipType": "ex:relationshipTypes/is-member-of",
    "open:sourceAgent": "ex:agents/mikey",
    "open:targetAgent": "ex:agents/enspiral"
  }]
}

@elf-pavlik
Copy link
Member

thanks @ahdinosaur! what do you think about

{
  "@context": {
    "open": "http://openvocab.is/#",
    "schema": "http://schema.org/",
    "as": "http://www.w3.org/ns/activitystreams",
    "foaf": "http://xmlns.com/foaf/0.1/",
    "ex": "http://holodex.example.com/api/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "owl": "http://www.w3.org/2002/07/owl#",
    "rdfs:label": { "@container": "@language" },
    "open:labelTemplate": { "@container": "@language" }
  },
  "@graph": [{
    "@id": "open:mentor",
    "@type": "rdf:Property",
    "rdfs:label": {
      "en": "mentors",
     },
    "open:labelTemplate": {
      "en": "{subject} mentors {object}",
     },
    "owl:inverseOf": {
      "rdfs:label": {
        "en": "is mentored by",
      },
      "open:labelTemplate": {
        "en": "{subject} is mentored by {object}"
      }
    }
  }, {
    "@id": "schema:member",
    "@type": "rdf:Property",
    "rdfs:label": {
      "en": "has member",
     },
    "open:labelTemplate": {
      "en": "{subject} has member {object}",
     },
    "owl:inverseOf": {
      "rdfs:label": {
        "en": "is member of",
      },
      "open:labelTemplate": {
        "en": "{subject} is member of {object}"
      }
    }
  }, {
    "@id": "ex:agents/mikey",
    "@type": ["foaf:Person", "foaf:Agent"],
    "schema:name": "Mikey"
  }, {
    "@id": "ex:agents/lynn",
    "@type": ["foaf:Person", "foaf:Agent"],
    "schema:name": "Lynn"
  }, {
    "@id": "ex:agents/openvocab",
    "@type": ["foaf:Group", "foaf:Agent"],
    "schema:name": "OpenVocab"
  }, {
    "@id": "ex:agents/enspiral",
    "@type": ["foaf:Group", "foaf:Agent"],
    "schema:name": "Enspiral"
  }, {
    "@id": "ex:relationships/b4dc56a7-2e07-411b-9bb7-794ed6ccb516",
    "@type": "as:Relationship",
    "as:relationship": "open:mentor",
    "as:subject": "ex:agents/lynn",
    "as:object": "ex:agents/mikey",
    "open:relationshipContext": "ex:agents/openvocab"
  }, {
    "@id": "ex:relationships/8604bd82-a4b7-4aba-ba16-3c4917e7df48",
    "@type": "as:Relationship",
    "as:relationship": "schema:member",
    "as:subject": "ex:agents/enspiral",
    "as:object": "ex:agents/mikey"
  } ]
}

reason for using blank nodes and not giving URI for reverse/inverse properties:
http://richard.cyganiak.de/blog/2006/06/an-rdf-design-pattern-inverse-property-labels/

@ahdinosaur
Copy link
Member

nice work @elf-pavlik. 😄 it's good to know that our logical model is such that we'd easily be able to translate to that format if we want to output data compatible with these LOD specs. thanks heaps for your help with this, i'd have no idea how to interface with these LOD specs.

i notice the change back to use foaf:Agent and foaf:Person, so worth mentioning that #9 (comment) is still true,

i've come back to the position that we should do what is best rather than what is most common, so in this case i think flexible AgentType objects are more powerful than restricted subclasses. being compatible with existing LOD is not a huge priority for me.

so the translation might lose some information but that's fine. that being said using AgentType is an experiment based on intuition, we have yet to see how it'll play out in practice.

@elf-pavlik
Copy link
Member

@ahdinosaur we had discussion with @fosterlynn that one can define in very flexible way (eg. via CMS style interface) new instances of rdfs:Class and rdf:Property. I see impression of needing to 'restrict' to existing established vocabularies as misunderstanding of how Linked Data works.

No one stops you from using

 {
    "@id": "ex:agents/openvocab",
    "@type": [
      "foaf:Group",
      "foaf:Agent",
      "ex:agentTypes/group",
      "ex:snowflakeTypes/486739ba-c497-4aff-8c55-509322d07ce0"],
    "schema:name": "OpenVocab"
  }

@ahdinosaur
Copy link
Member

@elf-pavlik ah sweet. is it possible for you to give an example AgentType defined in this way (or anything that could be used as a @type)? i'm aware that anyone can make up their own vocabs, but i'm not learned of the format and how to programmatically generate compatible classes / properties from our data. again, this is super helpful, thanks for educating us, i'm sorry for being so jaded.

@elf-pavlik
Copy link
Member

@ahdinosaur you can start by simply assigning for each property and class a HTTP URI in namespace which you control. Even if you to get started just respond with HTTP 404 it doesn't matter, you can use those terms in your data already!

{
  "@context": {
    "ex": "http://circus.example/ns/"
  },
  "@graph": [
    {
      "@id": "ex:roles/juggler"
    },
    {
      "@id": "ex:relationships/impersonate"
    }
  ]
}

Later you can provide HTML(+RDFa) / JSON-LD / Turtle etc. definitions with some more useful information.

{
  "@context": {
    "ex": "http://circus.example/ns/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "owl": "http://www.w3.org/2002/07/owl#",
    "foaf": "http://xmlns.com/foaf/0.1/",
    "rdfs:label": { "@container": "@language" }
  },
  "@graph": [
    {
      "@id": "ex:roles/juggler",
      "@type": "rdfs:Class",
      "rdfs:subClassOf": "foaf:Agent",
      "rdfs:label": {
        "en": "Juggler"
      },
    },
    {
      "@id": "ex:relationships/impersonate",
      "@type": "rdf:Propery",
      "rdfs:label": {
        "en": "impersonates"
      },
      "owl:inverseOf": {
        "rdfs:label": {
          "en": "impersonated by"
        }
      }
    }
  ]
}

But once again YOU DO NOT NEED IT just to start using classes and properties uniquely identified by those URIs in your data! We don't deal with Object Oriented Programming classes and properties here + preferably we keep in mind https://en.wikipedia.org/wiki/Open-world_assumption

@ahdinosaur
Copy link
Member

@elf-pavlik makes sense, rdfs:Class and rdf:Property seem very generally useful, cheers for sharing how to use them.

@fosterlynn
Copy link
Contributor Author

@elf-pavlik @ahdinosaur Great discussion, thanks to both of you for getting really concrete on this!! 😄

@fosterlynn
Copy link
Contributor Author

@elf-pavlik @ahdinosaur I'm doing research on how other vocabs handle agent relationships. I'm now leaning towards separating the directions, based on getting more of a feel for how it tends to be done. And, I think you guys lean that way too so also happy to move toward agreement! I think this would apply to the "relationship type" and the relationship. The relationship would be how elf has suggested, just reverse the subject and object and use the inverse relationship type.

Some nice examples:
http://vocab.org/relationship/.html (this is the purl.org stuff)
http://d-nb.info/standards/elementset/agrelon.owl# (agent relationship ontology, well well!)

A note: Some relationships define their inverse (Mikey's old obverse - now renamed - relationship on his diagram). Some relationships say they are symmetrical. Maybe this would be hard to implement for user defined? Or maybe not, like in NRP if the label and inverse label are the same, it is symmetrical.

@ahdinosaur
Copy link
Member

A note: Some relationships define their inverse (Mikey's old obverse - now renamed - relationship on his diagram). Some relationships say they are symmetrical. Maybe this would be hard to implement for user defined? Or maybe not, like in NRP if the label and inverse label are the same, it is symmetrical.

maybe if the relationship type is symmetrical then owl:inverseOf points to itself?

@elf-pavlik
Copy link
Member

A note: Some relationships define their inverse (Mikey's old obverse - now renamed - relationship on his diagram).

I have impression that we mix class definition with instances and reified statements (which we can further qualify)

For different types(?) of relationships we define as an instance of rdf:Property (eg. role:member) which we can use as label for an edge.

direct relation

Such labeled edge (~ instance of 'direction relationship', labeled with instance of rdf:Property) we can reify and use as value of relationship (let's rename it to 'property' to avoid even more confusions #46 ? ) when we want to qualify this particular edge and make it an instance of (Qualified)Relationship.

relationship

We can use owl:inverseOf to formalize that two instances of rdf:Property act as inverse relationships e.g.

{
  "@context": [
    "https://w3id.org/valueflows/",
    { "org": "http://www.w3.org/ns/org#" }
  ],
  "@id": "org:isMemberOf",
  "owl:inverseOf": "org:hasMember" 
}

But the obverse property, to my understanding addresses #7 and links two instances of (Qualified)Relationships. In most likely same way as mirror label used in this diagram

likes

please compare with use of owl:inverseOf in this one

member-inverse-a

In short, we can use owl:inverseOf to formalize for example role:friend as symmetric relationship. But we would use proposed oberese or mirror to link to independently published statements, where in each a person expresses having relationship of type (property) friend with the other. Same with groups, I gave example here of using owl:inverseOf in cases where vocab defines two separate directions sharing exactly same semantics. But an organization and a person will publish independently #7 two statements where in each one of the sides expresses having such relationship with the other side.

@ahdinosaur
Copy link
Member

@elf-pavlik so to recap my understanding: you think we should have two separate properties:

  1. owl:inverseOf to be used to specify the inverse of a RelationshipType
  2. vf:mirror to be used to specify the inverse of a Relationship

and the reason for separating these is:

I have impression that we mix class definition with instances and reified statements

?


i suppose that makes sense. i've been using the same property (obverse, inverse, reverse, ...) for both relationship type (class) or instance, since i like to reduce the number of concepts in my mind and whether it's a relationship type (class) or instance doesn't seem to change the general concept of it being the inverse, although maybe it does.

@elf-pavlik
Copy link
Member

formal definition of owl:inverseOf (in turtle syntax copied from http://www.w3.org/2002/07/owl.ttl )

owl:inverseOf a rdf:Property ;
     rdfs:label "inverseOf" ;
     rdfs:comment "The property that determines that two given properties are inverse." ;
     rdfs:domain owl:ObjectProperty ;
     rdfs:isDefinedBy <http://www.w3.org/2002/07/owl#> ;
     rdfs:range owl:ObjectProperty .

If one uses it on an instance of vf:Relationship, that would imply (when running RDFS reasoner which can infer based on rdfs:domain) that it's also an instance of owl:ObjectProperty (itself rdfs:subClassOf rdf:Property as defined in same .ttl file), which I don't think we intend.

To make statements about relation(ship) between two instances of vf:Relationship (or vf:QualifiedRelation to avoid overloading relationship term). We need to define (or find already defined elsewhere) different instance of rdf:Propery - vf:mirror or vf:obverse or vf:sameStatementButMadeByAnotherParty/vf:equivalentStatementButMadeByAnotherParty (same/equivalent depending on resolution of valueflows/valueflows#52) ...

suppose that makes sense. i've been using the same property (obverse, inverse, reverse, ...) for both relationship type (class) or instance, since i like to reduce the number of concepts in my mind and whether it's a relationship type (class) or instance doesn't seem to change the general concept of it being the inverse, although maybe it does.

I think we will need to keep discussing those issues, as well as continue our conversation about mixing types with instances. I believe best if we do it based on .... concrete, real world examples, which we can illustrate in non ambiguous way with colorful drawings of directed labeled graphs and serialize in machine readable way as JSON-LD

@fosterlynn
Copy link
Contributor Author

@elf-pavlik so to recap my understanding: you think we should have two separate properties:
owl:inverseOf to be used to specify the inverse of a RelationshipType
vf:mirror to be used to specify the inverse of a Relationship

Actually, I didn't get that out of it, @ahdinosaur , although you may well be right! I got that mirror would handle the situation of different assertions of something, which may or may not match - the old multiple sources of truth thing. @elf-pavlik you'll have to clarify for us.

IF it is the multiple sources of truth, I'd suggest we leave that out for now. I think it can be added on later without disruption to the vocab, is that true?

If it is not the multiple sources of truth, and nobody is suggestion handling multiple sources of truth, then please disregard this comment!

@elf-pavlik
Copy link
Member

I think @ahdinosaur understood clearly what I tried to explain

IF it is the multiple sources of truth, I'd suggest we leave that out for now. I think it can be added on later without disruption to the vocab, is that true?

Yeah, we can wait with that a bit. I will just add to data I publish relation from me to enspiral network as role:boss, this will give us chance to look at how apps could at some point weed out such one sided claims.
https://github.com/hackers4peace/rdf-for-object-oriented-heads#anyone-can-say-anything-about-anything

@fosterlynn
Copy link
Contributor Author

@elf-pavlik role:boss, why not? Somebody's gotta do it.....

Seriously though, I don't get the "role:" thing. I get it in the agent - resource relationship (conceptually more the right word), but not here really.

Is that related to the list of roles you defined? (Can't find the link, maybe in w3id?)

@elf-pavlik
Copy link
Member

@fosterlynn I just used it as playful example of someone stating nonsense, and while we integrate data from multiple sources from all over the web, we will need a way to automatically verify such claims. At the same time I agree that we better focus on other things first... (BTW second link on http://prefix.cc/role )

@ahdinosaur
Copy link
Member

@almereyda
Copy link
Member

We have moved the ValueFlows organization from GitHub to https://lab.allmende.io/valueflows.

This issue has been closed here, and all further discussion on this issue can be done at

https://lab.allmende.io/valueflows/agent/-/issues/11.

If you have not done so, you are very welcome to register at https://lab.allmende.io and join the ValueFlows organization there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants