Node definition

<< Click to Display Table of Contents >>

Navigation:  Using SMILE > Anatomy of a node >

Node definition

The definition of a node specifies how this node interacts with other nodes in the network. Node definition are saved in the network file (by DSL_network::WriteFile and WriteString) and are retrieved back when reading the file. For a general chance node, the definition consists of a conditional probability table (CPT) and a list of state names. To access a node definition, please use DSL_node::Def method, which returns a pointer to the instance of the class derived from the DSL_nodeDef.

int nodeHandle = …;

DSL_node *node = net.GetNode(nodeHandle);

DSL_nodeDef *def = node->Def();

The definition object is managed by the network containing the node. SMILE provides a number of classes derived from DSL_nodeDef, specialized to represent different node types (CPT, Noisy-MAX, decision, etc.). The choice of the definition object class associated with a given node is based on the node type parameter that is passed to DSL_network::AddNode. As SMILE is compiled with RTTI disabled, you cannot use dynamic_cast to check for the actual type of the object returned by DSL_node::Def. However, you can use DSL_nodeDef::GetType and GetTypeName methods:

int nodeHandle = net.AddNode(DSL_CPT, "myNodeId");

DSL_nodeDef *def = net.GetNode(nodeHandle)->Def();

printf("Type of the definition: %d %s\n", def->GetType(), def->GetTypeName());

In the example above, the def variable points to the object of the DSL_cpt class derived from DSL_nodeDefinition. While it is possible to static_cast or use DSL_node::Def<T> to obtain access to type-specific functionality of the object, SMILE provides general purpose virtual methods defined in DSL_nodeDef, overridden in derived classes, which makes casting unnecessary most of the time. For example, two of these methods are DSL_nodeDef::GetMatrix and GetOutcomeIds, which give access to node’s parameters and state names. Some of the node types do not support all of the operations: the decision nodes do not have any numeric parameters, and, therefore, their definition object of DSL_decision class returns NULL from its GetMatrix method.

While the virtual methods defined in DSL_nodeDef support most of the APIs required for discrete Bayesian networks and influence diagrams, there is plenty of extended functionality in SMILE's node definition classes (continuous equation nodes, canonical nodes, interval-based discrete nodes, etc). SMILE provides DSL_nodeDef::Def<T> template method, which returns a pointer to the node definition type specified as its template parameter. The example below assumes that eqNodeHandle is the handle to the DSL_EQUATION node, which uses DSL_equation class derived from DSL_nodeDef to represent its definition:

DSL_node *node = net.GetNode(eqHandle);

auto eq = node->Def<DSL_equation>(); // eq variable type is DSL_equation*

eq->SetEquation("a=Normal(0,1)");

The templated Def<T> method does a simple inline static_cast and is provided as a 'syntactic sugar'. Note that there is no runtime type checking here. If there is only one call through the pointer cast to the derived type, the code can be shortened to a single line:

net.GetNode(eqHandle)->Def<DSL_equation>()->SetEquation("a=Normal(0,1)");

The choice of style is, of course, left to the SMILE user.