Michael Stangl 6710d4f06a Bessere Verteilung: Strafen/Mutation, plus Abstammungsbaum mit Id-Herkunft
Weniger vermeidbare Gruppentrennungen:
- strafen.cfg: Tischbesetzung bestraft jetzt gestaffelt nach freien
  Plaetzen (teilbelegte Tische am teuersten, mit Fallback auf den
  naechstkleineren Eintrag), Trennungsstrafen deutlich erhoeht - so
  werden Gruppen nicht mehr getrennt, obwohl leere Tische danebenstehen
- gibPunkte('Tischbesetzung') mit Naechst-kleiner-Fallback
- mutieren() setzt geraeumte Gruppen groesste-zuerst neu
  (GruppenSetzen(GrosseZuerst=True)), damit grosse Gruppen die frei
  gewordenen ganzen Tische bekommen und wieder zusammenkommen
  (uebrig bleiben nur physisch unvermeidbare Trennungen, Gruppe > Tisch)

Abstammungsbaum (neuer Schalter --show-lineage -> Abstammung.svg):
- neue Klasse ga.Abstammung zeichnet den vollen Mutationsbaum aller
  Loesungen; der Ast der finalen besten Loesung ist hervorgehoben und
  mit ihrer Id beschriftet
- hierarchische Loesungs-Ids (Farm._WurzelId/_KindId): Wurzel '7',
  Mutationskind '7.2', dessen Kind '7.2.1' - die ganze Abstammung ist
  direkt aus der Id ablesbar

Tests (15 gruen), README und CLAUDE.md aktualisiert; Beispiele mit den
neuen Strafen und beiden Grafiken neu berechnet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 22:38:43 +02:00

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

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:

    :: Windows
    bin\install_py.bat
    
    # 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

:: Windows
bin\activate_venv.bat
bin\platz.bat --indir work\test1
# 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 <dir> 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 <name> 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-developmentEntwicklung.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-lineageAbstammung.svg: the mutation tree of every solution. The final best solution's ancestral branch is highlighted and labelled with its lineage id. Ids are hierarchical — a root solution is a plain number (7), each mutation appends a child index (7.2, then 7.2.1) — so the id itself spells out the whole ancestry.

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.

S
Description
Platzverwaltung (converted from SVN)
Readme 925 KiB
Languages
Python 74.5%
HTML 20.9%
Batchfile 2.3%
Shell 2.3%