Skip to main content

CausalInferenceEngine

Struct CausalInferenceEngine 

Source
pub struct CausalInferenceEngine {
    pub graph: CausalGraph,
    pub max_path_length: usize,
}
Expand description

Production-grade causal inference engine.

§Example

use ipfrs_tensorlogic::{
    CausalInferenceEngine, CausalNode, CausalEdge, Intervention,
};

let mut engine = CausalInferenceEngine::new(10);
engine.add_node(CausalNode::new("X", 0.0, 1.0)).expect("example: should succeed in docs");
engine.add_node(CausalNode::new("Y", 0.0, 1.0)).expect("example: should succeed in docs");
engine.add_edge(CausalEdge::direct("X", "Y", 0.8)).expect("example: should succeed in docs");

let result = engine.do_calculus(
    &Intervention::new("X", 1.0),
    &ipfrs_tensorlogic::CausalNodeId::new("Y"),
);
assert!((result.mean - 0.8).abs() < 1e-9);

Fields§

§graph: CausalGraph

The underlying causal graph.

§max_path_length: usize

Maximum number of hops considered when enumerating paths.

Implementations§

Source§

impl CausalInferenceEngine

Source

pub fn new(max_path_length: usize) -> Self

Create a new engine with an empty graph and the given path-length limit.

Source

pub fn add_node(&mut self, node: CausalNode) -> Result<(), CausalError>

Add a node to the graph.

Returns CausalError::NodeAlreadyExists if the identifier is taken.

Source

pub fn add_edge(&mut self, edge: CausalEdge) -> Result<(), CausalError>

Add a directed edge to the graph.

Both endpoints must already exist, and the edge must not introduce a directed cycle. On success the parent/child lists of both endpoints are updated in-place.

Source

pub fn remove_node(&mut self, id: &CausalNodeId) -> bool

Remove a node and all edges that touch it.

Returns true if the node existed and was removed, false otherwise.

Source

pub fn has_path(&self, from: &CausalNodeId, to: &CausalNodeId) -> bool

Return true if there is at least one directed path from from to to (depth-first search, respects max_path_length).

Source

pub fn is_ancestor( &self, ancestor: &CausalNodeId, descendant: &CausalNodeId, ) -> bool

Return true if ancestor is a strict ancestor of descendant (i.e. there is a directed path from ancestor to descendant).

Source

pub fn ancestors(&self, id: &CausalNodeId) -> Vec<CausalNodeId>

Return all strict ancestors of id via BFS through parent pointers.

Source

pub fn descendants(&self, id: &CausalNodeId) -> Vec<CausalNodeId>

Return all strict descendants of id via BFS through child pointers.

Source

pub fn all_directed_paths( &self, from: &CausalNodeId, to: &CausalNodeId, ) -> Vec<Vec<CausalNodeId>>

Enumerate all directed paths from from to to up to max_path_length hops (DFS with backtracking).

Source

pub fn backdoor_paths( &self, from: &CausalNodeId, to: &CausalNodeId, ) -> Vec<Vec<CausalNodeId>>

Enumerate backdoor paths from from to to.

A backdoor path is any path that arrives at from via an incoming edge (i.e. starts from a parent of from and eventually reaches to). Paths are limited to max_path_length hops.

Source

pub fn do_calculus( &self, intervention: &Intervention, target: &CausalNodeId, ) -> InferenceResult

Compute the interventional distribution P(target | do(intervention)).

Uses a linear causal model: the mean of target under the intervention is the intervention value times the sum of all path effects from the intervened node to target. The posterior variance shrinks by the total explained fraction (capped at 0.99 to avoid degenerate zero variance), and the confidence is the explained fraction clamped to [0, 1].

Source

pub fn counterfactual(&self, query: &CounterfactualQuery) -> InferenceResult

Estimate the counterfactual distribution of query.target had query.intervention been applied, conditioned on query.evidence.

The implementation uses do-calculus as a base and adds an evidence correction: for each observed variable in evidence we sum the product of its observed value and the direct edge strength to the target.

Source

pub fn average_causal_effect( &self, from: &CausalNodeId, to: &CausalNodeId, value1: f64, value2: f64, ) -> f64

Compute the Average Causal Effect (ACE) of from on to.

ACE = E[to | do(from = value2)] - E[to | do(from = value1)]

Source

pub fn confounders( &self, x: &CausalNodeId, y: &CausalNodeId, ) -> Vec<CausalNodeId>

Return the common ancestors of x and y (i.e. potential confounders).

Source

pub fn is_d_separated( &self, x: &CausalNodeId, y: &CausalNodeId, given: &[CausalNodeId], ) -> bool

Simplified d-separation check.

Returns true if x and y are d-separated given the conditioning set given.

The implementation tests:

  1. No direct edge from x to y (after removing given nodes).
  2. No directed path from x to y that does not pass through a given node.
  3. No backdoor path from x to y that is not blocked by a given node.
Source

pub fn stats(&self) -> CausalStats

Compute summary statistics for the current graph.

Trait Implementations§

Source§

impl Debug for CausalInferenceEngine

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more