CND (Conditional Node Distribution) Base Class¶
The CND class is the abstract base class for all conditional node distributions in Bayesian Networks. It defines the common interface and functionality that all distribution types must implement.
Overview¶
The CND class establishes a consistent interface for:
- Probability Computation: Methods for evaluating probabilities and densities
- Parameter Access: Standardized ways to get and set distribution parameters
- Validation: Common validation and consistency checking
- Serialization: Uniform methods for saving and loading distributions
- Type System: Ensures all distributions work consistently within BNs
Abstract Interface¶
All concrete distribution classes (CPT, LinGauss) must implement the CND interface:
from abc import ABC, abstractmethod
class CND(ABC):
@abstractmethod
def prob(self, value, parents_values=None):
"""Compute probability/density for given value and parent values."""
pass
@abstractmethod
def sample(self, parents_values=None):
"""Generate a sample from the distribution."""
pass
@abstractmethod
def validate(self):
"""Check distribution parameters for consistency."""
pass
Common Attributes¶
All CND instances provide:
parents: List of parent variable namesnode_type: Type of distribution ('discrete' or 'continuous')param_count: Number of free parameters in the distribution
Usage Patterns¶
The CND base class is typically used for:
- Type Checking: Ensuring objects are valid distributions
- Polymorphism: Writing code that works with any distribution type
- Interface Definition: Understanding what methods distributions provide
- Extension: Creating new distribution types
Example Usage¶
from causaliq_core.bn.dist import CPT, LinGauss, CND
# Create different distribution types
discrete_dist = CPT(values=['A', 'B'], table=[0.3, 0.7])
continuous_dist = LinGauss(mean=0.0, sd=1.0, coeffs={}, parents=[])
# Both implement the CND interface
distributions = [discrete_dist, continuous_dist]
for dist in distributions:
assert isinstance(dist, CND) # Type checking
# Common interface methods
sample = dist.sample() # Generate sample
dist.validate() # Check consistency
print(f"Distribution type: {dist.node_type}")
print(f"Parameter count: {dist.param_count}")
print(f"Sample: {sample}")
Implementing Custom Distributions¶
To create a new distribution type, inherit from CND and implement the abstract methods:
from causaliq_core.bn.dist.cnd import CND
import random
class BernoulliDistribution(CND):
"""Custom Bernoulli distribution example."""
def __init__(self, p=0.5, parents=None):
self.p = p
self.parents = parents or []
self.node_type = 'discrete'
def prob(self, value, parents_values=None):
"""Compute probability for Bernoulli distribution."""
if value == 1:
return self.p
elif value == 0:
return 1 - self.p
else:
return 0.0
def sample(self, parents_values=None):
"""Generate Bernoulli sample."""
return 1 if random.random() < self.p else 0
def validate(self):
"""Check parameter validity."""
if not 0 <= self.p <= 1:
raise ValueError("Bernoulli parameter must be in [0,1]")
@property
def param_count(self):
return 1 # One free parameter (p)
# Use custom distribution
custom_dist = BernoulliDistribution(p=0.3)
assert isinstance(custom_dist, CND)
sample = custom_dist.sample()
Validation Framework¶
The CND base class provides a validation framework that:
- Parameter Checking: Ensures parameters are in valid ranges
- Consistency Validation: Checks internal consistency of distributions
- Parent Validation: Verifies parent relationships are valid
- Error Reporting: Provides clear error messages for invalid configurations
Integration with BN Class¶
The CND interface ensures that:
- Any CND subclass can be used in a BN
- Probabilistic inference works consistently across distribution types
- Parameter learning follows the same patterns
- Serialization and I/O operations are uniform
API Reference¶
cnd
¶
Classes:
-
CND–Conditional Node Distribution for a node conditional on parental values.
CND
¶
Conditional Node Distribution for a node conditional on parental values.
Concrete subclasses support specific kinds of distributions, for example, CPT (multinomial), LinearGaussian etc.
Attributes:
-
has_parents(bool) –Whether CND is for a node with parents.
-
free_params(int) –Number of free params in CND.
Methods:
-
__eq__–Return whether two CNDs are the same allowing for
-
__str__–Human-friendly description of the contents of the CND.
-
cdist–Return conditional distribution for specified parental values.
-
fit–Constructs a CND (Conditional Node Distribution) from data.
-
parents–Return parents of node CND relates to.
-
random_value–Generate a random value for a node given the value of its parents.
-
to_spec–Returns external specification format of CND,
-
validate_cnds–Checks that all CNDs in graph are consistent with one another
-
validate_parents–Checks every CND's parents and (categorical) parental values
cdist
abstractmethod
¶
cdist(parental_values: Optional[Dict[str, Any]] = None) -> Any
Return conditional distribution for specified parental values.
Parameters:
-
(parental_values¶dict, default:None) –Parental values for which dist. required for non-orphans.
Raises:
-
TypeError–If args are of wrong type.
-
ValueError–If args have invalid or conflicting values.
fit
abstractmethod
classmethod
¶
fit(
node: str, parents: Optional[Tuple[str, ...]], data: Any, autocomplete: bool = True
) -> Tuple[Tuple[type, Dict[str, Any]], Optional[int]]
Constructs a CND (Conditional Node Distribution) from data.
Parameters:
-
(node¶str) –Node that CND applies to.
-
(parents¶tuple) –Parents of node.
-
(data¶Data) –Data to fit CND to.
-
(autocomplete¶bool, default:True) –Whether complete CPT tables.
Returns:
-
tuple(Tuple[Tuple[type, Dict[str, Any]], Optional[int]]) –(cnd_spec, estimated_pmfs) where cnd_spec is (CPT class, cpt_spec for CPT()) estimated_pmfs int/None - only for CPTs.
parents
abstractmethod
¶
Return parents of node CND relates to.
Returns:
-
list(List[str]) –Parent node names in alphabetical order.
random_value
abstractmethod
¶
random_value(pvs: Optional[Dict[str, Any]]) -> Union[str, float]
Generate a random value for a node given the value of its parents.
Parameters:
-
(pvs¶dict) –Parental values, {parent1: value1, ...}.
Returns:
-
Union[str, float]–str or float: Random value for node.
to_spec
abstractmethod
¶
to_spec(name_map: Dict[str, str]) -> Dict[str, Any]
Returns external specification format of CND, renaming nodes according to a name map.
Parameters:
-
(name_map¶dict) –Map of node names {old: new}.
Returns:
-
dict(Dict[str, Any]) –CND specification with renamed nodes.
validate_cnds
classmethod
¶
Checks that all CNDs in graph are consistent with one another and with graph structure.
Parameters:
-
(nodes¶list) –BN nodes.
-
(cnds¶dict) –Set of CNDs for the BN, {node: cnd}.
-
(parents¶dict) –Parents of non-orphan nodes, {node: parents}.
Raises:
-
TypeError–If invalid types used in arguments.
-
ValueError–If any inconsistent values found.
validate_parents
abstractmethod
¶
validate_parents(
node: str, parents: Dict[str, List[str]], node_values: Dict[str, List[str]]
) -> None
Checks every CND's parents and (categorical) parental values are consistent.
Validates consistency with the other relevant CNDs and the DAG structure.
Parameters: