Discussion Forum

Multiple Inheritance Support

Can there be support for multiple inheritance please? While even languages like Java & C# support for multiple inheritance via Interfaces, it will be a powerful & necessary feature for a knowledge graph.

HI @velulev,

We have actually been going back and forth on this one for a while. The conclusion we keep hitting is that we will implement it only when we truly need it because while it is a powerful feature it does add some complexity to the model.

What’s been stopping us from diving into this is that we can’t think of an example that cannot be modeled with the current single inheritance constraint. Do you have such an example in mind? If so that would probably expedite the feature.

Regards,

Filipe

1 Like

Correct me if I’m wrong, but using Grakn’s model this could be achieve by assigning multiple roles to the same entity right ? if you define it in a hierarchical way, (with car sub vehicle;), is it possible to inherit from multiple entities?

Thanks !

1 Like

Yes that is 100% correct! and thank you for clarifying the issue. Grakn allows multiple inheritance as long as its from the same “branch”. In other words this works:

insert 
    vehicle sub entity;
    car sub vehicle;
    smaller-car sub car;

However, this does not:

insert 
    vehicle sub entity;
    car sub entity;
    smaller-car sub vehicle;
    smaller-car sub car;

In the latter case smaller-car will not inherit from both but will first be a vehicle and then be changed to a car

Note that multiple inheritance is fundamental to many/most ontologies, and lack of support may make GRAKN a non-starter for most ontology-based work. Eg. most biomedical ontologies (GO, HPO, UBERON, PATO, Cell ontology, etc.). One can work-around this limitation by defining a relationship as ‘subclass’ and use that in lieu of the native ‘sub’, but that is a hack around one of the main selling-points of GRAKN: that it supports ontologies.

1 Like

Hi @BobR,

Actually, we can still represent them in Grakn. The problem with multiple-inheritance, is that every time someone comes up with a problem that needs to be modelled with multiple-inheritance, it’s often an abuse of the construct.

For example:

A government can employ a person, and company can employ a person. Then users often think there should be an entity that inherits both government and company entity that can employ a person - e.g. they end up with a employer entity that subclasses both.

This is an example of an abuse of inheritance, as it is used in the wrong place. This problem is solved by the notion of a role in Grakn. roles are part of relationships that contextualises a how a thing s are involved in a relationship.

The correct way, as we model it in Grakn, is to have employer as a role in an employment relationship, where government and company plays the role of an employer.

Here’s an example schema of it:

company sub entity,
    has name,
    plays employer;

government sub entity,
    has name,
    plays employer;

employment sub relationship,
    relates employee,
    relates employer;

Let me know if that makes sense. And do share if you there are problems that are critical to be modelled with multiple-inheritance that cannot be modelled with roles.

Thank you!

Hi @haikal, yes, in ontologies it is important to distinguish which properties of a class ought to be considered truly inheritable, and which should not. In your example, a state-government, and indeed any government that is a smaller entity, might still be reasonably considered to be an employer, so we would want that role to be inherited by any subclasses without having to explicitly restate it.

If roles, when assigned to entities, are already heritable in GRAKN, then the problem is solved - and basically, GRAKN is (nearly) supporting multiple-inheritance by another name.

If not, there is a truth-maintenance issue introduced, since we’d need to indicate the inherited roles explicitly on each subclass.

Consider the example

cancer sub entity;
liver_disease sub entity;
liver_cancer sub cancer;
liver_cancer sub liver_disease;

In a case where we do not want to (or can’t) arbitrarily select “cancer” or “liver disease” to be represented via a “role”, how would we model the above w/o multiple inheritance?

Thanks!

Hi @JeffL,

First, yes, the roles are inherited when type subclasses another. :white_check_mark:

Regarding your example, I see two potential problems with the suggested model.

  1. It uses multiple-inheritance to “group” things, rather than to subclass “types”, where each type is a definition of something else. In this case, cancer is probably a group of diseases? Which is not the same as a type. If we quickly look at wikipedia:

Cancer is a group of diseases involving abnormal cell growth with the potential to invade or spread to other parts of the body.[2][8]

  1. It represents an instance as a type in the schema, rather than as an instance of fact in the graph. In this case, liver-cancer is probably an instance of a disease? More specifically, an instance of a liver disease?

Thus, I would probably model this problem like the following:

define

disease sub entity,
    has name,
    plays member;

liver-disease sub entity;

disease-group sub entity,
    has name;
    plays owner;

grouping sub relationship,
    relates member,
    relates owner;

And insert data instances (i.e. facts) to the graph such as the following:

insert 
$x isa liver-disease, has name "liver cancer";
$y isa disease-group, has name "cancer";
(member: $x, owner: $y) isa grouping;

You can then query the graph like:

match $x isa disease, has name $xn; ($x, $y);
$y isa disease-group, has name "cancer"; get $x;

Which will return a $x as a liver-disease with name “liver cancer”.

What do you think? Would that make sense?

@ haikal,
Hierarchies can be malformed if incorrect superclasses are used, but multiple, semantically-correct direct-superclasses are common in many ontologies. It is true that one can tease apart properties and roles reflected in a logical superclass and model those associations to a subclass independently, but one should be able to model the superclass entity that encompasses those and relate it to all logical subclasses.

Consider a multiple-inheritance example common on Protege pages from Stanford: Red_wine, Dessert_wine, and Port_wine. Consider some biological processes in the GeneOntology, eg. http://amigo.geneontology.org/amigo/term/GO:0006663. Consider some phenotypes in HPO, eg. https://hpo.jax.org/app/browse/term/HP:0001043. Consider an extension of the example above: vehicle, car, small-vehicle, small-car. In OWL, a class can have as many superclasses as are named or logical identified by DL reasoning.

I have seen many assertions that ‘most ontologies support multiple inheritance’, and that has been my experience, but I haven’t computed the fraction that do. Since multiple inheritance is reflected in many reference ontologies that might be data sources for users of a graph database, it would help greatly to enable direct representation of those ontologies in GRAKN without working around the n=1 superclass limitation.

1 Like

What would the Grakn way look like for something I’m inclined to model in the following fashion?

define
    software
        sub entity,
        has name,
        … ;

    service
        sub entity,
        has name,
        … ;

    saas
        sub software,
        sub service,
        has url
        … ;

insert
    $fb isa saas,
    has name "Facebook",
    has url "https://facebook.com"
    … ;

A late reply, but nonetheless here’s an idea of how this could be re-modelled. The fact that a software can be provided as a service sounds more like a behaviour or an aspect of that entity, so is well-suited as a role. In this way we try to model the domain more exactly: We decompose SAAS to be a software that is hosted somewhere, in this case a web-domain. This way we also separate the name of the software from the domain, which models the scenario closer to real-world.

The extra trick here is that we can use a rule to classify software as saas. We can only have (virtual) multiple types through logical inference and not through multiple inheritance defined in the schema.

define

  url sub attribute, datatype string;
  name sub attribute, datatype string;

  web-domain sub entity,
    has url,
    plays web-host;

  software sub entity,
    has name,
    plays hosted-software;

  software-hosting sub relation,
    relates hosted-software,
    relates web-host;


  # An extra trick
  saas sub entity,
    plays hosted-software;

  hosting-means-saas sub rule,
  when {
    $w isa web-domain;
    $s isa software;
    (web-host: $w, hosted-software: $s) isa software-hosting;
  }, then {
    $s isa saas;
  };

insert
  $w isa web-domain, has url "facebook.com";
  $s isa software, has name "Facebook";
  (web-host: $w, hosted-software: $s) isa software-hosting;

match $x isa saas, has name $n; get;

To answer this question we must first answer the question what does it mean to be an entity of a given type or subtype. Logically a type is just a named group whose members share higher level supertypes, relationships, roles, attributes and the supertype relationships belonging to those relationships, roles and attributes…

If we accept the definition of a type as a subtype of a group then the question becomes can we define a group in a non recursive way, ie a group is something with members who can be groups. With a minimal amount of trial and error it quickly becomes apparent that any meaningful definition of group must be recursive in nature.

This is important because the single inheritance model requires that all possible subgroups of the parent inherit no logically groupable set of traits that are not shared by the parent. Since it is clear that any attempt to group any large number of entities together without violating this paradigm is doomed to failure.

The only solution is to allow for multiple inheritance including allowing an entity be both a thing and an attribute, for example a county fair is both type of entity being that it is a type of event and also an attribute in that it is something that the entity ‘city’ can have/host.

Allowing multiple inheritence makes the rules about function overloads and virtual dispatch decidedly more tricky, as well as the language implementation around object layouts. These impact language designers/implementors quite a bit, and raise the already high bar to get a language done, stable and adopted.

It is simple to think this way, if class A inherits from multiple classes, then the class A will have the same grandparent class multiple times, this means the code will be complicated and a series of bugs will go unacknowledged. Personally, I think multiple inheritance has a bad rap, and that a well done system of trait style composition would be really powerful/useful… but there are a lot of ways that it can be implemented badly, and a lot of reasons it’s not a good idea in a language like C++.