Initial commit, ACM PEARC25 and PEARC26 chosen restaurants work.
Committer: hpcdisrespecter <noreply@git.asperger.pro> modified: .gitignore modified: README.md new file: menus/peoples-organic.sexp new file: menus/townhall-shortnorth.sexp new file: organic-cafe.asd new file: run.lisp new file: src/package.lisp new file: src/planner.lisp new file: test/tests.lisp
This commit is contained in:
119
README.md
119
README.md
@@ -1,3 +1,120 @@
|
||||
# organicCafe
|
||||
|
||||
MC sampling a downtown cafe's menu under the Federal per diem
|
||||
~~Practical joke~~ ~~vent art~~ SERIOUS DISCUSSION code for generating multi-day,
|
||||
budget-constrained meal plans from a menu using MC sampling.
|
||||
|
||||
- Never make a decision about food at a technical conference again!
|
||||
- Make wait staff feel awkward by ordering as soon as you arrive!
|
||||
- Avoid the temptation to eat the same thing every day!
|
||||
|
||||
The menu and meal templates are a small, data-only S-expression DSL.
|
||||
|
||||
Shoutout to People's Organic in MSP (Federal per diem: $92, FY2026) and
|
||||
TownHall Short North in Columbus ($80, FY2025), the respective off-site ordering adventures
|
||||
for ACM PEARC26 and PEARC25.
|
||||
|
||||
People's Organic has a small menu and fewer options, whereas TownHall produces
|
||||
a Cartesian product of garnishes. Both are supported in this framework.
|
||||
|
||||
## General Ideas
|
||||
|
||||
Prices are converted to integer cents when loaded, so budget comparisons do
|
||||
not rely on floating-point arithmetic.
|
||||
|
||||
For normal generation, the planner computes the weighted number of completions
|
||||
at each remaining budget and samples only branches that can finish beneath the
|
||||
cap. This avoids both rejection loops and materializing large Cartesian products.
|
||||
|
||||
Any given day, a small pool of feasible days is drawn, and least-repetitive
|
||||
candidates are favored.
|
||||
|
||||
`feasible-candidates` still eagerly enumerates combinations for tests,
|
||||
diagnostics, and suitably small menus such as People's Organic.
|
||||
|
||||
## Variables
|
||||
|
||||
- `--budget DOLLARS` sets the daily per diem.
|
||||
- `--days N` sets the number of days to plan.
|
||||
- `--menu FILE` selects a menu file from `menus/`.
|
||||
- `--plan PLAN` selects a plan from the menu. If omitted, the first plan is used.
|
||||
- `--add-lazy-day DOLLARS` appends a breakfast-only day with its own budget. For outbound flight days.
|
||||
- `--seed N` sets the random seed for reproducibility (don't use this you orthorexic nerd).
|
||||
|
||||
## Usage
|
||||
|
||||
SBCL and ASDF are the only requirements.
|
||||
|
||||
```sh
|
||||
# PEARC26 default
|
||||
sbcl --script run.lisp
|
||||
# the same thing explicitly with seed
|
||||
sbcl --script run.lisp -- --budget 92 --days 3 --seed 1337 --add-lazy-day 30
|
||||
# PEARC25 default
|
||||
sbcl --script run.lisp -- \
|
||||
--menu menus/townhall-shortnorth.sexp \
|
||||
--budget 80 --add-lazy-day 30 --seed 1337
|
||||
```
|
||||
|
||||
Use `--help` for all options.
|
||||
|
||||
Ask for help if you need it. Someone will probably answer.
|
||||
|
||||
## Tests
|
||||
|
||||
Run the tests:
|
||||
|
||||
```sh
|
||||
sbcl --non-interactive \
|
||||
--eval '(require "asdf")' \
|
||||
--eval '(asdf:load-asd (truename "organic-cafe.asd"))' \
|
||||
--eval '(asdf:test-system "organic-cafe/tests")'
|
||||
```
|
||||
|
||||
## The DSL
|
||||
|
||||
The complete menus live in `menus/` and defaults to `menus/peoples-organic.sexp`. The DSL is a small S-expression language for describing menus and meal plans.
|
||||
|
||||
`:lazy-day` is a special plan item, for the day you leave town.
|
||||
|
||||
### Basic example
|
||||
|
||||
```lisp
|
||||
(:menu "A Cafe"
|
||||
(:group :mains
|
||||
(:item "Soup and sandwich" 12.50)
|
||||
(:item "Grain bowl" 14))
|
||||
(:group :drinks
|
||||
(:item "Coffee" 3.25))
|
||||
|
||||
(:plan :lunch
|
||||
(:meal :lunch
|
||||
(:one :main :mains)
|
||||
(:maybe :drink :drinks :chance 1/2))))
|
||||
```
|
||||
|
||||
`(:one LABEL GROUP)` always chooses one item. `(:maybe LABEL GROUP :chance P)`
|
||||
chooses no item with probability `1-P`; if present, each item in the group has
|
||||
an equal share of `P`.
|
||||
|
||||
### Composable forms
|
||||
|
||||
TownHall's menu has options, so it demonstrates compositional forms:
|
||||
|
||||
```lisp
|
||||
(:choose :side :bowl-side :count 2)
|
||||
|
||||
(:either :meal
|
||||
(:branch 1/2
|
||||
(:one :shared-plate :pour-la-table))
|
||||
(:branch 1/2
|
||||
(:one :protein :bowl-protein)
|
||||
(:one :base :bowl-base)))
|
||||
```
|
||||
|
||||
`:choose` samples the requested number of distinct items. `:either` selects one
|
||||
weighted branch, whose body may contain any number of other plan forms. Branch
|
||||
weights must sum to one. `:one` and `:maybe` are also valid. You are also valid.
|
||||
|
||||
### License and Sharing
|
||||
|
||||
Do what the fuck you want.
|
||||
|
||||
Reference in New Issue
Block a user