Rust framework

DeepCausality

Dynamic causality for advanced systems.

A causal-reasoning library for engineering systems where time, context, and rules evolve. Built around three primitives: the causal monad, the causaloid, and the context.

01 / 04 WHAT IS DYNAMIC CAUSALITY

Causal reasoning for a dynamic world

DeepCausality treats causality as a spacetime-agnostic dependency. The Causal Monad sequences causal processes. Causaloids encode each causal relation as a small composable unit in an isomorphic recursive structure. The PropagatingEffect composes Causal Monads and Causaloids together. A Context hypergraph encodes the environment those rules operate in. The Effect Ethos verifies that whatever the rules conclude still satisfies the operational policies you have to honor.

02 / 04 ONE FRAMEWORK, MANY FIELDS

What can you build with DeepCausality

Async / Tokio

Background causal inference on a Tokio task.

use crate::handler::EventHandler;
use crate::model::build_causal_model;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let event_handler = EventHandler::new(build_causal_model());

    tokio::spawn(async move {
        if let Err(e) = event_handler.run_background_inference().await {
            eprintln!("inference error: {e}");
        }
    })
    .await
    .expect("Failed to spawn async background task");

    Ok(())
}
Open example
Counterfactuals

Pearl Rung-3: surgically intervene on a value mid-chain.

use deep_causality_core::{Intervenable, PropagatingEffect};

// Natural chain: nicotine → tar → cancer.
let before = PropagatingEffect::pure(0.8_f64)
    .bind(|nic, _, _| PropagatingEffect::pure(nicotine_to_tar(
        nic.into_value().unwrap_or_default())))
    .bind(|tar, _, _| PropagatingEffect::pure(tar_to_cancer(
        tar.into_value().unwrap_or_default())));

// Counterfactual: same start, but intervene on tar mid-chain.
let after = PropagatingEffect::pure(0.8_f64)
    .bind(|nic, _, _| PropagatingEffect::pure(nicotine_to_tar(
        nic.into_value().unwrap_or_default())))
    .intervene(0.1)
    .bind(|tar, _, _| PropagatingEffect::pure(tar_to_cancer(
        tar.into_value().unwrap_or_default())));
Open example
Sensor monitoring

A Causal State Machine wired to three real-time sensors.

use deep_causality::{CSM, CausalState, PropagatingEffect};

let default_data: PropagatingEffect<f64> = PropagatingEffect::pure(0.0);

let smoke_cs = CausalState::new(SMOKE_SENSOR, 1, default_data.clone(),
    get_smoke_sensor_causaloid(), None);
let fire_cs  = CausalState::new(FIRE_SENSOR, 1, default_data.clone(),
    get_fire_sensor_causaloid(), None);

let csm = CSM::new(&[(&smoke_cs, &get_smoke_alert_action()),
                     (&fire_cs,  &get_fire_alert_action())]);

let evidence: PropagatingEffect<f64> = PropagatingEffect::pure(smoke_data[i]);
csm.eval_single_state(SMOKE_SENSOR, &evidence)?;
Open example
Aerospace

Five-stage PropagatingProcess for a flight-envelope monitor.

let initial: FlightProcess<SensorReading> = PropagatingProcess {
    value: EffectValue::Value(reading),
    state: FlightState::default(),
    context: Some(config),
    error: None,
    logs: EffectLog::new(),
};

initial
    .bind(|v, s, c| run_sensor_collection(v, s, c, failing_airspeed))
    .bind(|v, s, c| health_fold(v, s, c, seed_estimate.clone()))
    .bind(|v, s, c| kalman_step(v, s, c))
    .bind(|v, s, c| estimate_step(v, s, c))
    .bind(|v, s, c| run_envelope_graph(v, s, c))
Open example
Biomedical

Optimize TTFields electrode angle with a causal Metropolis loop.

use deep_causality_core::{CausalityError, EffectValue, PropagatingEffect};

let effect = PropagatingEffect::pure(new_params).bind(|params, _, _| {
    let p = match params {
        EffectValue::Value(v) => v,
        _ => (0.0, 0.0),
    };
    let score = match model::evaluate_efficacy(&tumor, p) {
        Ok(s) => s,
        Err(e) => return PropagatingEffect::from_error(
            CausalityError::new(/* ... */)
        ),
    };
    PropagatingEffect::pure(score)
});

if let EffectValue::Value(new_score) = effect.value() {
    if *new_score > current_score { /* accept */ }
}
Open example
Physics

Maxwell field derivation as a four-step monadic chain.

use deep_causality::PropagatingEffect;
use model::{MaxwellState, PlaneWaveConfig};

let initial_state = MaxwellState::from_config(&config);

let result: PropagatingEffect<MaxwellState> =
    PropagatingEffect::pure(initial_state).bind(|state, _, _| {
        model::compute_potential(state.into_value().unwrap_or_default())
            .bind(|s, _, _| model::compute_em_field(s.into_value().unwrap_or_default()))
            .bind(|s, _, _| model::check_lorenz_gauge(s.into_value().unwrap_or_default()))
            .bind(|s, _, _| model::compute_poynting_flux(s.into_value().unwrap_or_default()))
    });

let final_state = result.value.into_value().unwrap_or_default();
Open example

03 / 04 WHY DEEPCAUSALITY

What DeepCausality can do for you

Static, dynamic, adaptive, and emergent causality

Model causal structure that is fixed at design time, evolves over the lifetime of a system, adapts to feedback, or arises from interaction. The same primitives carry across all four modalities, so the choice is a modeling decision.

Multi-shaped causality

Express a single rule as a Causaloid, a flat collection of Causaloids, or a hypergraph of nested Causaloids. The shape follows the problem: an isolated guard, a battery of independent checks, or a deeply composed causal structure with subgraphs and shared subexpressions.

Causal discovery via CDL

The Causal Discovery Language is a typestate-driven DSL that walks raw observational data through configuration, loading, feature selection, discovery, and analysis. Each stage is enforced by the type system.

Causal State Machines (CSM)

Wire Causaloids to actions and let the framework drive the transitions. The CSM pattern is the right fit for sensor monitoring, alerting, and control loops where a state change has to follow a causal verdict.

Static and dynamic context

Causaloids run inside a Context: a hypergraph of the data, time, and space they depend on. A static context is defined up front; a dynamic context grows, shrinks, or rewires at runtime as new information arrives.

Multimodal reasoning

A single graph can reason deterministically, probabilistically, counterfactually, or in any combination. The PropagatingEffect type carries the modality through the graph.

Markovian and non-Markovian modeling

PropagatingEffect carries the immediate signal; PropagatingProcess carries the trajectory of effects over time. Together they let a model reason about systems whose next state depends on the current state, on full history, or on anything in between.

First-class uncertainty

Uncertain<T> wraps a value whose distribution is known but whose exact value is not. MaybeUncertain<T> goes further and represents probabilistic presence: a value that may or may not be there. Both compose with the rest of the framework without breaking type safety.

Uniform mathematical composition

Tensors, multivectors, manifolds, and sparse matrices expose the same Functor/Monad/CoMonad surface through HAFT and the algebraic trait hierarchy.

Programmable safety with the Effect Ethos

The Effect Ethos is a programmable policy layer that verifies operational rules over the effects a graph produces. It lets safety-critical and regulated systems encode "what is allowed to happen" alongside "what does happen," checked deterministically at runtime.