# platz A genetic-algorithm-based solver that assigns people to tables ("Tische") for an event, given group memberships, table sizes/neighbor relationships, and a configurable penalty scheme. It reads a guest list (XML) and a table layout (INI), searches for a good seating using a small custom GA framework, and writes the result to text/CSV output files. **This is Python 3 code** (migrated from an original Python 2 implementation). There are no third-party dependencies (standard library only), so `requirements.txt` is empty — it exists only so `bin/install_py` has something to install. ## Project structure ``` platz/ ├── bin/ # environment + launcher scripts (.bat + .sh pairs) ├── cfg/ # GA cycle definition and penalty scheme ├── libs/ # the two Python modules (ga.py, Strukturdaten.py, platz.py) ├── tests/ # unittest suite for Strukturdaten.py └── work/ # per-run input (table layout, guest list) and output ├── test1/ └── test2/ ``` - `libs/platz.py` — entry point; wires together config, input data, and the GA run. - `libs/ga.py` — generic genetic-algorithm scaffolding (`Loesung`, `Zyklus`, `Farm`, `Entwicklung`). - `libs/Strukturdaten.py` — domain model for the seating problem (`Person`, `Gruppe`, `Tisch`, `Strafliste`, `Sitzplatzverteilung`, `JSONConfig`). ## Running the tests ```bash python -m unittest discover -s tests -p "test_*.py" -v ``` If a stray global `PYTHONPATH` entry shadows the standard-library `tests` package name (unrelated to this project), clear it for the command, e.g. `PYTHONPATH= python -m unittest discover -s tests -p "test_*.py" -v`. ## Setup 1. Install a Python interpreter (`py` on Windows / `python3` on Linux/macOS must be on `PATH`). 2. Run the installer for your platform to create a `.venv` and install `requirements.txt`: ```bat :: Windows bin\install_py.bat ``` ```bash # Linux/macOS bin/install_py.sh ``` All `bin/` scripts derive `PLATZ` automatically from their own location (no path editing required) by calling `setenv.bat`/`setenv.sh` first. ## Running ```bat :: Windows bin\activate_venv.bat bin\platz.bat --indir work\test1 ``` ```bash # Linux/macOS source bin/activate_venv.sh bin/platz.sh --indir work/test1 ``` `bin/platz.bat` / `bin/platz.sh` call `setenv` to set `PLATZ`, `PLATZ_CFG`, `PLATZ_LIBS`, `PLATZ_WORK`, `PLATZ_IN`, `PLATZ_OUT`, add `PLATZ_LIBS` to `PYTHONPATH`, and then run `libs/platz.py`, forwarding any extra arguments (like `--indir`) to it. Other helper scripts (`bin/setenv.*`, `bin/get_cmd.*`) follow the same environment convention: - `setenv` — sets all `PLATZ_*` environment variables and creates missing folders; sourced by every other script, not normally called directly. - `activate_venv` — activates the `.venv` created by `install_py`. - `get_cmd` — opens a new shell with the `PLATZ_*` environment already set. ### Configuring a run `--indir ` is required and points at a directory containing the input files and receiving the output files for one run — e.g. `work/test1/` or `work/test2/`: - `tische.ini` — one section per table: `Nummer`, `Hof` (venue/court), `Plaetze` (seat count), `Nachbarliste` (neighboring table ids), `Koordinaten`. - `bestellung.json` — `{ "gruppen": [ ... ] }`, each group with a `"personen"` list (`vorname`/`nachname`/optional `titel`), an optional `"anzahl"` (how many bookings to expand each person into), an optional `"name"` (display label) and an optional `"tisch"` (pins the group as a VIP group to that table instead of placing it via the GA). To run against a different dataset, create a new folder with a `tische.ini` and `bestellung.json` following the same layout and pass it via `--indir`. The GA cycle and penalty scheme are read directly from `$PLATZ_CFG/zyklus.cfg` and `$PLATZ_CFG/strafen.cfg` (independent of `--indir`); there is no longer a `platz.cfg` indirection. The GA profile is selected with the `--zyklus-art ` switch (default: `Adaptiv`). `cfg/zyklus.cfg` defines the GA profiles. Two styles exist: - **static** profiles (`Easy`, `Simple`) give an explicit `Abfolge` (sequence of actions) and matching `Anzahl` (counts): `e` create, `s` select best, `S` select randomly, `m` mutate, `j` keep parents, `z` advance generation. - the **adaptive** profile (`Adaptiv`, the default) has no fixed action list. It is recognised by a `Start` field and runs a generation loop: a large starting population that shrinks each generation (`Schrumpfung`, down to `MinPopulation`) and stops once the best score fails to improve by at least `Schwelle` for `Geduld` generations (or after `MaxGenerationen`). Select a different profile per run, e.g. `bin/platz.bat --indir work/test2 --zyklus-art Easy`. `cfg/strafen.cfg` defines the penalty scheme: cost of splitting a group across tables (by group size and number of splits), cost of a person sitting alone or without a group-mate at a neighboring table, and per-table seat-utilization penalties. ### Output A run writes two files into the `--indir` directory: - `TischePersonen.txt` — table → seated people, with venue/table/seat numbers. - `PersonenTische.csv` — person → table, sorted alphabetically by name. Pass `--tosvg` to additionally write `Sitzplatzverteilung.svg` into the `--indir` directory: tables are drawn as white circles, people as colored circles inside their table's circle (color = group). See `doc/docu_tests.md` for example renderings. Two more optional graphs go into the `--indir` directory: - `--show-development` → `Entwicklung.svg`: the course of the search (best/average/worst value over time, plus a panel with the number of solutions in the pool per step). - `--show-lineage` → `Abstammung.svg`: the mutation tree of every solution. The final best solution's ancestral branch is highlighted and labelled with its id. Every solution gets a plain running number (`1..N`); the ancestry is recorded via each node's stored predecessor (parent id), not encoded in the id itself, and is followed back along the highlighted branch. ## Further details See `CLAUDE.md` for a deeper architectural walkthrough of the GA framework and domain model, intended for AI coding assistants but equally useful for human contributors.