use std::collections::BTreeMap;
use converge_pack::gate::GateResult as Result;
use converge_pack::gate::{ProblemSpec, ReplayEnvelope, SolverReport};
use super::types::*;
pub struct FuzzyInferenceEngine;
impl FuzzyInferenceEngine {
pub fn solve(
&self,
input: &FuzzyInferenceInput,
spec: &ProblemSpec,
) -> Result<(FuzzyInferenceOutput, SolverReport)> {
input.validate()?;
let input_memberships = evaluate_input_memberships(&input.inputs, &input.variables);
let mut memberships: BTreeMap<String, f64> = BTreeMap::new();
let mut activated_rules = Vec::new();
for (idx, rule) in input.rules.iter().enumerate() {
let antecedent_strength = evaluate_expression(&rule.when, &input_memberships)?;
let weight = rule.weight();
let strength = (antecedent_strength * weight).clamp(0.0, 1.0);
let consequent = rule.then.key();
memberships
.entry(consequent.clone())
.and_modify(|current| *current = current.max(strength))
.or_insert(strength);
if strength > 0.0 {
activated_rules.push(ActivatedRule {
id: rule
.id
.clone()
.unwrap_or_else(|| format!("rule-{}", idx + 1)),
antecedent_strength,
weight,
strength,
consequent,
});
}
}
let confidence = memberships.values().copied().fold(0.0, f64::max);
let output = FuzzyInferenceOutput {
input_memberships,
memberships,
activated_rules,
confidence,
total_rules: input.rules.len(),
};
let replay = ReplayEnvelope::minimal(spec.seed());
let report = SolverReport::optimal("fuzzy-inference-v1", confidence, replay);
Ok((output, report))
}
}