reasoninglayer 0.1.2

Rust client SDK for the Reasoning Layer API
Documentation
//! Statistical analysis DTOs.

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use super::causal::CausalRelationshipDto;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatisticalSuccessResponse {
    pub message: String,
    pub success: bool,
}

// ─── Correlation ──────────────────────────────────────────────────────────────

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CorrelationRequest {
    pub var_x: String,
    pub var_y: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CorrelationResponse {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub correlation: Option<f64>,
    pub count: u64,
    pub success: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartialCorrelationRequest {
    pub conditioning_set: Vec<String>,
    pub var_x: String,
    pub var_y: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PartialCorrelationResponse {
    pub count: u64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub partial_correlation: Option<f64>,
    pub success: bool,
}

// ─── Conditional independence ─────────────────────────────────────────────────

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConditionalIndependenceRequest {
    pub conditioning_set: Vec<String>,
    pub var_x: String,
    pub var_y: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConditionalIndependenceResponse {
    pub explanation: String,
    pub independent: bool,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub p_value: Option<f64>,
}

// ─── Observations ─────────────────────────────────────────────────────────────

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObserveSingleRequest {
    pub value: f64,
    pub variable: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObserveSingleResponse {
    pub count: u64,
    pub success: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObservePairRequest {
    pub var_x: String,
    pub var_y: String,
    pub x: f64,
    pub y: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObservePairResponse {
    pub count: u64,
    pub success: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObserveMultiRequest {
    pub observations: BTreeMap<String, f64>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ObserveMultiResponse {
    pub success: bool,
    #[serde(default)]
    pub variables: Vec<String>,
}

// ─── Intervention observation ─────────────────────────────────────────────────

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InterventionObservationRequest {
    pub changed_variables: Vec<String>,
    pub unchanged_variables: Vec<String>,
    pub value: String,
    pub variable: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct InterventionObservationResponse {
    pub message: String,
    pub remaining_uncertain_count: u64,
    #[serde(default)]
    pub resolved_edges: Vec<Vec<serde_json::Value>>,
    pub success: bool,
}

// ─── Causal discovery ─────────────────────────────────────────────────────────

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoverCausalRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub min_samples: Option<u32>,
    pub variables: Vec<String>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DiscoverCausalResponse {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub data_needed: Option<Vec<serde_json::Value>>,
    pub message: String,
    #[serde(default)]
    pub relationships: Vec<CausalRelationshipDto>,
    pub relationships_discovered: u64,
    pub success: bool,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DiscoveryStateDto {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub current_samples: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub required_samples: Option<u32>,
    pub state_type: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uncertain_count: Option<u64>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DiscoveryStatusResponse {
    pub directed_edge_count: u64,
    pub has_graph: bool,
    pub state: DiscoveryStateDto,
    pub total_uncertainty: f64,
    pub undirected_edge_count: u64,
}

// ─── Dynamic discovery ────────────────────────────────────────────────────────

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DiscoveryStrategy {
    Pc,
    Mcmc,
    Hybrid,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DynamicDiscoveryRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub alpha: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub edge_threshold: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub mcmc_burn_in: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub mcmc_samples: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub min_samples: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub strategy: Option<DiscoveryStrategy>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub temporal_tiers: Option<Vec<Vec<String>>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub use_active_learning: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub use_ges: Option<bool>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DiscoveryProofStatsDto {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub duration_ms: Option<u64>,
    pub max_depth: u32,
    pub total_nodes: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoveryProofNodeDto {
    pub depth: u32,
    pub explanation: String,
    pub id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub p_value: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<String>,
    pub step_type: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DiscoveryProofTreeDto {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub dot_format: Option<String>,
    #[serde(default)]
    pub nodes: Vec<DiscoveryProofNodeDto>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub root_id: Option<String>,
    pub statistics: DiscoveryProofStatsDto,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GesResultDto {
    pub edges_added: u32,
    pub edges_removed: u32,
    pub final_score: f64,
    pub improvement: f64,
    pub initial_score: f64,
    pub was_refined: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InterventionRecommendationDto {
    pub edges_resolved_count: u32,
    pub expected_information_gain: f64,
    pub reason: String,
    pub variable: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UncertainEdgeDto {
    #[serde(default)]
    pub possible_directions: Vec<Vec<serde_json::Value>>,
    pub uncertainty: f64,
    pub x: String,
    pub y: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DynamicDiscoveryResponse {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub edge_posteriors: Option<Vec<serde_json::Value>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub ges_result: Option<GesResultDto>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub proof_tree: Option<DiscoveryProofTreeDto>,
    #[serde(default)]
    pub recommended_interventions: Vec<InterventionRecommendationDto>,
    #[serde(default)]
    pub relationships: Vec<CausalRelationshipDto>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub skeleton: Option<Vec<serde_json::Value>>,
    pub state: DiscoveryStateDto,
    pub strategy: String,
    pub success: bool,
    #[serde(default)]
    pub uncertain_edges: Vec<UncertainEdgeDto>,
}