An MDELite Allegory Model


We recently made a connection between UML class diagrams and allegories -- categories that have power set domains.  Here's the idea: a natural way to think about tuples in categories is by a domain of tuples.  But what we really want in a relational database interpretation is a power set of tuples -- elements of this domain are sets of tuples -- i.e., relational tables.  Arrows in this universe map tables-to-tables; this is exactly what relational algebra does.

Below is a UML class diagram that relates persons to the departments that they work in, departments to the divisions in which they reside, and persons with children (who are also persons):



An allegory (category) with power domains is shown below. Arrow traversals are rightSemiJoins. A database that encodes these relationships is shown below:

dbase(PDD,[Person,Department,Division,employs_worksin,childrenOf_parentsOf]).

table(Person,[pid,name,age]).
Person(p1,don,64).
Person(p2,karen,57).
Person(p3,hanna,23).
Person(p4,alex,25).
Person(p5,steve,53).
Person(p6,priscila,28).

table(Department,[did,name,inDiv:Division]).
Department(d1,mens,v1).
Department(d2,womens,v1).
Department(d3,appliances,v2).
Department(d4,hardware,v2).

table(Division,[vid,name]).
Division(v1,clothing).
Division(v2,goods).
table(childrenOf_parentsOf,[id,childrenOf:Person,parentsOf:Person]).
childrenOf_parentsOf(c1,p3,p1).
childrenOf_parentsOf(c2,p3,p2).
childrenOf_parentsOf(c3,p4,p1).
childrenOf_parentsOf(c4,p4,p2).

table(employs_worksin,[id,Person:Person,Department:Department]).
employs_worksin(w1,p1,d1).
employs_worksin(w2,p2,d2).
employs_worksin(w3,p3,d2).
employs_worksin(w4,p4,d4).
employs_worksin(w5,p5,d3).
employs_worksin(w6,p6,d2).
employs_worksin(w7,p1,d3).

Given this, here are some queries (easily transformed into constraints) that one can express.  Note how compact they are.


The above program, and the hand-written Java class that implements these arrows is in MELite7/LectureExamples/allegory. The current version of the allegory program is shown below.

Please note that this source, which is in the LectureExamples directory of MDELite7, is a single file with nested classes.  Study it in detail -- the main ideas are shown below.

import PrologDB.DB;
import PrologDB.Table;
import PrologDB.TableSchema;
import PrologDB.Tuple;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class PDD {

DB db;
public Table person;
public Table department;
public Table division;
public Table employs_worksin;
public Table childrenof_parentsof;

public PDD(String fileName) {
db = DB.readDataBase(fileName);
person = db.getTableEH("Person");
department = db.getTableEH("Department");
division = db.getTableEH("Division");
employs_worksin = db.getTableEH("employs_worksin");
childrenof_parentsof = db.getTableEH("childrenOf_parentsOf");
}
class Department extends common<Department> {
protected Department New(Table t) { return new Department(t); }

public Department() { table = department; }

public Department(Table t) { super("Department",t); }

public Department(Tuple t) { super("Department",t); }

protected Department(String n, Table t) { super(n,t); }

protected Department(String n, Tuple t) { super(n,t); }

public Person employs() {
Table result1 = table.rightSemiJoin("did",employs_worksin,"Department");
Table result2 = result1.rightSemiJoin("Person",person,"pid");
return new Person(result2);
}

public Division inDiv() {
Table result = table.rightSemiJoin("inDiv",division,"vid");
return new Division(result);
}
}
class Person extends common<Person> {
protected Person New(Table t) { return new Person(t); }

public Person() { table = person; }

public Person(Table t) { super("Person",t); }

public Person(Tuple t) { super("Person",t); }

protected Person(String n, Table t) { super(n,t); }

protected Person(String n, Tuple t) { super(n,t); }

public Department worksin() {
Table result1 = table.rightSemiJoin("pid",employs_worksin,"Person");
Table result2 = result1.rightSemiJoin("Department",department,"did");
return new Department(result2);
}

public Person childrenOf() {
Table result1 = table.rightSemiJoin("pid",childrenof_parentsof,"parentsOf");
Table result2 = result1.rightSemiJoin("childrenOf",person,"pid");
return new Person(result2);
}

public Person parentsOf() {
Table result1 = table.rightSemiJoin("pid",childrenof_parentsof,"childrenOf");
Table result2 = result1.rightSemiJoin("parentsOf",person,"pid");
return new Person(result2);
}
}
abstract class common<T extends common> {
Table table;

protected common() { }

protected common(String tableName, Tuple t) {
TableSchema ts = t.getSchema();
if (!ts.getName().equals(tableName))
throw new RuntimeException("assigning non-"+tableName+" table to "+tableName);
table = new Table(ts).add(t);
}

protected common(String tableName, Table tab) {
if (!tab.getSchema().getName().equals(tableName)) {
throw new RuntimeException("assigning non-"+tableName+" table to "+tableName);
}
table = tab;
}

public T select(Predicate p) {
Table result = table.filter(p);
return New(result);
}

protected abstract T New(Table t);

public T id() { return New(table); }

public void print() { table.print(System.out); }

public void forEach(Consumer action) { table.stream().forEach(t -> action.accept(t)); }

public T intersect(T tab) { return New(this.table.intersect(tab.table)); }

public int size() { return this.table.count(); }

public boolean equals(T tab) { return this.table.equals(tab.table); }
}
class Division extends common<Division> {
protected Division New(Table t) { return new Division(t); }

public Division() { table = division; }

public Division(Table t) { super("Division",t); }

public Division(Tuple t) { super("Division",t); }

protected Division(String n, Table t) { super(n,t); }

protected Division(String n, Tuple t) { super(n,t); }

public Department hasDeps() {
Table result = table.rightSemiJoin("vid",department,"inDiv");
return new Department(result);
}
}
class childrenOf_parentsOf extends common<childrenOf_parentsOf> {
protected childrenOf_parentsOf New(Table t) { return new childrenOf_parentsOf(t); }

public childrenOf_parentsOf() { table = childrenof_parentsof; }

public childrenOf_parentsOf(Table t) { super("childrenOf_parentsOf",t); }

public childrenOf_parentsOf(Tuple t) { super("childrenOf_parentsOf",t); }

protected childrenOf_parentsOf(String n, Table t) { super(n,t); }

protected childrenOf_parentsOf(String n, Tuple t) { super(n,t); }
}
class employs_worksin extends common<employs_worksin> {

protected employs_worksin New(Table t) { return new employs_worksin(t); }

public employs_worksin() { table = employs_worksin; }

public employs_worksin(Table t) { super("employs_worksin",t); }

public employs_worksin(Tuple t) { super("employs_worksin",t); }

protected employs_worksin(String n, Table t) { super(n,t); }

protected employs_worksin(String n, Tuple t) { super(n,t); }
}

A Catalina (MDELite-bootstrapped) specification of this design is:



And a generated version of the above source is here.