<< Click to Display Table of Contents >> Navigation: Using SMILE Wrappers > Canonical nodes > Noisy-MAX |
Noisy-MAX is a generalization of the widely used canonical gate Noisy-OR and can model interactions among variables with multiple states. When all nodes involved are binary, a Noisy-MAX node reduces to a standard Noisy-OR node. SMILE’s implementation of Noisy-MAX also includes an implicit negation feature. By DeMorgan's laws, the OR function (or its generalization, MAX) combined with negation can express any logical relationship, including AND (or MIN) functions. This means that SMILE’s Noisy-MAX can be used to model Noisy-AND/MIN gates, as well as more complex logical interactions.
SMILE’s inference algorithm includes a specialized code path for networks containing Noisy-MAX nodes, which can substantially speed up computations. See the Noisy-MAX decomposition section of this manual for further details.
To create a Noisy-MAX node, use the NOISY_MAX type with Network.add_node:
Python
net.add_node(pysmile.NodeType.NOISY_MAX, "node1")
Java
net.addNode(Network.NodeType.NOISY_MAX, "node1");
C#
net.AddNode(Network.NodeType.NoisyMax, "node1");
R
net$addNode(net$NodeType$NOISY_MAX, "node1")
A Noisy-MAX node has discrete outcomes, like a standard CPT node. Its node definition includes two key components:
•Conditionally Independent (CI) Probabilities – define the distribution of the child node given the states of its parents, assuming conditional independence. Set or retrieve them with Network.set_node_definition and Network.get_node_definition.
•Parent Outcome Strengths – for each parent, an array of numerical strengths specifies the order in which parent states influence the child in the CI table. The Noisy-MAX CI table is always organized according to these strengths. Use Network.set_noisy_parent_strengths and Network.get_noisy_parent_strengths to modify or read them.
As an example, consider a binary Noisy-MAX node with two parents, each having three outcomes. The following snippet modifies the probabilities and outcome strengths for the second parent (zero-based index 1):
Python
ci = net.get_node_definition(h)
BASE = 2 * 3
ci[BASE] = 0.1
ci[BASE + 1] = 0.9
ci[BASE + 2] = 0.3
ci[BASE + 3] = 0.7
net.set_node_definition(h, ci)
net.set_noisy_parent_strengths(h, 1, [2, 0, 1])
Java
double[] ci = net.getNodeDefiniton(h);
int BASE = 2 * 3;
ci[BASE] = 0.1;
ci[BASE + 1] = 0.9;
ci[BASE + 2] = 0.3;
ci[BASE + 3] = 0.7;
net.setNodeDefiniton(h, ci);
net.setNoisyParentStrengths(h, 1, new int[] { 2, 0, 1 });
C#
double[] ci = net.GetNodeDefinition(h);
int BASE = 2 * 3;
ci[BASE] = 0.1;
ci[BASE + 1] = 0.9;
ci[BASE + 2] = 0.3;
ci[BASE + 3] = 0.7;
net.SetNoisyParentStrengths(h, 1, new int[] { 2, 0, 1 });
R
ci <- net$getNodeDefiniton(h)
BASE <- 2 * 3
ci[BASE + 1] <- 0.1
ci[BASE + 2] <- 0.9
ci[BASE + 3] <- 0.3
ci[BASE + 4] <- 0.7
net$setNodeDefiniton(h, ci)
net$setNoisyParentStrengths(h, 1, c(2L, 0L, 1L))
Explanation:
•BASE is calculated as the product of the child node’s outcome count and the product of preceding parents’ outcome counts. Here, one preceding parent has three outcomes, giving BASE = 2 * 3
•Each pair of probabilities in the CI table corresponds to a binary child node for a given parent outcome. The probabilities within a pair always sum to 1.
•The parent outcome strengths array [2, 0, 1] defines the order in which the parent’s outcomes are interpreted by the Noisy-MAX child node. For example, after applying the strengths, the second parent’s outcomes are seen by the child as {State2, State0, State1}.
•Changing the strengths does not modify the parent node itself; the ordering is local to this parent-child relationship.
•Other Noisy-MAX nodes can define their own parent outcome ordering if they share the same parent.
This structure ensures that probabilities remain valid (sum to 1 for each parent outcome) while allowing flexible control over which parent outcome maps to which column in the child’s CI table.
Assuming that we started with the default uniform probabilities in the table, our modifications yields the following Noisy-Max definition, as viewed in GeNIe:
The outcomes of both parent are {State0, State1, State2}. However, by using set_parent_outcome_strenghts for parent p2, its outcomes are seen by the Noisy-MAX child node as {State2, State0, State1}. Other Noisy-MAX nodes in the same network can set up their own parent outcome ordering if p2 becomes their parent.
The conditionally independent (CI) probabilities of a Noisy-MAX node are used internally to derive the full conditional probability table (CPT) for the node. This expansion is performed automatically by the library whenever the complete CPT is required during inference. The resulting CPT can be retrieved using the Network.get_noisy_expanded_definition method.
The following methods of the Network class allow you to work with parent outcome strengths and retrieve the expanded CPT for Noisy-MAX nodes:
Python
set_noisy_parent_strengths(node: int | str, parent: int | str, strengths: list[int]) -> None
get_noisy_parent_strengths(node: int | str, parent: int | str) -> list[int]
get_noisy_expanded_definition(node: int | str) -> list[float]
Java
void setNoisyParentStrengths(int nodeHandle, int parentIndex, int[] strengths);
void setNoisyParentStrengths(String nodeId, int parentIndex, int[] strengths);
void setNoisyParentStrengths(int nodeHandle, String parentId, int[] strengths);
void setNoisyParentStrengths(String nodeId, String parentId, int[] strengths);
int[] getNoisyParentStrengths(int nodeHandle, int parentIndex);
int[] getNoisyParentStrengths(String nodeId, int parentIndex);
int[] getNoisyParentStrengths(int nodeHandle, String parentId);
int[] getNoisyParentStrengths(String nodeId, String parentId);
double[] getNoisyExpandedDefinition(int nodeHandle);
double[] getNoisyExpandedDefinition(String nodeId);
C#
void SetNoisyParentStrengths(int nodeHandle, int parentIndex, int[] strengths);
void SetNoisyParentStrengths(string nodeId, int parentIndex, int[] strengths);
void SetNoisyParentStrengths(int nodeHandle, string parentId, int[] strengths);
void SetNoisyParentStrengths(string nodeId, string parentId, int[] strengths);
int[] GetNoisyParentStrengths(int nodeHandle, int parentIndex);
int[] GetNoisyParentStrengths(string nodeId, int parentIndex);
int[] GetNoisyParentStrengths(int nodeHandle, string parentId);
int[] GetNoisyParentStrengths(string nodeId, string parentId);
double[] GetNoisyExpandedDefinition(int nodeHandle);
double[] GetNoisyExpandedDefinition(string nodeId);
R
set_noisy_parent_strengths(nodeIdOrHandle, parentIdOrIndex, strengths)
noisy_parent_strengths <- get_noisy_parent_strengths(nodeIdOrHandle, parentIdOrIndex)
noisy_expanded_definition <- get_noisy_expanded_definition(nodeIdOrHandle)