Family relations
The SDB language is particularly suited to compactly representing knowledge such as family relations. In this example we will do it in two parts. The first defines a specific family tree, and the second part a general set of operators that apply to any family tree. We start with this sample family tree:
|context> => |family tree> mother |sally> => |trude> father |sally> => |tom> age |sally> => |16> mother |erica> => |trude> father |erica> => |tom> age |erica> => |12> mother |trude> => |sara> father |trude> => |sam> husband |trude> => |tom> daughter |trude> => |sally> + |erica> age |trude> => |38> mother |peter> => |ruth> father |peter> => |mike> age |peter> => |26> mother |tom> => |ruth> father |tom> => |mike> wife |tom> => |trude> daughter |tom> => |sally> + |erica> age |tom> => |40> husband |sara> => |sam> daughter |sara> => |trude> age |sara> => |56> wife |sam> => |sara> daughter |sam> => |trude> age |sam> => |56> mother |ruth> => |gina> husband |ruth> => |mike> son |ruth> => |tom> + |peter> age |ruth> => |57> mother |mike> => |mary> father |mike> => |mark> wife |mike> => |ruth> son |mike> => |tom> + |peter> age |mike> => |60> daughter |gina> => |ruth> age |gina> => |76> husband |mary> => |mark> son |mary> => |mike> age |mary> => |76> wife |mark> => |mary> son |mark> => |mike> age |mark> => |78>
Which using graphviz and the dot language becomes:
Next, we define a collection of operators that apply to traversing family trees in general. The intent is that you define a specific family tree with a small subset of operators defined, and then load the family-relations.sw3 file to reason with that family tree.
-- Family relations operators: -- Given only operators for: mother, father, son, daughter, wife, husband, age -- We can construct the following collection of family related operators: -- updated to the version 3.1.1 language -- define our not operator: not |yes> => |no> not |no> => |yes> not |don't know> => |don't know> child |*> #=> (son + daughter) |_self> parent |*> #=> (mother + father) |_self> sibling |*> #=> drop (clean child parent + -1) |_self> brother |*> #=> drop (clean son parent + -1) |_self> sister |*> #=> drop (clean daughter parent + -1) |_self> brother-and-sister |*> #=> sibling |_self> half-brother |*> #=> drop son (mother + -1 father) |_self> + drop son (father + -1 mother) |_self> half-sister |*> #=> drop daughter (mother + -1 father) |_self> + drop daughter (father + -1 mother) |_self> grand-parent |*> #=> parent parent |_self> grand-mother |*> #=> mother parent |_self> grand-father |*> #=> father parent |_self> grand-child |*> #=> child child |_self> grand-son |*> #=> son child |_self> grand-daughter |*> #=> daughter child |_self> great-grand-child |*> #=> child child child |_self> great-grand-son |*> #=> son child child |_self> great-grand-daughter |*> #=> daughter child child |_self> great-grand-parent |*> #=> parent parent parent |_self> great-grand-mother |*> #=> mother parent parent |_self> great-grand-father |*> #=> father parent parent |_self> uncle |*> #=> brother parent |_self> aunt |*> #=> sister parent |_self> aunt-and-uncle |*> #=> (aunt + uncle) |_self> great-uncle |*> #=> brother grand-parent |_self> great-aunt |*> #=> sister grand-parent |_self> great-aunt-and-uncle |*> #=> (great-aunt + great-uncle) |_self> cousin |*> #=> clean child aunt-and-uncle |_self> niece |*> #=> daughter brother-and-sister |_self> nephew |*> #=> son brother-and-sister |_self> brother-in-law |*> #=> (brother wife + brother husband + husband sister) |_self> sister-in-law |*> #=> (sister wife + sister husband + wife brother) |_self> mother-in-law |*> #=> mother (wife + husband) |_self> father-in-law |*> #=> father (wife + husband) |_self> spouse |*> #=> (wife + husband) |_self> is-married |*> #=> do-you-know spouse |_self> is-not-married |*> #=> not do-you-know spouse |_self> -- now a collection of is-a-x rules: is-a-father |*> #=> is-mbr(|_self>) clean father child |_self> is-a-mother |*> #=> is-mbr(|_self>) clean mother child |_self> is-a-parent |*> #=> do-you-know child |_self> is-a-son |*> #=> is-mbr(|_self>) clean son parent |_self> is-a-daughter |*> #=> is-mbr(|_self>) clean daughter parent |_self> is-a-grand-mother |*> #=> is-mbr(|_self>) clean mother parent child^2 |_self> is-a-grand-father |*> #=> is-mbr(|_self>) clean father parent child^2 |_self> is-a-grand-parent |*> #=> do-you-know child^2 |_self> is-a-great-grand-mother |*> #=> is-mbr(|_self>) clean mother parent^2 child^3 |_self> is-a-great-grand-father |*> #=> is-mbr(|_self>) clean father parent^2 child^3 |_self> is-a-great-grand-parent |*> #=> do-you-know child^3 |_self> is-a-male |*> #=> is-a-son |_self> || is-a-father |_self> is-a-female |*> #=> is-a-daughter |_self> || is-a-mother |_self> is-an-uncle |*> #=> is-a-male |_self> && do-you-know child sibling |_self> is-an-aunt |*> #=> is-a-female |_self> && do-you-know child sibling |_self> is-a-husband |*> #=> is-a-male |_self> && do-you-know wife |_self> is-a-wife |*> #=> is-a-female |_self> && do-you-know husband |_self> is-a-brother |*> #=> is-a-male |_self> && do-you-know sibling |_self> is-a-sister |*> #=> is-a-female |_self> && do-you-know sibling |_self> -- define some is-a-x rules that require knowledge of age: is-a-child |*> #=> is-in-range[0,17] age |_self> is-a-teenager |*> #=> is-in-range[13,19] age |_self> is-an-adult |*> #=> not is-in-range[0,17] age |_self> is-a-man |*> #=> is-a-male |_self> && is-an-adult |_self> is-a-woman |*> #=> is-a-female |_self> && is-an-adult |_self> is-a-boy |*> #=> is-a-male |_self> && not is-an-adult |_self> is-a-girl |*> #=> is-a-female |_self> && not is-an-adult |_self> is-male-or-female |*> #=> is-a-male |_self> || is-a-female |_self> is-a-senior-citizen |*> #=> not is-in-range[0,59] age |_self> -- now a collection of have-a-x rules: have-a-child |*> #=> do-you-know child |_self> have-a-brother |*> #=> do-you-know brother |_self> have-a-sister |*> #=> do-you-know sister |_self> have-a-wife |*> #=> do-you-know wife |_self> have-a-husband |*> #=> do-you-know husband |_self> have-an-uncle |*> #=> do-you-know uncle |_self> have-an-aunt |*> #=> do-you-know aunt |_self> have-a-cousin |*> #=> do-you-know cousin |_self> have-a-niece |*> #=> do-you-know niece |_self> have-a-nephew |*> #=> do-you-know nephew |_self> -- now a collection of how-many rules: how-many-children |*> #=> how-many child |_self> how-many-grand-children |*> #=> how-many child^2 |_self> how-many-great-grand-children |*> #=> how-many child^3 |_self> how-many-brothers |*> #=> how-many brother |_self> how-many-sisters |*> #=> how-many sister |_self> how-many-uncles |*> #=> how-many uncle |_self> how-many-aunts |*> #=> how-many aunt |_self> how-many-cousins |*> #=> how-many cousin |_self> how-many-nieces |*> #=> how-many niece |_self> how-many-nephews |*> #=> how-many nephew |_self> -- some more rules about number of children: have-1-child |*> #=> is-equal[1] how-many-children |_self> have-2-children |*> #=> is-equal[2] how-many-children |_self> have-3-children |*> #=> is-equal[3] how-many-children |_self> have-4-children |*> #=> is-equal[4] how-many-children |_self>
Now, we load both files into the SDB shell, and then we can ask some simple questions about the loaded knowledge:
$ ./SDB3_1 -iq family-tree.sw3 family-relations.sw3 Welcome to the Semantic DB version 3.1.1 shell. Last updated 18th June 2021. Type h for help. Online info for the SDB language at http://semantic-db.org/docs/usage3/ sa: sister |sally> |erica> sa: grand-mother |sally> |sara> + |ruth> sa: age grand-mother |sally> |56> + |57> sa: great-grand-father |sally> |mark> sa: age great-grand-father |sally> |78> sa: aunt |sally> |> sa: uncle |sally> |peter> sa: is-an-uncle |peter> |yes> sa: age uncle |sally> |26> sa: is-married |sally> |no> sa: is-married |ruth> |yes> sa: grand-child |ruth> |sally> + |erica> sa:
Or we could just display a table with some chosen operators:
sa: table[person, mother, father, age, sister, brother, grand-mother, grand-father, is-a-female, is-a-male] such-that[is-male-or-female] rel-kets[*] +--------+--------+--------+-----+--------+---------+--------------+--------------+-------------+-----------+ | person | mother | father | age | sister | brother | grand-mother | grand-father | is-a-female | is-a-male | +--------+--------+--------+-----+--------+---------+--------------+--------------+-------------+-----------+ | sally | trude | tom | 16 | erica | | sara + ruth | sam + mike | yes | no | | erica | trude | tom | 12 | sally | | sara + ruth | sam + mike | yes | no | | trude | sara | sam | 38 | | | | | yes | no | | peter | ruth | mike | 26 | | tom | gina + mary | mark | no | yes | | tom | ruth | mike | 40 | | peter | gina + mary | mark | no | yes | | sara | | | 56 | | | | | yes | no | | sam | | | 56 | | | | | no | yes | | ruth | gina | | 57 | | | | | yes | no | | mike | mary | mark | 60 | | | | | no | yes | | gina | | | 76 | | | | | yes | no | | mary | | | 76 | | | | | yes | no | | mark | | | 78 | | | | | no | yes | +--------+--------+--------+-----+--------+---------+--------------+--------------+-------------+-----------+ |table>
where we have filtered the output of rel-kets[*] to kets that are male or female, ie, people, using the such-that[is-male-or-female] operator. Otherwise our table would include a couple of kets that are not people. Note that the blanks in the table correspond to operators that return the empty ket when applied to the given ket/person.