Contributing to the web runtime
Katherine Ye edited this page Jun 11, 2021
·
26 revisions
THIS PAGE IS OUT OF DATE
Speed: Note that the optimizer may take multiple optimization steps per display step (currently 10,000
).
- A "display step" is what happens when you click "step" in the frontend and you see the diagram update. It lets you see more of the process, at the cost of speed.
- An "optimization step" is one iterative update to the state of the diagram via a descent method.
- You will have to use a differentiable number type and differentiable operations in all objectives/constraints/computations.
- The parameters to these functions are any kind of expression (
Expr
intypes/types.d.ts
) or, as you see in the existing examples in the file, a shape. If you see something like[t1, s1]: [string, any]
, that's a shape input, wheret1
is the name of the shape ("Text"
, etc.) ands1
is the shape information. You can access the parameter of the shape by doingshapeName.property.contents
, which will return aVarAD
(differentiable floating point number) containing a single number.- For example, if you had a circle
c
as input, and you want its radius, doingc.r.contents
will give you something like5.0
(wrapped in aVarAD
).
- For example, if you had a circle
- Read these tips on debugging optimization (some may not apply in the new system, but most are helpful)
- Add another one to
objDict
inConstraints.ts
. - It should output the "badness" of the inputs (as a number or Tensor), and have local minima where you want the solution to be.
- Add another one to
constrDict
inConstraints.ts
. - Let's say I want the constraint
f(x) <= c
to be true. - I translate it to the zero-based inequality
f(x) - c <= 0
. - I translate the inequality constraint into an energy (penalty)
E(x) = f(x) - c
— it is greater than0
iff the constraint is violated, and the more the constraint is violated, the higher the energy is (e.g. iff(x)
is way bigger thanc
then the energy is a lot bigger than0
). That is the form of all the constraints in the system (and the form you'll be writing them in). It should return a number or Tensor.- You may need to multiply it by some weight d depending on how it compares to the overall magnitude of other constraints/energies in the system.
E(x) = d * (f(x) - c)
- You may need to multiply it by some weight d depending on how it compares to the overall magnitude of other constraints/energies in the system.
- The Penrose runtime automatically substitutes each individual constraint into the penalty function
p(x) = max(x, 0)^2
. This has the effect of ignoring any energy value for a constraint that is satisfied (e.g. iff(x) <= c
thenE(x) < 0
then you can ignore it), and of making the penalty quadratic for any constraint that's violated.- The choice of exponent is arbitrary though squaring seems to work well in practice, as detailed in the notes on exterior point method. Just be careful with how the squaring changes the asymptotic behavior of how you defined the energy originally, e.g. squaring a linear energy works well, but squaring a quadratic may not.
- The Penrose runtime increases a separate weight on all the constraints (multiplicatively by a factor of
10
) for each unconstrained optimization (this is also part of the exterior point method, and you don't have to worry about it, though you should know it's happening).
TODO: give a concrete example here
- If you just want to call it from inside the system (e.g. a helper function for an objective or computation), add it somewhere in
Functions.ts
- The only types a computation can take and return are defined in
types/types.d.ts
, the typeExpr
(and its branches). - You'll have to tag the result of computation with the right type.
- Read these tips on debugging optimization (some may not apply in the new system, but most are helpful)
- Use the web inspector, as described in the README
Found a problem or got a suggestion? Please open a GitHub issue and tag it with documentation
!