TensorCode Docs

DocsPythonStart here

Algorithms across substrates#

tensorcode.algorithm represents a bounded tensor algorithm independently of how it executes. Author the algorithm once, compile it to a symbolic executor, a native differentiable circuit, or a scheduled attention machine, train its explicit parameters, and export the updated algorithm. The JSON artifact is shared with TypeScript's tensorcode/algorithm.

Install the current checkout with pip install -e '.[algorithm]'. The symbolic executor requires NumPy. Importing this entry point does not import PyTorch; compiling neural substrates does. The existing scalar tensorcode.program API and its artifact format remain separate and unchanged.

Compile an algorithm#

from tensorcode.algorithm import compile, compare, convert

algorithm = compile('''def policy(position, velocity, target, gain):
    error = target - position
    return {"torque": (gain * error - 2.5 * velocity).clip(-8, 8)}
''', inputs={"position": (20,), "velocity": (20,), "target": (20,)},
     parameters={"gain": 30.0})

symbolic = algorithm.compile("alg0")
circuit = algorithm.compile("alg1")
attention = algorithm.compile("alg2")
case = {"position": [0.0] * 20, "velocity": [0.0] * 20,
        "target": [0.1] * 20}

assert compare(symbolic, attention, [case])["passed"]
updated_symbolic = convert(attention, "alg0")
print(updated_symbolic(case)["torque"])

The frontend parses the source AST. It never executes supplied Python. Supported source includes assignments, arithmetic, comparisons, conditional expressions, literal-range loops, and the documented tensor methods. Loops unroll at compile time, and exact integer arithmetic on literals and loop variables folds at compile time so it can form slice bounds. Arbitrary calls, imports, recursion, while loops, exceptions and host effects are rejected. Conditional expressions and where are eager: both branches must be valid. This differs from the scalar compiler's lazy selection.

Use AlgorithmBuilder for explicit graphs, graph composition and attention. Each variable has a statically known shape. Inputs require exactly those shapes; there are no implicit batch dimensions. All computation uses the artifact's float32 or float64 dtype. Comparisons produce numeric zero/one values and have no learned surrogate derivative.

Execution contracts#

TargetImplementationContract
alg0NumPy reference interpreterDeclared tensor operations and explicit state
alg1Native PyTorch computation graphSame operations, native autograd, backend numerical tolerance
alg2, hard routingScaled dot-product attention over operand registers, followed by declared local operationsExact operand selection; backend numerical tolerance
alg2, soft routingFinite structural penalties plus contextual QK logitsApproximate execution; validate before use
alg2_biasRelations projected into existing attention through learned or supplied bindingsStructural prior, not an execution guarantee

ALG.2 hard execution is a scheduled neural/symbolic attention machine. Its instruction schedule and local arithmetic are supplied by the compiler. It is not an assertion that arbitrary algorithms have been converted into an ordinary fixed-depth pretrained transformer. All compiled machines expose manifest() to make these distinctions inspectable.

Each instruction's argument roles become separate directed relations. Query row i, key column j means instruction i reads source j. In the attention machine, previous register values are padded into a value memory, and actual scaled dot-product attention retrieves each argument. Hard masks allow exactly one source per argument. Soft routing allows other earlier registers with a finite penalty; it can change behavior even if the graph is correct.

context= may supply a [node_count, context_dim] tensor to an attention machine. With hard single-source masks its content logits cannot change operand selection. With soft routing they can. The default context is zero. This explicit binding must not be confused with a model learning what every algorithm variable means.

Structural compilation into a pretrained transformer#

The prior target implements:

bias[head] = sum_role strength[head, role] * Pquery @ Arole @ Pkey.T

Arole comes from the authored algorithm. The query and key binding networks are independent and include an edge-free null slot. They are initially untrained. Users may train them with their own task objective or supply explicit probability distributions over algorithm nodes plus null. Relation strengths start at zero.

from tensorcode.algorithm import StructuralBias, BiasedMultiheadAttention

bias_model = algorithm.compile("alg2_bias", hidden_dim=768, heads=12)
# query_latents/key_latents: [batch, tokens, hidden_dim]
# bias = bias_model(query_latents, key_latents)  # [batch, heads, queries, keys]
# Add bias to scaled QK logits before softmax, retaining the original legal mask.

# For an existing torch.nn.MultiheadAttention:
# adapter = BiasedMultiheadAttention.from_module(pretrained_attention, algorithm)
# output, weights = adapter(query_latents, key_latents, values)

from_module copies existing projections, accepts batch-first equal-width attention without extra key/value tokens or dropout, and freezes those projections by default. from_projections(q, k, v, out, algorithm, heads=...) accepts four standard pretrained Linear projections using 1/sqrt(head_dim) scoring. This factory does not automatically patch a model or invent positional semantics. Pass any original attention and padding masks explicitly. Extra new tokens are not inserted, so the original softmax denominator is preserved at zero bias. Numerical backend changes can still introduce floating-point differences.

checkpoint() and restore() persist the complete adapter, including its owned projection weights, binding weights, relation strengths and dtype, as data-only objects. They do not serialize Python code or pickle executable modules.

Run the pretrained integration check using a locally cached pinned checkpoint:

python examples/algorithms/pretrained_attention_bias.py \
  --image /path/to/observed-image.png \
  --output /tmp/pretrained-bias-check.json

The pretrained attention example checks a pinned local CLIP checkpoint on an actual image. Its measured result is function preservation at zero bias, gradient flow, and changed output at nonzero bias. It does not show that CLIP understands or executes a robotics policy.

Train and convert back#

Both neural execution targets are torch.nn.Module instances. Parameters declared in the algorithm are registered parameters; ordinary optimizers update them. artifact() exports their current values, rather than stale initialization values.

import torch

optimizer = torch.optim.Adam(attention.parameters(), lr=0.01)
optimizer.zero_grad()
result = attention(case)["torque"]
loss = (result - torch.ones(20, dtype=torch.float64)).square().mean()
loss.backward()
optimizer.step()

trained = attention.artifact()
restored = type(trained).from_json(trained.to_json())
standalone_source = trained.to_python("policy")

to_python emits readable standalone NumPy code returning (outputs, next_state). Artifact loading never evaluates this source. freeze() replaces explicit parameters with constants. optimize() removes unreachable instructions while preserving the public input/state/parameter signature.

A hard attention machine can round-trip through ALG.0 and ALG.1. A soft machine cannot silently export its nominal algorithm as an equivalent implementation: artifact() and exact conversion reject that request. Its checkpoint() preserves its approximation settings. Any symbolic replacement needs separate validation.

State and recurrence#

from tensorcode.algorithm import AlgorithmBuilder

b = AlgorithmBuilder(name="filter")
x = b.input("sample", (3,))
state = b.state("estimate", [0., 0., 0.])
alpha = b.parameter("alpha", 0.2)
next_estimate = state + alpha * (x - state)
b.update(state, next_estimate)
filter_algorithm = b.build(next_estimate)

module = filter_algorithm.compile("alg2")
outputs, next_state = module.step({"sample": [1., 2., 3.]})
outputs, next_state = module.step({"sample": [2., 3., 4.]}, state=next_state)

State updates are simultaneous. Neither executor mutates caller state; failures produce no partial state commit. unroll(sequence, state=...) on Python modules retains the state computation graph for backpropagation through time. Optional detach_every requests explicit truncated gradients. There is no hidden simulator or event loop in the framework.

Import supported trained computation#

from_module imports current weights from supported PyTorch Sequential, Linear, ReLU, Sigmoid, Tanh, last-axis LayerNorm, Softmax and Identity modules. from_attention imports supported multi-head self-attention, including QK, OV, softmax and an optional causal mask. Unsupported modules fail closed.

These factories do not require TensorCode compiler provenance. They reproduce the supported neural computation as an algorithm artifact. They do not discover a compact semantic algorithm from an arbitrary pretrained model. Layer normalization is represented explicitly; it is not silently linearized.

Validation and boundaries#

compare(reference, candidate, cases, rollout=True) compares both outputs and state across the supplied trajectory, allowing each implementation to carry its own state forward. It reports tolerance, number of cases, maximum error and the first counterexample. Empty evaluations are rejected. validate_replacement rejects a candidate when comparison fails. These reports are empirical, not continuous-domain proofs, and do not establish task quality by themselves.

Artifacts reject unsupported versions, unknown node fields, invalid dependencies, shape inconsistencies, nonfinite data and oversized individual tensors. Execution rejects fully masked attention rows and nonfinite intermediate results. Limits are 10,000 nodes, rank six, and one million elements per tensor; dense attention register memory has a separate budget. These bounds are not a sandbox for executing untrusted workloads. No arbitrary host callbacks are available.

G1 robotics application#

The robotics lab uses this framework for sensor-relative manipulation trajectory retargeting alongside a pinned pretrained Unitree G1 walker. The controller consumes RGB-D, IMU, encoders and contacts; simulator poses are reserved for scoring and replay. Runtime trajectory context compiles through ALG.0/1/2 without weight updates. This is authored retargeting, not learned video-only ICL. See the policy comparison and reproduction guide.

Composable task prerequisites#

compile_schedule turns a bounded acyclic prerequisite mapping into an ordinary portable algorithm. Vector indices follow mapping insertion order. It accepts completed and enabled vectors (values >= 0.5 mean true), and returns ready for enabled, unfinished tasks whose prerequisites are complete. Dispatch and completion evidence are explicit caller responsibilities. Invalid names, unknown or duplicate prerequisites, cycles and graphs over 256 tasks are rejected.

from tensorcode.algorithm import compile_schedule
schedule = compile_schedule({"inspect": [], "pick": ["inspect"], "release": ["pick"]})
ready = schedule.compile("alg2")({"completed": [1, 0, 0], "enabled": [1, 1, 1]})
# ready["ready"] is [0, 1, 0]

Use AlgorithmBuilder.include to compose readiness with application decisions. These hard predicates are authored rules, not a differentiable relaxation of task success. They neither infer task graphs nor replace observation validation.