Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Porting runtime to the web #336

Merged
merged 87 commits into from
Oct 13, 2020
Merged

Porting runtime to the web #336

merged 87 commits into from
Oct 13, 2020

Conversation

wodeni
Copy link
Member

@wodeni wodeni commented Apr 3, 2020

Description

Related issues: none

This PR will eventually contain a web runtime for Penrose. Short-term goals include:

  • TypeScript types for various data structures for easier pattern-matching in the evaluator
  • Evaluator: given a serialized State, decode it into some data structure with type, and evaluate the translation in the state. Top level function evalTranslation(s : State) : Shapes
  • A subset of computations as arbitrary TS functions

Longer-term goals:

  • Optimizer: progress below. Close to done
  • A subset of constraints in TensorFlow.js compatible format
  • If needed, port the computations to the TensorFlow format as well

See additional documentation on this wiki page.

Implementation strategy and design decisions

  • This branch has more npm dependencies, so you'll have to run npm install.
  • If you run into fsevents related errors, try brew install watchman, which did the trick for me on Mac OS X Catalina

Examples with steps to reproduce them

  • TS definitions from Haskell: stack install && tsdef > types.d.ts
  • Tests for evaluator: npm test in react-renderer

Checklist

  • I have commented my code, particularly in hard-to-understand areas
  • I ran Haddock and there were no errors when generating the HTML site
  • My changes generate no new warnings
  • New and existing tests pass locally using stack test
  • My code follows the style guidelines of this project (e.g.: no HLint warnings)

Open questions

Questions that require more discussion or to be addressed in future development:

Backend runtime related

  • While the design of ArgVal seems convenient for differentiating between GPI and Val, I think it's cleaner if we just treat it as an expression since the GPI values can just be treated as yet another data structure similar to lists. Obviously a few things to consider:
-- Synonyms of GPIs: can a GPI be reused? Is it copied as reference or value?
global { defaultRect = Rectangle { ... } }
Set A { A.shape = global.defaultRect }
Set B { B.shape = global.defaultRect }

-- As discussed a long time before, GPIs as outputs of computation functions
Set A { 
  A.shape = computeRect(...) -- returns Rectangle. Does `computeRect` have to compute all properties?
  A.shape.x = 3.0 -- Does this take precedance over the previous computation?

@wodeni

This comment has been minimized.

@wodeni wodeni self-assigned this Apr 3, 2020
@maxkrieger

This comment has been minimized.

@maxkrieger maxkrieger self-assigned this Apr 3, 2020
@wodeni

This comment has been minimized.

@maxkrieger

This comment has been minimized.

@wodeni

This comment has been minimized.

@maxkrieger

This comment has been minimized.

@wodeni
Copy link
Member Author

wodeni commented Apr 3, 2020

Some more types here. After manually encoding Data.Map.Strict.Map a b as Map<a, b>. Only Map and Record allow non-string keys, and I'm using Map now for benefits noted in an SO post.

In addition to the array encoding of sum type data, the generated types also contain these generics that we don't really need. This will depend a little on tfjs's preferred number encoding, but I'll probably cast everything to number while I write the evaluator.

type Translation<T> = ITrans<T>;

interface ITrans<T> {
  trMap: Map<Name, Map<string, FieldExpr<T>>>;
  warnings: string[];
}

type FieldExpr<T> = IFExpr<T> | IFGPI<T>;

interface IFExpr<T> {
  tag: "FExpr";
  contents: TagExpr<T>;
}

interface IFGPI<T> {
  tag: "FGPI";
  contents: [string, Map<string, TagExpr<T>>];
}

type TagExpr<T> = IOptEval<T> | IDone<T> | IPending<T>;

interface IOptEval<T> {
  tag: "OptEval";
  contents: Expr;
}

interface IDone<T> {
  tag: "Done";
  contents: Value<T>;
}

interface IPending<T> {
  tag: "Pending";
  contents: Value<T>;
}

…pedoc support; change Name type to plain string in the backend
@wodeni
Copy link
Member Author

wodeni commented Apr 5, 2020

Turns out that decoding serialized JSON state requires quite a bit of manual effort (after double-checking with @maxkrieger it seems to be necessary). Some tests in https://github.com/penrose/penrose/blob/95edd0e6d85796f3f7dd3b519e5183360f8eb02a/react-renderer/src/__tests__/Evaluator.test.ts.

I ended up using typedoc over tsdoc for it's automation:
image

@kai-qu kai-qu marked this pull request as draft April 8, 2020 20:13
@kai-qu
Copy link
Contributor

kai-qu commented Jul 28, 2020

@strout18 I added a temp SVG path here for you to use on completing the mod tab for shapes (black line below) in #362. Repro:

image

runpenrose linear-algebra-domain/twoVectorsPerp.sub linear-algebra-domain/linear-algebra-paper-simple.sty linear-algebra-domain/linear-algebra.dsl

(The path is hardcoded in orientedSquare for now; I plan to come back and finish this example later)

Things to finish:

  • orientedSquare implementation with tensors
  • unit mark implementation (commented out in the simple style, original full style to repro is linear-algebra-paper.sty)
  • implement label positioning objective function, atDist
  • calculate curve bbox size for inspector

BTW @wodeni where would be the right place to convert pathData information (in tensors) to normal numbers if autodiff is off? Is this the right place (in resolvePath, when a property value is looked up and returned)? 369d5a5#diff-8b57d4ca1f6e63958534ea22760608a7R436

GeometryCollective and others added 11 commits August 19, 2020 15:08
…s and types to be on autodiff types only (in this case, Tensors). remove autodiff=true flag from evaluator. convert to and from the `number` type for display. factor out computations into a separate file, and convert their types to be autodiff as well
Change "engine" to run on autodiff types only
… but resample still doesn't work for the same reason; fix frontend -> backend JSON (translation conversion); add @keenancrane's hyperbolic `tangentTo` constraint
katherineye and others added 8 commits October 1, 2020 14:47
…bra-domain/twoVectorsPerp.sub linear-algebra-domain/linear-algebra-paper-simple.sty linear-algebra-domain/linear-algebra.dsl`
… with L-BFGS; remove tf.js as dependency; port several examples (including large ones from the paper) to work with new autodiff
Add custom autodiff, energy/gradient compilation, and solver in web-runtime
@wodeni wodeni marked this pull request as ready for review October 12, 2020 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants