aehrc / snorocket

The Snorocket Description Logic classifier for EL++ with concrete domains support
Apache License 2.0
22 stars 6 forks source link

Modeling Role Groups in the Snorocket API #4

Closed davetrig closed 8 years ago

davetrig commented 8 years ago

Could someone point me to a piece of documentation or code example explaining or demonstrating how to represent a role group in an axiom in the Snorocket API? The example code mentions role groups, but I don't see any specific examples. Thanks!

ametke commented 8 years ago

Hi davetrig,

A role group is just an existential whose property is a named role with a specific SNOMED id (currently 609096000) and whose filler is a conjunction. For example, if you wanted to role group A and B you would do something like this:

Concept a = Factory.createNamedConcept("a");
Concept b = Factory.createNamedConcept("b");
Role roleGroup = Factory.createNamedRole("609096000");

Concept conj = Factory.createConjunction(a, b);
Concept ex = Factory.createExistential((NamedRole) roleGroup, conj);
davetrig commented 8 years ago

Thank you so much for your quick response. I assume that the filler could also be the conjunction of two existentials? Here's my example:

Given these concepts in this defined hierarchy:

{ROOT}
  {Chemical}
    {ChemicalViewedFunctionally}
    {StructurallyViewedChemical}
      {InorganicChemical}
  {Concept1}
  {Concept2}

and one role, basicRole, where:

Concept1 ≡ ROOT ⊓ ∃basicRole.ChemicalViewedFunctionally
Concept2 ⊑ ROOT ⊓ ∃roleGroup.(
    ∃basicRole.ChemicalViewedFunctionally ⊓
    ∃basicRole.InorganicChemical
)

I would expect Concept1 to subsume Concept2, and when I model this example in DTS and classify with the Modular Classifier, Concept1 does subsume Concept2. However, in my Snorocket code example, it does not.

My code follows. If you could take a quick look to see if I'm representing it correctly, or if you think I'm proceeding from a false assumption, I'd greatly appreciate it.

Thanks again!

        Concept _root = Factory.createNamedConcept("ROOT");
        Concept concept1 = Factory.createNamedConcept("Concept1");
        Concept concept2 = Factory.createNamedConcept("Concept2");

        Concept chem = Factory.createNamedConcept("Chemical");
        Concept cvf = Factory.createNamedConcept("ChemicalViewedFunctionally");
        Concept svc = Factory.createNamedConcept("StructurallyViewedChemical");
        Concept ic  = Factory.createNamedConcept("InorganicChemical");

        Role basicRole = Factory.createNamedRole("basicRole");
        Role roleGroup = Factory.createNamedRole("roleGroup");

        Set<Axiom> baseAxioms = new HashSet<Axiom>();

        baseAxioms.add(Factory.createConceptInclusion(ic, svc));
        baseAxioms.add(Factory.createConceptInclusion(svc, chem));
        baseAxioms.add(Factory.createConceptInclusion(cvf, chem));
        baseAxioms.add(Factory.createConceptInclusion(chem, _root));

        Concept rhs = Factory.createConjunction(_root, Factory.createExistential(basicRole, cvf));
        baseAxioms.add(Factory.createConceptInclusion(concept1, rhs));
        baseAxioms.add(Factory.createConceptInclusion(rhs, concept1));

        baseAxioms.add(Factory.createConceptInclusion(concept2, 
                Factory.createConjunction(_root, Factory.createExistential(roleGroup, 
                        Factory.createConjunction(
                                Factory.createExistential(basicRole, cvf),
                                Factory.createExistential(basicRole, ic))))));

        SnorocketReasoner reasoner = new SnorocketReasoner();
        reasoner.loadAxioms(baseAxioms);
        reasoner.classify();

        Ontology t = reasoner.getClassifiedOntology();
        Utils.printTaxonomy(t.getTopNode(), t.getBottomNode());

Outputs:

{ROOT}
  {Concept1}
  {Concept2}
  {Chemical}
    {ChemicalViewedFunctionally}
    {StructurallyViewedChemical}
      {InorganicChemical}
davetrig commented 8 years ago

Ametke, I realized in looking at this again that this particular example can be modeled like this:

        baseAxioms.add(Factory.createConceptInclusion(concept2, 
                Factory.createConjunction(_root, Factory.createExistential(basicRole, 
                        Factory.createConjunction(cvf,ic)))));

in which case, Concept1 does subsume Concept2.
However, this assumes that a role group is a single role with multiple concepts. There are cases when a role group contains different roles.

So, my question is more accurately represented by this example: Given the same defined concept hierarchy, with roles role1 and role2,

Concept1 ≡ ROOT ⊓ ∃role1.ChemicalViewedFunctionally
Concept2 ⊑ ROOT ⊓ ∃roleGroup(
    ∃role1.ChemicalViewedFunctionally ⊓
    ∃role2.InorganicChemical
)

When this example is modeled and classified in DTS, Concept1 subsumes Concept2. How would this be modeled in the Snorocket API such that Concept1 also subsumes Concept 2?

Thank you.

ametke commented 8 years ago

Hi davetrig,

In your example Concept1 should NOT subsume Concept2, so I am not sure why DTS is classifying it this way or how it was modelled (notice that the exisitentials are role grouped). If you remove the role group you will get Concept1 subsuming Concept2.

Hope this helps.

Cheers

davetrig commented 8 years ago

Hi Ametka, I really do appreciate your continued help. I'm not an expert on DL or ontylog reasoning, show let me show you a concrete example from SNOMED CT, that I believe is the same situation:

Disease caused by parasite (disorder) [17322007] ≡ 
    Disease (disorder) [64572001] ⊓
    ∃Pathological Process (attribute).Parasitic process (qualifier value)

Disease caused by Acanthocephala (disorder) [105713003] ≡
    Disease (disorder) [64572001] ⊓
    ∃Role Group.(
       ∃Causative agent (attribute).Phylum Acanthocephala (organism) ⊓
       ∃Pathological Process (attribute).Parasitic process (qualifier value)
    )

In SNOMED CT, Disease caused by Acanthocephala is subsumed by Disease caused by parasite.

It is entirely possible that I am using the wrong notation or vocabulary to describe this, but this is the scenario I'm trying to model.

Here are screenshots of each concept's defined view as they appear in DTS: image

image

And the tree representing the inferred hierarchy: image

Thank you again for your continued attention.

ametke commented 8 years ago

Hi davetrig,

The problem is that the axiom for "Disease caused by parasite" is not showing an implicit role group that should be there. The axioms should look like this:

Disease caused by parasite (disorder) [17322007] ≡ 
    Disease (disorder) [64572001] ⊓
    ∃Role Group.(∃Pathological Process (attribute).Parasitic process (qualifier value))

Disease caused by Acanthocephala (disorder) [105713003] ≡
    Disease (disorder) [64572001] ⊓
    ∃Role Group.(
       ∃Causative agent (attribute).Phylum Acanthocephala (organism) ⊓
       ∃Pathological Process (attribute).Parasitic process (qualifier value)
    )

Once you add the missing (implicit) role group you'll get the expected subsumption.

Cheers

davetrig commented 8 years ago

Huzzah! Thanks a million!