Vector operations — dot product, norm, cosine similarity
Vectors are plain lists. dot() zips two lists and sums the pairwise products; norm is sqrt of the self-dot; cosine similarity normalizes the dot by the product of the norms. Reductions (sum) and zip do the work.
A Soma program from the math part of the verified corpus: 56 lines, cells VectorOps, VectorTests. It passes soma check with soma 3.2.4.
How it is built
The cell VectorOps declares 4 signals in its face: dot(a: List, b: List) -> Float, norm(a: List) -> Float, cosine(a: List, b: List) -> Float and run() -> Map. Handlers: dot (line 20), norm (line 25), cosine (line 29) and run (line 33).
The file also holds 1 test cell (VectorTests) with 4 assertions, run by soma test.
The source
vector_ops.cell
// ============================================================================
// Vector operations — dot product, norm, cosine similarity
// ============================================================================
//
// Vectors are plain lists. dot() zips two lists and sums the pairwise
// products; norm is sqrt of the self-dot; cosine similarity normalizes the
// dot by the product of the norms. Reductions (sum) and zip do the work.
//
// soma run vector_ops.cell run
// ============================================================================
cell VectorOps {
face {
signal dot(a: List, b: List) -> Float
signal norm(a: List) -> Float
signal cosine(a: List, b: List) -> Float
signal run() -> Map
}
on dot(a: List, b: List) {
let prods = zip(a, b) |> map(p => p.left * p.right)
return sum(prods)
}
on norm(a: List) {
return sqrt(dot(a, a))
}
on cosine(a: List, b: List) {
return dot(a, b) / (norm(a) * norm(b))
}
on run() {
let u = [3, 4]
let v = [4, 3]
return map(
"dot", dot(u, v),
"norm_u", norm(u),
"cosine", cosine(u, v)
)
}
}
cell test VectorTests {
rules {
// 3*4 + 4*3 = 24
assert dot([3, 4], [4, 3]) == 24
// |(3,4)| = 5
assert norm([3, 4]) == 5.0
// orthogonal vectors have zero dot, cosine 0
assert dot([1, 0], [0, 1]) == 0
// identical unit-ish vectors have cosine 1
assert abs(cosine([1, 2], [1, 2]) - 1.0) < 0.0000001
}
}What the toolchain says
$ soma check vector_ops.cell
✓ All checks passed.$ soma test vector_ops.cell
test VectorTests ...
✓ assert dot([3, 4], [4, 3]) == 24
✓ assert norm([3, 4]) == 5.0
✓ assert dot([1, 0], [0, 1]) == 0
✓ assert abs(cosine([1, 2], [1, 2]) - 1.0) < 0.0000001
4 tests: 4 passed, 0 failed$ soma verify vector_ops.cell
Verifying vector_ops.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 vector_ops.cell run
{"dot": 24, "norm_u": 5.0, "cosine": 0.96}