Skip to main content

Crate handwired_rs

Crate handwired_rs 

Source
Expand description

Exact programs as neural nets: a Rust port of the core of handwired.

A program is a fixed list of f32 operations, mostly weighted sums and products with a ReLU, written with builder code that runs once. Because it uses only these primitives, it compiles into layers of sparse matrix multiplications and stays differentiable, while computing exactly what the equivalent ordinary code computes.

use handwired_rs::{emit_compare, Circuit, Relation};

// const result = (a > 4) ? 10 : 12, for an integer a within 0..100.
let mut circuit = Circuit::new(1);
let a = circuit.source(0);
circuit.assume_range(a, 0.0, 100.0);
circuit.assume_grid(a, 1.0);
let four = circuit.constant(4.0);
let above_four = emit_compare(&mut circuit, a, Relation::Greater, four);
let result = circuit.affine(above_four * -2.0 + 12.0);

for value in 0..=100 {
    let values = circuit.evaluate_reference(&[value as f32]).unwrap();
    assert_eq!(values[result.index()], if value > 4 { 10.0 } else { 12.0 });
}

Builder methods panic when a contract is violated, e.g. a comparison on an operand without a finite declared range, since that is a bug in the program being built. Evaluation returns Error for bad input data.

Modules§

dsl
The runtime half of #[handwired].

Structs§

BackpropOptions
CandidateTable
CellSpec
Circuit
CompareOptions
IndexRead
IndexReadRow
Lin
An affine form: bias + Σ coefficient × wire, with terms in the order they were written. Ordinary builder methods sort and merge terms; the rounding-preserving ones, e.g. Circuit::round_affine, keep this order.
Operation
Range
The range of values a wire may hold. An open side is infinite.
SourceTable
TensorExecutor
Reusable buffers for running one program many times.
TensorLayer
TensorProgram
Wire
The position of a source cell or of an operation’s result.

Enums§

BooleanGradient
Gradient rule at a boolean atom, which is a step function.
Error
IndexGradient
Gradient rule for the index of an index read, which is a step function.
Macro
The builder operation a wire came from, so the backward pass can differentiate the whole product or select instead of its ReLUs one by one.
OpKind
OutOfRange
What an index read returns when floor(index) is outside the table.
Policy
What happens to a cell around an evaluation.
Relation
RoundingPointKind
Why an operation’s FP32 evaluation, term order or operand wires carry meaning. See handwired’s docs/execution-model.md, “Rounding points”.

Functions§

constant
emit_and
bits.all(): relu(sum - (n - 1)), exact for exact bits.
emit_clamp_exact
min(max(value, minimum), maximum), as exactly one of the operands.
emit_compare
[a relation b] as an exact bit, equal to the native f32 comparison for every pair of values within the declared ranges. Both operands need finite declared ranges. When both lie on grids, the bit is built from the integer D = (a - b) / grid in 2 or 3 operations; otherwise a sign cascade lifts every nonzero f(a - b), down to 2^-149, to at least 1.
emit_compare_with
emit_maximum
max(a, b) rebuilt through a rounded difference: b + relu(a - b). Not always exactly one of the operands; see emit_maximum_exact.
emit_maximum_exact
max(a, b) as exactly one of the operands. Ties return a.
emit_minimum
min(a, b) rebuilt through a rounded difference: a - relu(a - b), e.g. 0.29998779 for min(f(1000.37), f(0.3)). See emit_minimum_exact.
emit_minimum_exact
min(a, b) as exactly one of the operands, e.g. f(0.3) for min(f(1000.37), f(0.3)). Ties return a. Needs finite declared ranges, like emit_compare.
emit_not
!bit for an exact bit.
emit_or
bits.any(): 1 - relu(1 - sum), exact for exact bits.
emit_relu
max(0, value).
emit_round
Math.round(x) for |x| below 2^22: FP32 values within 2^23..2^24 are whole numbers, so adding and then subtracting 2^23 + 2^22 rounds (ties to even). Both steps are marked rounding points.
emit_select
gate ? on : off for a gate of exactly 0 or 1. Both sides always compute.
event
input
input_bit
state
state_bit

Type Aliases§

Term
One term of an affine form: a wire and its coefficient. Coefficients are kept in f64 like handwired’s, and rounded to f32 when evaluated.

Attribute Macros§

handwired