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.
M0/T0: scaffold del crate sheafsync
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}