6. Interface Declaration

Interfaces are abstract classes used to impose constraints on classes. Just like classes, interfaces have attributes and reference slots (but no CPT). Classes that implement interfaces must necessarily contain the attributes and references slots specified in the interfaces. This mechanism is particularly effective to easily define relations between classes as well as multiple inheritance. For instance, interfaces are the key to define dynamic Bayesian networks (2TBN) using PRMs. Actually, a 2TBN contains one Bayesian network fragment for time slice t=0 and another fragment for transitions between time slice t and t+1, for all t’s. Using the 2TBN means copy/pasting the first fragment once, followed by (T-1) copy/pastes of the second fragment, hence resulting in the creation of a Bayesian network over time slices 0 to T. In the O3PRM language, we would naturally consider a class B0 for the first fragment and a class Bt for the second one. As Bt models the transition between time slices t0 and t1, some attributes of Bt should have parents in B0 (otherwise the transitions never depend on the past, which makes the temporal nature of the dynamic Bayesian network quite useless). But Bt also models the transition between time slices t1 and t2. As a result, the parents that were located in B0 should now be in Bt. So, at first sight, this prevents specifying dynamic Bayesian networks using the O3PRM language. Fortunately, interfaces enable this specification. Actually, in Bt, for the transition between t0 and t1, it is useless to know the value of the CPT of the parents belonging to B0, what is important is just to know which attributes of B0 are needed as parents in Bt. Similarly, for the transition between time slices t1 and t2, the only information needed in Bt is to know which attributes of t1 are used as parents in attributes of t2. As a consequence, if these parent attributes are specified in an interface, and if B0 and Bt implement this interface, both B0 and Bt are constrained to include these parent attributes and we just need to specify that, in Bt, the parents of the attributes at time t+1 are those contained in the interface. Since the interface is the same for B0 and Bt, when instantiating these classes, the O3PRM interpreter will select appropriately the parents. Here is the syntax to specify an interface:

<interface>      ::= interface <word> [ extends <path> ] "{" <interface_elt> "}"
<interface_elt>  ::= <reference_slot> | <abstract_attr>
<reference_slot> ::= [internal] <word> [ "[" "]" ] <word> ";"
<abstract_attr>  ::= <word> <word> ";"

Interface attributes are called abstract attributes because they do not have any CPT.

interface MyInterface {
  boolean state;
}

class MyClass {
  MyInterface iface;
  boolean X dependson iface.state {
    //iface.state==false | iface.state==true
    [                0.2,                0.7, // X==false
                     0.8,                0.3] // X==true
  };
}

Interfaces can be used as reference slots types and are useful for defining recursive relations (see the dynamic Bayesian network example described above). Note the keyword implements in the example below used to indicate that a class implements an interface, i.e., that it declares all the latter’s attributes and reference slots. Here, Base and Step correspond to classes B0 and Bt mentioned in the dynamic Bayesian network example respectively. Note that attribute state of Step depends on the attribute state of Interface Iface. As a consequence, when instantiating, previous.state can be either the state attribute of Class Base or that of Class Step.

interface Iface {
  boolean state;
}

class Base implements Iface {
  boolean state {[ 0.2, 0.8 ]};
}

class Step implements Iface {
  Iface previous;
  boolean state dependson previous.state {
    false: 0.9, 0.1; // P(state|previous.state==false)
    true:  0.2, 0.8; // P(state|previous.state==true)
  };
}

System DynamicO3PRM {
  Base base;
  Step step_1;
  step_1.previous = base;
  Step step_2;
  step_2.previous = step_1;
  Step step_3;
  step_3.previous = step_2;
  // ...
}