The JAX printer (trusted) #
A typed program P of the flow signature, with its roles ρ, is printed as two JAX functions
that also return the log-weight: the forward function from the lines of P, and the inverse
from the lines of the inverse program P† (Prog.inverse, the schedule of the recipes of the
derivation). The inverse program is typed too, with its own roles ρ† (inferred), and both are
printed by the same code (emitFwd): the log-weight is L_θ, the sum of ℓ_o over the spine
steps, accumulated in ld with one ld += ℓ_o on each spine step's row, the ; aligned. For
P† it is the log-weight of Prog.density for P†; that it agrees a.e. with -L_θ at the
values P† recomputes (Prog.inverse_density) is not proved (TODO.md), but checked by
scripts/compare.py. Every variable is a Python expression; structural operations (split,
the changes of sort) emit slices or nothing, the others bind a fresh variable; a spine step that
prints nothing gets a row pass ; ld += ….
Each stage is a definition (Linked.add) printed as {name}_fwd, {name}_inv over its own
weights. A model is printed as one program flow_fwd (and its inverse program flow_inv),
so the stage pipeline is a typed program rather than a Python composition: its stages inlined
(Flow.modelProg), or, with calls, a call of each stage (Flow.callProg), a row
y, l = {name}_fwd(w[a:b], x) ; ld += l. A call is a spine step like any other, and the inverse
program calls {name}_inv. The roles are inferred (Prog.infer) on each stage and on the model.
writeModule refuses a model or a stage that is not typed, or whose inverse program is not.
The leaf table (one JAX expression per operation and per nonzero log-weight) is trusted: it is
written to agree with Flow.semOp and Flow.ℓOp. Functions act on one example; the caller
batches with jax.vmap.
The printer's state #
The rows so far: the code, and the log-weight statement after its
;("": none).- next : ℕ
Each permutation's expression (on
x, of lengthn) with its index list, for<module>_perms.py.
Instances For
Instances For
Equations
- RoleFlow.Flow.Print.emitLine l = modify fun (g : RoleFlow.Flow.Print.Gen) => { lines := g.lines.push (l, ""), next := g.next, permChecks := g.permChecks }
Instances For
Bind an expression to a fresh variable.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Permutations #
A permutation is printed as its steps (Flow.PermS), one numpy call each, applied in order; its
inverse as the steps of PermS.inv. writeModule also writes each permutation's expression with
its index list (PermS.idxList) to <module>_perms.py, which checks that numpy agrees.
The comma-separated numbers.
Equations
- RoleFlow.Flow.Print.numsE l = ", ".intercalate (List.map toString l)
Instances For
A step applied to the expression x; the result keeps the step's shape (reshape reads
row-major, so the next step can reshape it directly).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The steps applied to the flat vector x, in order, flattened at the end; steps that do
nothing (PermStep.isId) are left out.
Equations
- RoleFlow.Flow.Print.permStepsE x ps = match List.filter (fun (x : RoleFlow.Flow.PermStep) => !x.isId) ps with | [] => x | qs => List.foldl RoleFlow.Flow.Print.stepE x qs ++ ".reshape(-1)"
Instances For
The empty vector is printed as bool, which jnp.concatenate promotes to the dtype of what
it is joined with.
Equations
- RoleFlow.Flow.Print.concatE [] = "jnp.zeros(0, bool)"
- RoleFlow.Flow.Print.concatE x✝ = toString "jnp.concatenate([" ++ toString (", ".intercalate x✝) ++ toString "])"
Instances For
Several values as one Python value: a tuple, or the value itself.
Equations
- RoleFlow.Flow.Print.tupE [e] = e
- RoleFlow.Flow.Print.tupE x✝ = toString "(" ++ toString (", ".intercalate x✝) ++ toString ")"
Instances For
Leaves #
The function computing Ref.logpdf, where it is not 0.
Equations
Instances For
An operation's results from its arguments, one expression per result; agrees with
Flow.semOp.
Equations
- One or more equations did not get rendered due to their size.
- RoleFlow.Flow.Print.emitOp RoleFlow.Flow.FOp.nil x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE "jnp.zeros(0, bool)" pure [__do_lift]
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.concat m n) x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE (RoleFlow.Flow.Print.concatE x✝) pure [__do_lift]
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.rebase r r' n) x✝ = pure x✝
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.relu n) x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE (toString "jax.nn.relu(" ++ toString (x✝.headD "") ++ toString ")") pure [__do_lift]
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.tanh n) x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE (toString "jnp.tanh(" ++ toString (x✝.headD "") ++ toString ")") pure [__do_lift]
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.layernorm n) x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE (toString "layernorm(" ++ toString (x✝.headD "") ++ toString ")") pure [__do_lift]
- RoleFlow.Flow.Print.emitOp (RoleFlow.Flow.FOp.mul n) x✝ = do let __do_lift ← RoleFlow.Flow.Print.bindE (toString (x✝.getD 0 "") ++ toString " * " ++ toString (x✝.getD 1 "")) pure [__do_lift]
Instances For
The log-weight ℓ_o on the arguments, where it is not 0; agrees with Flow.ℓOp
(rebase r r' has log ρ_{r'} - log ρ_r, a term for each density that is not 1;
oddpow_logdet p x is Σ log p x^(p-1), which opowLogdet sets to 0 on the null set of the
axes;
triu_logdet c n U = n Σ_a U_aa is triuLogdet c n U).
Equations
- One or more equations did not get rendered due to their size.
- RoleFlow.Flow.Print.ldOp x✝ = none
Instances For
Calls #
The weights at the positions ps, as a list: a slice w[a:b] if they are the function's
own weights a, …, b - 1.
Equations
- One or more equations did not get rendered due to their size.
- RoleFlow.Flow.Print.weightsE env [] = "[]"
Instances For
A row calling {name}_fwd (or _inv) on the weights ws and the values x, binding its
nb results and its log-weight; returns their expressions.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Programs #
An operation of the signature the printed program is over: of the flow signature, or a call
(Linked.view).
Equations
- RoleFlow.Flow.Print.View Sg = ({as bs : List RoleFlow.Flow.FS} → Sg.Op as bs → RoleFlow.Callee RoleFlow.Flow.flowSig.Op as bs)
Instances For
Print the lines from the expressions of the context they start in, each spine step with
its ℓ_o (for a call, the log-weight it returns); returns the expressions of all variables, by
position.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The column of the ;: after the longest row that has a log-weight statement, ignoring rows
longer than this.
Equations
Instances For
The function of P from the expressions of its weights and inputs: the returned expressions,
after the rows that compute them and accumulate the log-weight.
Equations
- One or more equations did not get rendered due to their size.
Instances For
{name}_fwd from P with its roles ρ, and {name}_inv from P† = P.inverse ρ with its
roles ρi, both with the log-weight. The weights are the list w.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Modules #
Helpers the leaf table refers to, matching Flow.FlowOps.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The postamble: the model's forward/inverse (the model as one program) and
init_weights.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The definitions of a tower, in order, each with the dimensions and inits of the weights of the stage of its name.
Equations
- One or more equations did not get rendered due to their size.
- RoleFlow.Flow.Print.emitDefs stages RoleFlow.Linked.base = pure []
Instances For
The module: the stages, the model (flow_fwd from P, flow_inv from P†), and the
Python interface; with each permutation's expression and index list.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A script that checks each permutation's numpy expression, applied to 0, …, n - 1, against
its index list (as Lean computes it).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The operation, if it is a permutation that is not PermS.valid (its index map is then not a
permutation, and the model does not read it as the steps).
Equations
- One or more equations did not get rendered due to their size.
- RoleFlow.Flow.Print.badPerm? x✝ = none
Instances For
Certify a model: add each stage, after the front end (swapArgs), as a definition of a
tower (Linked.add, with its roles and its inverse program's, inferred), then infer the roles
of the model as one program and of its inverse program: the stages inlined (modelProg, after
the front end), or, with calls, a call of each (callProg). Fails if something is not typed,
if two stages have one name, or if a permutation is not valid.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Certify a model (certify) and write its module, and <module>_perms.py
(permCheckScript).
Equations
- One or more equations did not get rendered due to their size.