Solving 2x2 linear systems — Cramer's rule via determinants
For A·x = b with A 2x2, Cramer's rule gives x_i = det(A_i)/det(A), where A_i is A with column i replaced by b. det() is the matrix builtin. A zero determinant means the system is singular (no unique solution).
A Soma program from the math part of the verified corpus: 46 lines, cells LinearSolve, SolveTests. It passes soma check with soma 3.2.4.
How it is built
The cell LinearSolve declares 2 signals in its face: solve2(a: Float, b: Float, c: Float, d: Float, e: Float, f: Float) -> List and run() -> Map. Handlers: solve2 (line 19) and run (line 28).
The file also holds 1 test cell (SolveTests) with 4 assertions, run by soma test.
The source
linear_solve.cell
// ============================================================================
// Solving 2x2 linear systems — Cramer's rule via determinants
// ============================================================================
//
// For A·x = b with A 2x2, Cramer's rule gives x_i = det(A_i)/det(A), where
// A_i is A with column i replaced by b. det() is the matrix builtin. A zero
// determinant means the system is singular (no unique solution).
//
// soma run linear_solve.cell run
// ============================================================================
cell LinearSolve {
face {
signal solve2(a: Float, b: Float, c: Float, d: Float, e: Float, f: Float) -> List
signal run() -> Map
}
// solve [a b; c d] x = [e; f]
on solve2(a: Float, b: Float, c: Float, d: Float, e: Float, f: Float) {
let A = [a, b, c, d].reshape(2, 2)
let detA = det(A)
if abs(detA) < 0.0000000001 { return [] } // singular
let dx = det([e, b, f, d].reshape(2, 2))
let dy = det([a, e, c, f].reshape(2, 2))
return [dx / detA, dy / detA]
}
on run() {
// 2x + y = 5 ; x + 3y = 10 -> x=1, y=3
let sol = solve2(2.0, 1.0, 1.0, 3.0, 5.0, 10.0)
return map("x", sol[0], "y", sol[1])
}
}
cell test SolveTests {
rules {
// 2x+y=5, x+3y=10 -> x=1, y=3
assert abs(solve2(2.0, 1.0, 1.0, 3.0, 5.0, 10.0)[0] - 1.0) < 0.0000001
assert abs(solve2(2.0, 1.0, 1.0, 3.0, 5.0, 10.0)[1] - 3.0) < 0.0000001
// x+y=2, x-y=0 -> x=1, y=1
assert abs(solve2(1.0, 1.0, 1.0, 0 - 1.0, 2.0, 0.0)[0] - 1.0) < 0.0000001
// singular system returns empty
assert len(solve2(1.0, 2.0, 2.0, 4.0, 3.0, 6.0)) == 0
}
}What the toolchain says
$ soma check linear_solve.cell
✓ All checks passed.$ soma test linear_solve.cell
test SolveTests ...
✓ assert abs(solve2(2.0, 1.0, 1.0, 3.0, 5.0, 10.0)[0] - 1.0) < 0.0000001
✓ assert abs(solve2(2.0, 1.0, 1.0, 3.0, 5.0, 10.0)[1] - 3.0) < 0.0000001
✓ assert abs(solve2(1.0, 1.0, 1.0, 0 - 1.0, 2.0, 0.0)[0] - 1.0) < 0.0000001
✓ assert len(solve2(1.0, 2.0, 2.0, 4.0, 3.0, 6.0)) == 0
4 tests: 4 passed, 0 failed$ soma verify linear_solve.cell
Verifying linear_solve.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)$ soma run linear_solve.cell run
{"x": 1.0, "y": 3.0}