(What is this? Check the lab notebook's table of contents)

Entry 007: Improve readability with schematic tables?

Started 2024-11-11
Published 2024-11-18

Purpose

Let's check in. Models in my language look like this:

Animation of that model implemented in this PPL

There's a lot I like, and a lot I don't like, but it turned out that, on balance, I came to dread making models with that notation. 😩 It was enough to extinguish the desire I had to work on this project for quite a while.

I never cooled on probabilistic programming, though. I had a ton of fun writing this in-depth explainer of one inference algorithm. I just put this project on the backburner while I thought of a way forward.

Eventually, I remembered schematic tables!

The fibonacci function as a schematic table

They cleverly constrain dataflow graphs to make data travel only vertically, so that the horizontal dimension can be dedicated to decision-making/conditionals.

If my readability problems lie with how little information the shapes of my models convey, then differentiating program branching and dataflow using X and Y axes like this might help.

Experimental plan

My goal is to implement a schematic table visualization in my modeling environment, then use it to render all the example models I've collected so far to see how they feel:

  1. Tug of war (entry 002)
  2. Sum of biased coin flips (entry 002)
  3. Exam fairness (entry 004)
  4. Anonymous function, used directly (entry 005)
  5. Named function (entry 005)

I've thought a bit about how I'd like probability distributions to appear inline, but I expect these ideas to evolve once I'm working in software and pixels:

A hand-drawn sketch of a schematic table with probability distributions inline

Observations and data

I would waste so much time twiddling pixel coordinates if I tried to lay these tables out by hand, so I implemented a recursive, constraint-based algorithm with familiar primitives like VStack/HStack, Padding, etc:

A code example using the layout API, next to what the UI looks like

Every object participating in the layout system satisfies a simple, familiar interface:

type ProposedSize = {width?: number, height?: number};
type Size = {width: number, height: number};

interface Layoutable {
  root: THREE.Object3D;

  // “Given this much available space, how much would you use?”
  sizeThatFits(availableSize: ProposedSize): Size;

  // “Okay, you get this much space. Arrange your views.”
  layoutForSize(size: Size): void;
}

I ended up with structural Layoutables like EmptyView, VStack, HStack, Spacer, MaterialView, and wrappers FixedFrame, WithBackground, and Padding. This was enough.

Damage calculation

As a warm-up, I recreated Jonathan Edwards's damage calculation example. In this video, the table looks like this:

Jonathan Edwards' schematic table for calculating damage in an imaginary game

I actually got pretty close!

My schematic table for calculating damage in an imaginary game

I didn't write this directly in terms of the Layoutables above, but I used them in all of the accessory views. The table is a new Layoutable for rendering a grid, that sizes each row and column based on the max() of the widths and heights of the views they contain.

The wires are drawn in a separate pass, using the world coordinates of the anchor Object3Ds post-layoutForSize.

Sum of biased coin flips

This model counts the number of heads you get if you flip three biased coins.

Before and after:

Node-and-wire version of the model

Schematic table version of the model

Exam fairness

This model has prior likelihoods of an exam being fair and of a student studying, and updates them based on the outcome of a single student failing.

Node-and-wire version of the model

Node-and-wire version of the model

I had planned to port the tug-of-war and function-calling models, too, but honestly, I'd seen enough.

Discussion of results

Schematic tables are an incontrovertibly better representation for these models than what I had before. The results speak for themselves!

The layout library makes it easy to create these tables, too. Every time I was unhappy with the way something looked, I could fix it with a few Spacers or Paddings. As with previous prototypes, this is a visualization, and not directly editable, so I don't have a signal yet about whether it's good for that.

And finally, I'm very pleased with the affordance for inline charts. I see tons of options.

Conclusion

Schematic tables will be my starting point for visualizations going forward. I'm psyched!