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.

One framework, many fields

What can you build with it

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

What is dynamic causality

Causal reasoning for a dynamic world.

Most causal-inference libraries assume a static graph and a fixed set of rules. Real systems rarely cooperate. A trading regime shifts; a robot enters a new room; a service mesh reroutes traffic. The variables stay the same; the relationships between them do not.

DeepCausality treats causality as a spacetime-agnostic functional dependency. Causaloids encode each rule as a small composable unit. 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.

The framework is written in Rust, runs in real time, and stays correct when both the data and the rules evolve under it.