Compare commits
	
		
			2 Commits
		
	
	
		
			8b88beae88
			...
			7ff3b2148e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7ff3b2148e | |||
| c335917226 | 
							
								
								
									
										123
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								README.md
									
									
									
									
									
								
							|  | @ -1,17 +1,23 @@ | ||||||
| # A minimalist calculator for f estimation | # A minimalist calculator for fermi estimation | ||||||
| 
 | 
 | ||||||
| This project is a minimalist, stack-based DSL for f estimation. It can multiply and divide scalars, lognormals and beta distributions. | This project is a minimalist, stack-based DSL for fermi estimation. It can multiply, divide, add and substract scalars, lognormals and beta distributions. | ||||||
| 
 | 
 | ||||||
| ## Motivation | ## Motivation | ||||||
| 
 | 
 | ||||||
| Sometimes, [Squiggle](https://github.com/quantified-uncertainty/squiggle), [simple squiggle](https://git.nunosempere.com/quantified.uncertainty/simple-squiggle) or [squiggle.c](https://git.nunosempere.com/personal/squiggle.c) are still too complicated and un-unix-like. | Sometimes, [Squiggle](https://github.com/quantified-uncertainty/squiggle), [simple squiggle](https://git.nunosempere.com/quantified.uncertainty/simple-squiggle) or [squiggle.c](https://git.nunosempere.com/personal/squiggle.c) are still too complicated and un-unix-like. | ||||||
| 
 | 
 | ||||||
| ## Usage | ## Installation | ||||||
| 
 |  | ||||||
| Here is an example |  | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| $ go run f.go | make build | ||||||
|  | sudo make install | ||||||
|  | fermi  | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Usage | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ fermi | ||||||
| 5000000 12000000 | 5000000 12000000 | ||||||
| => 5.0M 12.0M | => 5.0M 12.0M | ||||||
| * beta 1 200 | * beta 1 200 | ||||||
|  | @ -31,18 +37,18 @@ $ go run f.go | ||||||
| Perhaps this example is more understandable with comments and better units: | Perhaps this example is more understandable with comments and better units: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| $ sed -u "s|#.*||" | sed -u 's|M|000000|g' | go run f.go | $ fermi | ||||||
| 5M 12M # number of people living in Chicago | 5M 12M        # number of people living in Chicago | ||||||
| => 5.0M 12.0M | => 5.0M 12.0M | ||||||
| * beta 1 200 # fraction of people that have a piano | * beta 1 200  # fraction of people that have a piano | ||||||
| 1.9K 123.1K | 1.9K 123.1K | ||||||
| 30 180 # minutes it takes to tune a piano, including travel time | 30 180        # minutes it takes to tune a piano, including travel time | ||||||
| 122.9K 11.7M | 122.9K 11.7M | ||||||
| / 48 52 # weeks a year pianotuners work for | / 48 52       # weeks a year pianotuners work for | ||||||
| 2.5K 234.6K | 2.5K 234.6K | ||||||
| / 6 8 # hours a day | / 6 8         # hours a day | ||||||
| 353.9 34.1K | 353.9 34.1K | ||||||
| / 60 # minutes to an hour | / 60          # minutes to an hour | ||||||
| 5.9 568.3 | 5.9 568.3 | ||||||
| =: piano_tuners_in_Chicago | =: piano_tuners_in_Chicago | ||||||
| piano_tuners_in_Chicago => 5.9 568.3 | piano_tuners_in_Chicago => 5.9 568.3 | ||||||
|  | @ -51,6 +57,7 @@ piano_tuners_in_Chicago => 5.9 568.3 | ||||||
| Here is instead an example using beta distributions and variables: | Here is instead an example using beta distributions and variables: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | $ fermi | ||||||
| 1 2 | 1 2 | ||||||
| => 1.0 2.0 | => 1.0 2.0 | ||||||
| * 1_000_000_000 | * 1_000_000_000 | ||||||
|  | @ -77,69 +84,41 @@ The difference between `=: x` and `=. y` is that `=.` clears the stack after the | ||||||
| If you type "help", you can see a small grammar: | If you type "help", you can see a small grammar: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | $ fermi | ||||||
| help | help | ||||||
|    Operation | Variable assignment | Special |   Operation | Variable assignment | Special | ||||||
|       Operation:                             operator operand |     Operation:                             operator operand | ||||||
|             operator:                        (empty) | * | / | + | - |           operator:                        (empty) | * | / | + | - | ||||||
|             operand:                         scalar | lognormal | beta | variable |           operand:                         scalar | lognormal | beta | variable | ||||||
|               lognormal:                     low high |             lognormal:                     low high | ||||||
|               beta:                          beta alpha beta |             beta:                          beta alpha beta | ||||||
|       Variable assignment:                   =: variable_name |     Variable assignment:                   =: variable_name | ||||||
|       Clear stack:                           . | c | clear |     Variable assignment and clear stack:   =. variable_name | ||||||
|       Variable assignment and clear stack:   =. variable_name |     Special: | ||||||
|       Other special operations:              help | debug | exit |          Clear stack:                      clear | c | . | ||||||
|     Examples:  |          Print this help message:          help  | h | ||||||
|       + 2 |          Print debug info:                 debug | d | ||||||
|       / 2.5 |          Exit:                             exit  | e | ||||||
|       * 1 10 (interpreted as lognormal) |          Comment:                          # this is a comment | ||||||
|       + 1 10 |   Examples: | ||||||
|       * beta 1 10 |     + 2 | ||||||
|       1 10 (multiplication taken as default operation) |     / 2.5 | ||||||
|         =: x |     * 1 10 (interpreted as lognormal) | ||||||
|       . |     + 1 10 | ||||||
|       1 100 |     * beta 1 10 | ||||||
|       + x |     1 10 (multiplication taken as default operation) | ||||||
|       exit |       =: x | ||||||
|  |     . | ||||||
|  |     1 100 | ||||||
|  |     + x | ||||||
|  |     # this is a comment | ||||||
|  |     * 1 12 # this is an operation followed by a comment | ||||||
|  |     exit | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Installation |  | ||||||
| 
 |  | ||||||
| ``` |  | ||||||
| make build |  | ||||||
| sudo make install |  | ||||||
| f # rather than the previous go run f.go |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Why use make instead of the built-in go commands? Because the point of make is to be able to share command-line recipes.  |  | ||||||
| 
 |  | ||||||
| ## Usage together with standard Linux utilities |  | ||||||
| 
 |  | ||||||
| ```bash |  | ||||||
| f |  | ||||||
| sed -u "s|#.*||" | sed -u 's|M|000000|g' | f |  | ||||||
| 
 |  | ||||||
| cat more/piano-tuners.f | f |  | ||||||
| cat more/piano-tuners-commented.f | sed -u "s|#.*||" | sed -u 's|M|000000|g' | f |  | ||||||
| 
 |  | ||||||
| tee -a input.log | go run f.go | tee -a output.log |  | ||||||
| tee -a io.log | go run f.go | tee -a io.log |  | ||||||
| 
 |  | ||||||
| function f(){ |  | ||||||
|   sed -u "s|#.*||" |  |  | ||||||
|   sed -u "s|//.*||" |  |  | ||||||
|   sed -u 's|K|000|g' |  |  | ||||||
|   sed -u 's|M|000000|g' |  |  | ||||||
|   sed -u 's|B|000000000|g' |  |  | ||||||
|   /usr/bin/f |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Note that these sed commands are just hacks, and won't parse e.g., `3.5K` correctly—it will just substitute for 3.5000 |  | ||||||
| 
 |  | ||||||
| ## Tips & tricks | ## Tips & tricks | ||||||
| 
 | 
 | ||||||
| - It's conceptually clearer to have all the multiplications first and then all the divisions | - It's conceptually clearer to have all the multiplications first and then all the divisions | ||||||
| - Sums and divisions now also supported |  | ||||||
| - For things between 0 and 1, consider using a beta distribution | - For things between 0 and 1, consider using a beta distribution | ||||||
| 
 | 
 | ||||||
| ## Different levels of complexity | ## Different levels of complexity | ||||||
|  | @ -159,6 +138,7 @@ Done: | ||||||
| - [x] Save to file? | - [x] Save to file? | ||||||
| - [x] Allow comments? | - [x] Allow comments? | ||||||
|   - [x] Use a sed filter?  |   - [x] Use a sed filter?  | ||||||
|  |   - [x] Add proper comment processing | ||||||
| - [x] Add show more info version | - [x] Add show more info version | ||||||
| - [x] Scalar multiplication and division | - [x] Scalar multiplication and division | ||||||
| - [x] Think how to integrate with squiggle.c to draw samples | - [x] Think how to integrate with squiggle.c to draw samples | ||||||
|  | @ -169,6 +149,7 @@ Done: | ||||||
| - [x] Consider the following: make this into a stack-based DSL, with: | - [x] Consider the following: make this into a stack-based DSL, with: | ||||||
|   - [x] Variables that can be saved to and then displayed |   - [x] Variables that can be saved to and then displayed | ||||||
|   - [x] Other types of distributions, particularly beta distributions? => But then this requires moving to bags of samples. It could still be ~instantaneous though. |   - [x] Other types of distributions, particularly beta distributions? => But then this requires moving to bags of samples. It could still be ~instantaneous though. | ||||||
|  |   - [x] Added bags of samples to support addition and multiplication of betas and lognormals | ||||||
| - [x] Figure out go syntax for | - [x] Figure out go syntax for | ||||||
|   - Maps |   - Maps | ||||||
|   - Joint types |   - Joint types | ||||||
|  | @ -176,11 +157,11 @@ Done: | ||||||
| - [x] Fix correlation problem, by spinning up a new randomness thing every time some serial computation is done. | - [x] Fix correlation problem, by spinning up a new randomness thing every time some serial computation is done. | ||||||
| - [x] Clean up error code. Right now only needed for division | - [x] Clean up error code. Right now only needed for division | ||||||
| - [x] Maintain *both* a more complex thing that's more featureful *and* the more simple multiplication of lognormals thing. | - [x] Maintain *both* a more complex thing that's more featureful *and* the more simple multiplication of lognormals thing. | ||||||
|  | - [x] Allow input with K/M/T | ||||||
| 
 | 
 | ||||||
| To (possibly) do: | To (possibly) do: | ||||||
| 
 | 
 | ||||||
| - [ ] Document parenthesis syntax | - [ ] Document parenthesis syntax | ||||||
| - [ ] Allow input with K/M/T |  | ||||||
| - [ ] Add functions. Now easier to do with an explicit representation of the stakc | - [ ] Add functions. Now easier to do with an explicit representation of the stakc | ||||||
| - [ ] Think about how to draw a histogram from samples | - [ ] Think about how to draw a histogram from samples | ||||||
| - [ ] Dump samples to file | - [ ] Dump samples to file | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								f.go
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								f.go
									
									
									
									
									
								
							|  | @ -71,9 +71,15 @@ const HELP_MSG = "  Operation | Variable assignment | Special\n" + | ||||||
| 	"            lognormal:                     low high\n" + | 	"            lognormal:                     low high\n" + | ||||||
| 	"            beta:                          beta alpha beta\n" + | 	"            beta:                          beta alpha beta\n" + | ||||||
| 	"    Variable assignment:                   =: variable_name\n" + | 	"    Variable assignment:                   =: variable_name\n" + | ||||||
| 	"    Clear stack:                           . | c | clear\n" + |  | ||||||
| 	"    Variable assignment and clear stack:   =. variable_name\n" + | 	"    Variable assignment and clear stack:   =. variable_name\n" + | ||||||
| 	"    Other special operations:              help | debug | exit\n" + | 	"    Special: \n" + | ||||||
|  | 	"         Comment:                          # this is a comment\n" + | ||||||
|  | 	"         Clear stack:                      clear | c | .\n" + | ||||||
|  | 	"         Print debug info:                 debug | d\n" + | ||||||
|  | 	"         Print help message:               help  | h\n" + | ||||||
|  | 	"         Start additional stack:           operator (\n" + | ||||||
|  | 	"         Return from additional stack      )\n" + | ||||||
|  | 	"         Exit:                             exit  | e\n" + | ||||||
| 	"  Examples: \n" + | 	"  Examples: \n" + | ||||||
| 	"    + 2\n" + | 	"    + 2\n" + | ||||||
| 	"    / 2.5\n" + | 	"    / 2.5\n" + | ||||||
|  | @ -85,7 +91,14 @@ const HELP_MSG = "  Operation | Variable assignment | Special\n" + | ||||||
| 	"    .\n" + | 	"    .\n" + | ||||||
| 	"    1 100\n" + | 	"    1 100\n" + | ||||||
| 	"    + x\n" + | 	"    + x\n" + | ||||||
|  | 	"    # this is a comment\n" + | ||||||
|  | 	"    * 1 12 # this is an operation followed by a comment\n" + | ||||||
|  | 	"    * (\n" + | ||||||
|  | 	"    1 10\n" + | ||||||
|  | 	"    + beta 1 100\n" + | ||||||
|  | 	"    )\n" + | ||||||
| 	"    exit\n" | 	"    exit\n" | ||||||
|  | 
 | ||||||
| const NORMAL90CONFIDENCE = 1.6448536269514727 | const NORMAL90CONFIDENCE = 1.6448536269514727 | ||||||
| const INIT_DIST Scalar = Scalar(1) | const INIT_DIST Scalar = Scalar(1) | ||||||
| const N_SAMPLES = 1_000_000 | const N_SAMPLES = 1_000_000 | ||||||
|  | @ -345,9 +358,12 @@ func runRepl(stack Stack, reader *bufio.Reader) Stack { | ||||||
| replForLoop: | replForLoop: | ||||||
| 	for { | 	for { | ||||||
| 		new_line, _ := reader.ReadString('\n') | 		new_line, _ := reader.ReadString('\n') | ||||||
| 		words := strings.Split(strings.TrimSpace(new_line), " ") | 		new_line_before_comments, _, _ := strings.Cut(new_line, "#") | ||||||
|  | 		new_line_trimmed := strings.TrimSpace(new_line_before_comments) | ||||||
|  | 		words := strings.Split(new_line_trimmed, " ") | ||||||
|  | 
 | ||||||
| 		switch { | 		switch { | ||||||
| 		case strings.TrimSpace(new_line) == "": /* Empty line case */ | 		case strings.TrimSpace(new_line_trimmed) == "": /* Empty line case */ | ||||||
| 		/* Parenthesis */ | 		/* Parenthesis */ | ||||||
| 		case len(words) == 2 && (words[0] == "*" || words[0] == "+" || words[0] == "-" || words[0] == "/") && words[1] == "(": | 		case len(words) == 2 && (words[0] == "*" || words[0] == "+" || words[0] == "-" || words[0] == "/") && words[1] == "(": | ||||||
| 			new_stack := runRepl(Stack{old_dist: INIT_DIST, vars: stack.vars}, reader) | 			new_stack := runRepl(Stack{old_dist: INIT_DIST, vars: stack.vars}, reader) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user