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 handle relationships between agents? #12

Open
fosterlynn opened this issue Jan 28, 2015 · 21 comments
Open

How to handle relationships between agents? #12

fosterlynn opened this issue Jan 28, 2015 · 21 comments

Comments

@fosterlynn
Copy link

This is continuing the discussion today (2015-01-28) in the PLP hangout. @elf-pavlik provided these links:

http://patterns.dataincubator.org/book/qualified-relation.html
http://blog.schema.org/2014/06/introducing-role.html

Yes, these are both to the point, exactly.

In our object model in NRP which we were mostly using as starting point for openvocab, we have Agent, AgentRelationship, and AgentRelationshipRole. When we say Agent, we mean the superclass of Person or Organization. In no particular notation:

AgentRelationshipRole:
identifier = text
name = text
plural_name = text
association_behavior = child, member, customer, and some others....
description = text
label = text
inverse_label = text
AgentRelationship:
"An association between 2 agents, defining a role in relationship to each other."
is_associate = reference to an Agent
has_associate = reference to an Agent
relationship_type = reference to an AgentRelationshipRole
description = text
state = active, potential, inactive (and/or could be dates)

At some point @ahdinosaur asked could we put the ends of the relationship on the Agent itself (instead of using the AgentRelationship object). This has been at least partially implemented in openvocab I think. I don't know what might be "standard" for this type of situation in LOD land. I get one problem: If you have a separate class, and the data is distributed, how do you decide where the relationship lives?

Question: What is the best way to represent this concept in LOD? And I suppose, before that, do people agree with including something like this in PLP?

@elf-pavlik
Copy link
Member

@fosterlynn could you please provide two concrete examples in which you use this pattern?

@fosterlynn
Copy link
Author

@elf-pavlik

Agents: Enspiral, Mikey, Loomio
AgentRelationshipRoles: Child, Member

AgentRelationships:
Loomio is child of Enspiral (also can be stated Enspiral is parent of Loomio)
Mikey is member of Enspiral (also can be stated Enspiral has member Mikey)

If you would like them detailed out more in terms of properties, let me know.... or any other questions, just yell!

@elf-pavlik
Copy link
Member

{
  "@context": [
    "http://schema.org",
    { "superOrganization": { "@reverse": "subOrganization" } }
  ],
  "@graph": [
    {
      "@id": "https://enspiral.com/",
      "@type": "Organization",
      "name": "Enspiral",
      "member": [
        "https://www.loomio.org/u/g48DQjS5/mikey-the-human"
      ],
     "subOrganization": [
       "http://loomio.org"
     ]
    },
    {
      "@id": "https://www.loomio.org/u/g48DQjS5/mikey-the-human",
      "@type": "Person",
      "name": "Mikey",
      "memberOf": [
        "https://enspiral.com",
        "https://loomio.org"
      ]
    },
    {
      "@id": "https://loomio.org",
      "@type": "Organization",
      "name": "Loomio",
      "member": [
        "https://www.loomio.org/u/g48DQjS5/mikey-the-human"
      ],
      "superOrganization": [
        { "@id": "https://enspiral.com" }
      ]
    }
  ]
}

same on JSON-LD playground: http://tinyurl.com/nofsrlc

@fosterlynn
Copy link
Author

@elf-pavlik thanks!

Another one (to use an example where people want to define their own relationships). (Don't worry about defining this one out, just for discussion's sake.)

Agents: Driftless Herbal Network, Jane, Canyon Farm
AgentRelationshipRoles: Harvester, Grower, Administrator, Contact
AgentRelationships:
Canyon Farm is grower for Driftless Herbal Network
Jane is harvester for Driftless Herbal Network
Jane is administrator for Driftless Herbal Network
Jane is contact for Canyon Farm (interestingly, this only is within the context of Driftless Herbal Network, another data point that Mikey identified last week in his work on the Enspiral directory)

@ahdinosaur
Copy link

@elf-pavlik hehe, awesome! 🌷

in our case, we want more than just who is a member, we want information about the membership itself: when the person joined, whether they are active or not, what type of membership they have (member vs contributor). plus, we also have more relationships than just memberships, most exciting at the moment is our stewardship relationships (which is a great way we've learned to do networked human resources where each person in the group is a point of contact for another person in the group and meets with them once a month to check in about their life, see this and this for more info), which as @fosterlynn mentioned is not only between two people but also is only within the context of a group.

here's the data so far in our "Enspiral directory": https://github.com/holodex/app/tree/master/data. an example API resource is up at http://holodex.enspiral.info/api/groups/enspiral-craftworks. this is all a work in progress (super pre-alpha), so missing a lot, but i hope it's helpful and i'd be happy to explain anything that is confusing or you want to know more about. 😋

@fosterlynn
Copy link
Author

@ahdinosaur super interesting, I love that you're working on this in a real situation!

Now that I've seen the data, I understand more what you meant by keeping the ends of the relationships separate. It is actually more like having an entry for each direction of a relationship type. Does it have to do with an agent only having the basis to refer to the relationship from its perspective?

@ahdinosaur
Copy link

@fosterlynn i'm glad being able to see the data is helpful. (hacked up YAML database for the win 🐱).

yup, you got it. the purpose is for each agent to be in control of their own data and that means they must control their perspective of the relationship, which leads to some nice properties:

  • one cannot create a bidirectional relationship without consent from both parties
  • in the future we can support those parties being on separate servers without issue

an open question is about conflicting meta-information ("the group says you joined at this time, but you say you joined at this other time"), but i reckon life is relative so why not our data. anyways, it's an experiment. 🔬

@elf-pavlik
Copy link
Member

one cannot create a bidirectional relationship without consent from both parties

for distributed scenario, please check out my recent email to Credentials CG list

@ahdinosaur @fosterlynn please also check out two videos embedded on http://opencreds.org/

I'll check your Enspiral examples and reply with some Role examples tomorrow!

@ahdinosaur
Copy link

thanks @elf-pavlik 😸

@ahdinosaur
Copy link

as a cleaned up example, here's what we have right now:

{
  "@graph": [
    {
      "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks",
      "@type": "Group",
      "name": "Enspiral Craftworks",
      "image": "http://i.imgur.com/BFmaOxi.png",
      "relationships": [
        {
          "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-simon"
        },
        {
          "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-mikey"
        }
      ]
    },
    {
      "@type": "Person",
      "name": "Mikey",
      "handle": "ahdinosaur",
      "url": "http://dinosaur.is",
      "image": "http://gravatar.com/avatar/22ee24b84d0a2a9446fc9c0fe0652c46?s=512&d=identicon",
      "relationships": [
        {
          "@id": "http://holodex.enspiral.info/api/relationships/mikey-member-enspiral-craftworks"
        },
        {
          "@id": "http://holodex.enspiral.info/api/relationships/mikey-mentor-simon"
        }
      ],
      "@id": "http://holodex.enspiral.info/api/people/mikey"
    },
    {
      "@type": "Person",
      "name": "Simon",
      "handle": "simontegg",
      "image": "https://avatars0.githubusercontent.com/u/1574732?v=2&s=460",
      "relationships": [
        {
          "@id": "http://holodex.enspiral.info/api/relationships/simon-member-enspiral-craftworks"
        },
        {
          "@id": "http://holodex.enspiral.info/api/relationships/simon-mentee-mikey"
        }
      ],
      "@id": "http://holodex.enspiral.info/api/people/simon"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/group"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/people/simon"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/simon-member-enspiral-craftworks"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-simon"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/group"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/people/mikey"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/mikey-member-enspiral-craftworks"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-mikey"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/member"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/people/simon"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-simon"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/simon-member-enspiral-craftworks"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/member"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/people/mikey"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/enspiral-craftworks-group-mikey"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/mikey-member-enspiral-craftworks"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentee"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/people/simon"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/people/mikey"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/mikey-mentor-simon"
      },
      "context": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/simon-mentee-mikey"
    },
    {
      "@type": "Relationship",
      "relationshipType": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentor"
      },
      "is": {
        "@id": "http://holodex.enspiral.info/api/people/mikey"
      },
      "has": {
        "@id": "http://holodex.enspiral.info/api/people/simon"
      },
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationships/simon-mentee-mikey"
      },
      "context": {
        "@id": "http://holodex.enspiral.info/api/groups/enspiral-craftworks"
      },
      "@id": "http://holodex.enspiral.info/api/relationships/mikey-mentor-simon"
    },
    {
      "@type": "RelationshipType",
      "name": "group",
      "pluralName": "groups",
      "description": "A group has constituent members",
      "label": "is group of",
      "inverseLabel": "has group",
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/member"
      },
      "@id": "http://holodex.enspiral.info/api/relationshipTypes/group"
    },
    {
      "@type": "RelationshipType",
      "name": "member",
      "pluralName": "members",
      "description": "A member is part of a group",
      "label": "is member of",
      "inverseLabel": "has member",
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/group"
      },
      "@id": "http://holodex.enspiral.info/api/relationshipTypes/member"
    },
    {
      "@type": "RelationshipType",
      "name": "mentee",
      "pluralName": "mentees",
      "description": "A mentee is mentored by a mentor.",
      "label": "is mentee of",
      "inverseLabel": "has mentee",
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentor"
      },
      "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentee"
    },
    {
      "@type": "RelationshipType",
      "name": "mentor",
      "pluralName": "mentors",
      "description": "A mentor mentors a mentee.",
      "label": "is mentor of",
      "inverseLabel": "has mentor",
      "symmetric": {
        "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentee"
      },
      "@id": "http://holodex.enspiral.info/api/relationshipTypes/mentor"
    }
  ]
}

i'm wondering about how to make these into a more credential-like form. the examples linked to are one authority agent making a claim about another agent, so would each side make a symmetric claim (A says that "A is X of B" and B says that "B is X' of A") or is there only one claim being made with two signatures (both A and B say that "A is X of B")?

@elf-pavlik
Copy link
Member

@ahdinosaur let's see - "using schema:Role with inverse properties?"
https://lists.w3.org/Archives/Public/public-vocabs/2015Mar/0089.html

@fosterlynn
Copy link
Author

See also parallel discussions going on here:
valueflows/agent#1 (roles)
valueflows/agent#2 (types of relationships)

@fosterlynn
Copy link
Author

@elf-pavlik OK, here is my first attempt (very newbie, sorry for syntax errors, etc!) to sketch the context for agent relationships and relationship types. Lots of questions. Some of them how to define something, like values to a code. Lots of questions how to find and decide what vocab to use for existing concepts. @ahdinosaur you'll notice a few changes to what you have in the ovn vocab and holodex, also some additions based on recent discussions. All to be worked out....

relationshiptype

agentrelationship

Oops, need to add startDate and endDate to AgentRelationship.

@elf-pavlik
Copy link
Member

Please take a look at this gist https://gist.github.com/elf-pavlik/029917ccc535e889f693 which we discuss in 1EdTech/openbadges-specification#32

This week I will try to write similar but with MembershipCredential instead of AchievementCredential. Then we can also discuss mutual credentials!

EDIT: I suggested such use case here https://lists.w3.org/Archives/Public/public-credentials/2015Apr/0006.html

@elf-pavlik
Copy link
Member

@ahdinosaur have you considered

@prefix : <http://example.net/ns#>
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

:Relationship a owl:Class .

:relationship a owl:ObjectProperty ;
  rdfs:domain foaf:Agent ;
  rdfs:range :Relationship .

:Mentorship rdfs:subClassOf :Relationship .

:mentor a owl:ObjectProperty ;
  rdfs:label "mentor"@en ;
  rdfs:domain [
    a owl:Class ;
    owl:unionOf ( foaf:Person :Relationship )
  ]  ;
  rdfs:range [
    a owl:Class ;
    owl:unionOf ( foaf:Person :Relationship )
  ]  .

To my understanding linked data best practices discourage plural names for properties (so relationship not relationships) as well as defining inverse properties on vocabulary level. Instead of doing that JSON-LD context would preferably define

{
  "@context": {
    "mentee": { "@reverse": "mentor", "@type": "@id" }
  }
}

www.w3.org/TR/json-ld/#reverse-properties

{
      "@context": { ... },
      "@id": "http://holodex.enspiral.info/api/relationships/mikey-mentor-simon",
      "@type": "Mentorship",
      "mentor": "http://holodex.enspiral.info/api/people/simon",
      "mentee": "http://holodex.enspiral.info/api/people/mikey",
      "context": "http://holodex.enspiral.info/api/groups/enspiral-craftworks",
      "sameAs": "http://holodex.enspiral.info/api/relationships/simon-mentee-mikey"
}

but you can also use mentor/mentee as not Qualified Relaton

{
      "@context": { ... },
      "@id": "http://holodex.enspiral.info/api/people/mikey",
      "@type": "Person",
      "name": "Mikey",
      "mentor": "http://holodex.enspiral.info/api/people/simon",
}
{
      "@context": { ... },
      "@id": "http://holodex.enspiral.info/api/people/simon",
      "@type": "Person",
      "name": "Simon",
      "mentee": "http://holodex.enspiral.info/api/people/mikey",
}

@ahdinosaur
Copy link

@elf-pavlik thanks for the resources. 😸 i'm gonna need some time to chew on what you've shared and also give an update on our current data structure for holodex.

@elf-pavlik
Copy link
Member

@ahdinosaur maybe you could setup http://linkeddatafragments.org/software/ (server + client) so that we always test data you model with some real world queries!

@fosterlynn
Copy link
Author

@elf-pavlik Question: It looks like both of your examples (subclass and like a property) imply that the relationship types (e.g. mentor) have to be defined somewhere in the vocabulary itself. Does this preclude or make it harder to allow user definition of relationship types? Or can people just throw them out there as needed? Any issues with collision of same named relationship types if so?

@elf-pavlik
Copy link
Member

@fosterlynn nothing requires that terms used for example as owl:Class, owl:ObjectProperty or owl:DataProperty come from a static vocabulary. One can publish them using some dynamic CMS like system and it will work just fine. When it comes to name collisions, everything has its own namespace. Already you can find examples where foaf:name doesn't have exactly the same definition as schema:name. On the other side, Linked Data comes handy when you want to integrate data from multiple sources. In such case it can come handy if people reuse existing terms instead recreating new ones for the same concepts. Of course you can map them with constructs like rdfs:subclassOf, owl:equivalentClass, rdfs:subPropertyOf, owl:equivalentProperty but then you need to use reasoning (inference) which may raise a bar in possibly quite significant way.
BTW please take a look at very recent W3C Social IG ISSUE-4: management of 'living' vocabularies similar to microformats.org and schema.org

@elf-pavlik
Copy link
Member

@fosterlynn @ahdinosaur please also publish context you work on directly on github and test them on http://json-ld.org/playground/ using http://rawgit.com/ proxy for links (to avoid CORS issues) e.g. http://tinyurl.com/me47rs8 (both context and data served directly from github repos via rawgit!)

@elf-pavlik
Copy link
Member

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

3 participants