Skip to content

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 names
  • node_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

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

__eq__ abstractmethod
__eq__(other: object) -> bool

Return whether two CNDs are the same allowing for probability rounding errors.

Parameters:

  • other
    (CND) –

    CND to compared to self.

Returns:

  • bool ( bool ) –

    Whether CPTs are PRACTICALLY the same.

__str__ abstractmethod
__str__() -> str

Human-friendly description of the contents of the CND.

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
parents() -> List[str]

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
validate_cnds(
    nodes: List[str], cnds: Dict[str, CND], parents: Dict[str, List[str]]
) -> None

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:

  • node
    (str) –

    Name of node.

  • parents
    (dict) –

    Parents of all nodes {node: parents}.

  • node_values
    (dict) –

    Values of each cat. node {node: values}.