Nodes

<< Click to Display Table of Contents >>

Navigation:  Using SMILE > Networks, nodes and arcs >

Nodes

Nodes are represented by DSL_node objects. Your program should always use the DSL_network::AddNode method to create a node within the network and never use DSL_node constructor directly. To delete a node, use DSL_network::DeleteNode; never try to use delete on an DSL_node pointer.

The node type specified during node creation can be changed later with DSL_node::ChangeType. The type change modify neither node pointer nor its handle. However, node definition and value objects representing the old type are destroyed and recreated to reflect the new type.

Within a network, nodes are uniquely identified by their handles. A node handle is a non-negative integer, which is preserved when the network is copied using a copy constructor or operator=. Most of DSL_network methods dealing with nodes uses node handles as input arguments. In general, node handles may change when you write the network to file and read it later. This means that you should not rely on handles as persistent identifiers.

Values of handles are not guaranteed to be consecutive or start from any particular value. To iterate over nodes in a network, please use DSL_network::GetFirstNode and GetNextNode:

for (int h = net.GetFirstNode(); h >= 0; h = net.GetNextNode(h))

{

 DSL_node *node = net.GetNode(h);

 printf("Node handle: %d, node id: %s\n", h, node->GetId());

}

Note the loop exit condition - we stop when GetNextNode returns a negative value. It is also possible to get all node handles copied into a DSL_intArray object by means of GetAllNodes.

DSL_network::PartialOrdering returns a reference to a DSL_intArray containing all node handles in the network partially ordered (ancestor handles always precede their descendants).

In addition to a handle, each node has an unique (in the context of its containing network), persistent, textual identifier. This identifier is specified as an argument to DSL_network::AddNode method at node creation, and may be changed later with DSL_node::SetId. Identifiers in SMILE are case-sensitive, start with a letter and contain letters, digits, and underscores.

A node identifier can be translated to a node handle with a call to DSL_network::FindNode method.

int handle = net.FindNode("myNodeId");

if (handle >= 0)

{

 printf("Handle of myNodeId is: %d\n", handle);

}

else

{

 printf("There's no node with ID=myNodeId\n");

}

Note that FindNode has O(n) complexity, as it simply compares its input argument with all node identifiers in the loop. On the other hand, GetNode is O(1), as it performs an index lookup in the array. GetNode also has an overload, which accepts a node identifier as input, and performs O(n) linear search, returning NULL if there is no node with the specified identifier.

DSL_node *node = net.GetNode("myNodeId");

if (NULL == node)

{

 printf("Node 'myNodeId' doest not exist.\n");

}

To get all node identifiers into a DSL_idArray object, use GetAllNodeIds.

Nodes may be marked as targets with DSL_network::SetTarget method. Target nodes are always guaranteed to be updated by the inference algorithm. Other nodes, i.e., nodes that are not designated as targets, may be updated or not, depending on the internals of the algorithm used, but are not guaranteed to be updated. Focusing inference on the target nodes can reduce time and memory required to complete the calculation. When no targets are specified, SMILE assumes that all nodes are of interest to the user.

A node can be marginalized. The operation removes it from the network, and modifies the definitions of the remaining nodes, so that the joint probability distribution over the remaining variables in the network is unchanged.