Skip to main content

qualia_core_db/domains/financial/economics/
input_output.rs

1//! Input-output and supply-shock propagation.
2
3/// Maximum sectors in a bounded input-output (Leontief) model.
4pub const MAX_SECTORS: usize = 32;
5
6/// Propagate a supply/geopolitical shock through an inter-sector input-output
7/// (Leontief) coupling matrix to its total downstream impact.
8pub fn propagate_supply_shock(
9    coupling: &[f64],
10    shock: &[f64],
11    n: usize,
12    max_rounds: u32,
13    tolerance: f64,
14    impact_out: &mut [f64],
15) -> usize {
16    if n == 0
17        || n > MAX_SECTORS
18        || coupling.len() < n * n
19        || shock.len() < n
20        || impact_out.len() < n
21    {
22        return 0;
23    }
24    let mut term = [0.0f64; MAX_SECTORS];
25    let mut next = [0.0f64; MAX_SECTORS];
26    for i in 0..n {
27        term[i] = shock[i];
28        impact_out[i] = shock[i];
29    }
30    let mut rounds = 0usize;
31    for _ in 0..max_rounds {
32        rounds += 1;
33        let mut l1 = 0.0f64;
34        for i in 0..n {
35            let mut acc = 0.0;
36            for j in 0..n {
37                acc += coupling[i * n + j] * term[j];
38            }
39            next[i] = acc;
40            l1 += acc.abs();
41        }
42        for i in 0..n {
43            impact_out[i] += next[i];
44            term[i] = next[i];
45        }
46        if l1 < tolerance {
47            break;
48        }
49    }
50    rounds
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn supply_shock_propagates_to_dependent_sectors() {
59        let a = [0.0, 0.5, 0.5, 0.0];
60        let shock = [1.0, 0.0];
61        let mut impact = [0.0f64; 2];
62        let rounds = propagate_supply_shock(&a, &shock, 2, 100, 1e-9, &mut impact);
63        assert!(rounds > 1);
64        assert!((impact[0] - 4.0 / 3.0).abs() < 1e-6);
65        assert!(impact[1] > 0.6 && impact[1] < 0.7);
66    }
67
68    #[test]
69    fn supply_shock_rejects_bad_dimensions() {
70        let mut out = [0.0f64; 2];
71        assert_eq!(
72            propagate_supply_shock(&[0.0], &[1.0], 0, 10, 1e-9, &mut out),
73            0
74        );
75        assert_eq!(
76            propagate_supply_shock(&[0.0; 4], &[1.0, 0.0], 3, 10, 1e-9, &mut out),
77            0
78        );
79    }
80}