Go to file
2024-09-15 16:33:56 -04:00
more allow models to also be executables 2024-07-12 18:29:55 -04:00
pretty remove extra f in pretty print 2024-08-12 12:34:28 -04:00
sample fix correlation problem by using global variable 2024-06-10 03:08:10 +02:00
simple more feng shui 2024-06-19 10:41:47 -04:00
fermi.go add real life examples + simplify multiply code. 2024-09-15 16:33:56 -04:00
go.mod fix types 2024-06-09 22:46:08 +02:00
makefile rename f.go=>fermi.go after fixing nvim problem 2024-07-12 18:13:24 -04:00
README.md add real life examples + simplify multiply code. 2024-09-15 16:33:56 -04:00

A calculator for distributions, for Fermi estimation

This project is a minimalist, calculator-style DSL for fermi estimation. It can multiply, divide, add and substract scalars, lognormals and beta distributions, and supports variables.

Motivation

Sometimes, Squiggle, simple squiggle or squiggle.c are still too complicated and un-unix-like.

Installation

make build
sudo make install
fermi 

Usage

$ fermi
5000000 12000000
=> 5.0M 12.0M
* beta 1 200
=> 1.9K 123.1K
* 30 180
=> 122.9K 11.7M
/ 48 52
=> 2.5K 234.6K
/ 5 6
=> 448.8 43.0K
/ 6 8
=> 64.5 6.2K
/ 60
=> 1.1 103.7

Perhaps this example is more understandable with comments and better units:

$ fermi
5M 12M           # number of people living in Chicago
beta 1 200       # fraction of people that have a piano
30 180           # minutes it takes to tune a piano, including travel time
/ 48 52          # weeks a year that piano tuners work for
/ 5 6            # days a week in which piano tuners work
/ 6 8            # hours a day in which piano tuners work
/ 60             # minutes to an hour
=: piano_tuners

If you type "help", you can see a small grammar:

$ fermi
help
  Operation | Variable assignment | Special
    Operation:                             operator operand
          operator:                        (empty) | * | / | + | -
          operand:                         scalar | lognormal | beta | variable
            lognormal:                     low high
            beta:                          beta alpha beta
    Variable assignment:                   =: variable_name
    Variable assignment and clear stack:   =. variable_name
    Special:
         Comment:                          # this is a comment
         Clear stack:                      clear | c | .
         Print debug info:                 debug | d
         Print help message:               help  | h
         Start additional stack:           operator (
         Return from additional stack      )
         Exit:                             exit  | e
  Examples:
    + 2
                    # this is a comment
    / 2.5           # this is an operation followed by a comment
    * 1 10          # "low high" is interpreted as lognormal
    + 1 10
    * beta 1 10
    1 10            # multiplication taken as default operation)
    =: x
    .               # return the stack to 1.
    1 100
    + x
    * 1 12 
    * (
    1 10
    + beta 1 100
    )
    =. y            # save to variable and clear stack
    exit

You can see real life examples here, here, here, here, here, here

Tips & tricks

  • It's conceptually clearer to have all the multiplications first and then all the divisions
  • For things between 0 and 1, consider using a beta distribution

Command line options

You can specify the number of samples to draw when algebraic manipulations are not sufficient:

$ fermi -n 1000000
$ fermi -n 1_000_000

You also run a file with the -f option

$ fermi -f more/piano-tuners.fermi 

Integrations with linux utilities

Because the model reads from standard input, you can a model to it:

$ cat more/piano-tuners.fermi | fermi

You can make a model an executable file by running $ chmod -x model.fermi and then adding the following at the top!

#!/bin/usr/fermi -f

You can save a session to a logfile with tee:

fermi | tee -a fermi.log

Different levels of complexity

The top level f.go file (420 lines) has a bunch of complexity: variables, parenthesis, samples, beta distributions, number of samples, etc. In the simple/ folder:

  • f_simple.go (370 lines) strips variables and parenthesis, but keeps beta distributions, samples, and addition and substraction
  • f_minimal.go (140 lines) strips everything that isn't lognormal and scalar multiplication and addition, plus a few debug options.

Roadmap

Done:

  • Write README
  • Add division?
  • Read from file?
  • Save to file?
  • Allow comments?
    • Use a sed filter?
    • Add proper comment processing
  • Add show more info version
  • Scalar multiplication and division
  • Think how to integrate with squiggle.c to draw samples
    • Copy the time to botec go code
    • Define samplers
    • Call those samplers when operating on distributions that can't be operted on algebraically
  • Display output more nicely, with K/M/B/T
  • Consider the following: make this into a stack-based DSL, with:
    • Variables that can be saved to and then displayed
    • Other types of distributions, particularly beta distributions? => But then this requires moving to bags of samples. It could still be ~instantaneous though.
    • Added bags of samples to support addition and multiplication of betas and lognormals
  • Figure out go syntax for
    • Maps
    • Joint types
    • Enums
  • Fix correlation problem, by spinning up a new randomness thing every time some serial computation is done.
  • Clean up error code. Right now only needed for division
  • Maintain both a more complex thing that's more featureful and the more simple multiplication of lognormals thing.
  • Allow input with K/M/T
  • Document parenthesis syntax
  • Specify number of samples as a command line option
  • Figure out how to make models executable, by adding a #!/bin/bash-style command at the top?
  • Make -n flag work
  • Add flag to repeat input lines (useful when reading from files)

To (possibly) do:

  • Add functions. Now easier to do with an explicit representation of the stakc
  • Think about how to draw a histogram from samples
  • Dump samples to file
  • Represent samples/statistics in some other way
  • Perhaps use qsort rather than full sorting
  • Program into a small device, like a calculator?

Discarded:

  • Think of some way of calling bc