tawasuyu

tawasuyu/hifas

Motor en Rust para decidir, con demostración y no a ojo, cuándo un conjunto de réplicas local-first puede operar sin coordinación y cuándo no — y, cuando la respuesta es "sí, dentro de límites", proveer el mecanismo que lo garantiza.

⎇ 6595dbed856eec31669beb6db74b456faa4be9a1 src/linalg.rs Rust · 73 líneas · 2.4 KB Historia Quién tocó qué crudo

M0/T0: scaffold del crate sheafsync 6595dbed8 · Sergio ·

1//! Aislamiento del álgebra lineal tras un `trait` (§5.1, §7.1).
2//!
3//! Dos aritméticas, misma interfaz:
4//! - `F64Backend`: rápido, con tolerancia epsilon. Para arrancar el MVP.
5//! - `Gf2Backend` (M2): exacto, bit-packed sobre 𝔽₂. Aún no implementado.
6//!
7//! En M0 solo dejamos la *forma*: la impl `f64` existe pero sus operaciones
8//! todavía no calculan nada. La lógica llega en T1.
9
10/// Escalar del backend activo. Alias que resuelve la impl elegida (§6.1, §7).
11pub type Scalar = f64;
12
13/// Matriz densa mínima almacenada por filas. Placeholder de M0; en T1 puede
14/// migrarse a `nalgebra::DMatrix` o mantenerse propia para el backend `GF(2)`.
15#[derive(Debug, Clone, PartialEq)]
16pub struct Matrix {
17    pub rows: usize,
18    pub cols: usize,
19    /// Datos row-major: `data[r * cols + c]`.
20    pub data: Vec<Scalar>,
21}
22
23impl Matrix {
24    /// Matriz de ceros de tamaño `rows × cols`.
25    pub fn zeros(rows: usize, cols: usize) -> Self {
26        Self {
27            rows,
28            cols,
29            data: vec![0.0; rows * cols],
30        }
31    }
32}
33
34/// Interfaz de álgebra lineal que el motor usa sin conocer la aritmética concreta.
35///
36/// Las dos operaciones que la cohomología necesita (§7): rango del coboundary y
37/// una base del cokernel para localizar la obstrucción.
38pub trait LinAlg {
39    /// `rank(m)` — número de filas/columnas independientes.
40    fn rank(&self, m: &Matrix) -> usize;
41
42    /// Base del cokernel `C¹ / im δ`: vectores de longitud `m.rows` que no
43    /// provienen de ninguna sección global. Vacío si `H¹ = 0`.
44    fn cokernel_basis(&self, m: &Matrix) -> Vec<Vec<Scalar>>;
45}
46
47/// Backend `f64` del MVP (§7.1). Rango con tolerancia epsilon.
48///
49/// M0: shell vacío. La eliminación gaussiana llega en T1.
50#[derive(Debug, Default, Clone, Copy)]
51pub struct F64Backend {
52    /// Tolerancia para considerar un pivote como cero.
53    pub epsilon: Scalar,
54}
55
56impl F64Backend {
57    /// Backend con la tolerancia por defecto.
58    pub fn new() -> Self {
59        Self { epsilon: 1e-9 }
60    }
61}
62
63impl LinAlg for F64Backend {
64    fn rank(&self, _m: &Matrix) -> usize {
65        // TODO(T1): eliminación gaussiana con pivoteo, contar pivotes > epsilon.
66        unimplemented!("F64Backend::rank llega en T1")
67    }
68
69    fn cokernel_basis(&self, _m: &Matrix) -> Vec<Vec<Scalar>> {
70        // TODO(T1): extraer base del cokernel a partir de la forma escalonada.
71        unimplemented!("F64Backend::cokernel_basis llega en T1")
72    }
73}