Prolog is a great source of inspiration for TypeDB! It does indeed support inference and solving akin to Prolog. There are two inference engines in TypeDB: type inference and rule inference.
The problem you posed above could be solved as follows making use of both kinds of inference.
A roughly equivalent schema, define this using a schema session in a write transaction:
define
crime sub entity,
owns name,
plays criminal-liability:crime;
name sub attribute,
value string;
person sub entity,
owns classification, # Declaring this as an attribute rather than a subtype of person means that a person can be classified in multiple ways
owns geneva-convention-protection,
plays elements:defendant,
plays elements:victim,
plays criminal-liability:defendant,
plays criminal-liability:victim,
plays international-conflict:participant,
plays killing:perpetrator,
plays killing:victim,
plays torture:perpetrator,
plays torture:victim;
classification sub attribute,
value string;
geneva-convention-protection sub attribute,
value boolean;
rule geneva-convention-protects-civilians:
when {
$p isa person, has classification "civilian";
}
then {
$p has geneva-convention-protection true;
};
rule geneva-convention-protects-prisoners-of-war:
when {
$p isa person, has classification "prisoner of war";
}
then {
$p has geneva-convention-protection true;
};
rule geneva-convention-protects-medical-personnel:
when {
$p isa person, has classification "medical personnel";
}
then {
$p has geneva-convention-protection true;
};
rule geneva-convention-protects-religious-personnel:
when {
$p isa person, has classification "religious personnel";
}
then {
$p has geneva-convention-protection true;
};
elements sub relation,
relates defendant,
relates victim,
relates statute;
criminal-liability sub relation,
relates crime,
relates defendant,
relates victim,
relates statute;
statute sub entity,
owns name,
plays elements:statute,
plays criminal-liability:statute;
rule genocide-liability:
when {
$c isa crime, has name "Genocide";
(defendant: $d, victim: $v, statute: $s) isa elements;
}
then {
(crime: $c, defendant: $d, victim: $v, statute: $s) isa criminal-liability;
};
rule conflict-geneva-convention-liability:
when {
$p isa person, has geneva-convention-protection true;
($d, $v) isa international-conflict;
(defendant: $d, victim: $v, statute: $s) isa elements;
$c isa crime, has name "War Crime";
}
then {
(crime: $c, defendant: $d, victim: $v, statute: $s) isa criminal-liability;
};
# This relation needs to be inserted directly relate two people involved in a conflict as it is defined here. It may
# be better to infer that the two are on opposing sides each fighting for a nation where those nations are in conflict
international-conflict sub relation,
relates participant;
act sub relation,
relates party;
killing sub act,
relates victim as party,
relates perpetrator as party;
torture sub act,
relates victim as party,
relates perpetrator as party;
rule killing-under-article-8-2-a-i:
when {
(perpetrator: $pp, victim: $v) isa killing;
$s isa statute, has name "article-8-2-a-i";
}
then {
(defendant: $pp, victim: $v, statute: $s) isa elements;
};
rule turture-under-article-8-2-a-ii:
when {
(perpetrator: $pp, victim: $v) isa torture;
$s isa statute, has name "article-8-2-a-ii";
}
then {
(defendant: $pp, victim: $v, statute: $s) isa elements;
};
The data necessary for the rules in the schema:
insert $c isa crime, has name "Genocide";
insert $c isa crime, has name "War Crime";
insert $c isa crime, has name "Crime Against Humanity";
insert $c isa crime, has name "Crime of Aggression";
insert $s isa statute, has name "article-8-2-a-i";
insert $s isa statute, has name "article-8-2-a-ii";
Data to give us some examples to work with:
insert
$p1 isa person, has classification "civilian";
$p2 isa person;
(victim: $p1, perpetrator: $p2) isa killing;
insert
$p1 isa person, has classification "prisoner-of-war";
$p2 isa person;
(victim: $p1, perpetrator: $p2) isa torture;
(participant: $p1, participant:$p2) isa international-conflict;
Add all data using a data session and a write transaction.
Then, in a data session, in a read transaction ensuring infer=true
we can look for the insight we’re looking for: who faces criminal liability?
match
$cl(crime: $c, defendant: $d, victim: $v, statute: $s) isa criminal-liability;
$c has name $crime-name;
$s has name $statute-name;
$v has classification $classification;
You should get some answers back! Without meaning anything political it seems like the rule for genocide applies too widely. I’ve just interpreted it from your prolog snippet, any suggestions?
Thanks for posting such a poignant example! Hope this helps.