pub fn solve_on_change_sublinear(
matrix: &dyn Matrix,
_prev_solution: &[Precision],
b_new: &[Precision],
delta: &SparseDelta,
closure_depth: usize,
max_terms: usize,
tolerance: Precision,
) -> Result<Vec<(usize, Precision)>>Expand description
SubLinear sibling of IncrementalSolver::solve_on_change. Returns
Vec<(usize, Precision)> of (row_index, x_new[row]) for every row
in the bounded-depth closure of delta’s support, computed without
touching any row outside the closure.
The output is sorted ascending by row index. Callers that need a dense view can scatter the entries into a vector themselves; callers chaining onto contrastive search / find_anomalous_rows_in_subset don’t need to.
§Wiring
closure = closure::closure_indices(matrix, &delta.indices, closure_depth)
for i in closure:
x_new[i] = entry::solve_single_entry_neumann(matrix, b_new, i, max_terms, tolerance)Caller supplies b_new (the new RHS) directly rather than reconstructing
it from b_prev + delta — this is the “I already know what the world
looks like now” path. prev_solution is not used by this function:
the per-entry Neumann is cold-start from D⁻¹b_new. It’s exposed as
a parameter only for API symmetry with solve_on_change and so
callers can pre-bind the same shape.
§Complexity
O(|closure| · max_terms · branching) — independent of n for sparse
DD matrices with bounded max_terms. Pure SubLinear.
§Errors
Returns crate::error::SolverError from the inner per-entry calls
(InvalidInput on a zero diagonal in the closure; DimensionMismatch
on a wrong-sized b_new).
§Examples
// We perturbed b at a few indices; tell me the NEW solution at the
// rows that could have changed — and nowhere else.
let new_entries = solve_on_change_sublinear(
a, prev, b_new, delta,
/*closure_depth=*/ 4,
/*max_terms=*/ 32,
/*tolerance=*/ 1e-10,
).unwrap();
for (row, val) in new_entries {
// wake a downstream observer for `row`
}