Dane Sabo cebf8c167a Initial umbrella repo: thesis + FRET pipeline + plant model with first controllers
Folds three previously-separate pieces into one preliminary-example repo
for the HAHACS thesis:

- thesis/ (submodule) → gitea Thesis.git — the PhD proposal
- fret-pipeline/ — FRET requirements to AIGER controller (was
  ~/Documents/fret_processing/; prior single-commit history abandoned
  per user decision)
- plant-model/ — 10-state PKE + lumped T/H PWR model (was
  ~/Documents/PKE_Playground/; never version-controlled before)
- presentations/2026DICE/ (submodule) → gitea 2026DICE.git
- reachability/, hardware/ — empty placeholders for Thrust 3 and HIL
- docs/architecture.md — how the discrete and continuous layers compose
- claude_memory/ — session notes and scratch knowledge pattern

Plant model refactored to thesis naming (x, plant, u, ref); pke_th_rhs
now takes u as an explicit arg instead of reading rho_ext from the
params struct. First two controllers built to the contract
u = ctrl_<mode>(t, x, plant, ref): ctrl_null (baseline) and
ctrl_operation (stabilizing, proportional on T_avg). Validated under a
100% -> 80% Q_sg step: ctrl_operation reduces steady-state T_avg drift
~47% vs. the unforced plant.

Root CLAUDE.md emphasizes that CLAUDE.md files are living documents and
that any knowledge not captured before a session ends is lost forever;
claude_memory/ holds the session-level notes that haven't stabilized
enough to graduate into a CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 16:24:11 -04:00

4.4 KiB

CLAUDE.md

Guidance for Claude Code (claude.ai/code) working in this subdirectory.

What this is

A deterministic pipeline that converts FRET natural-language requirements into a reactive controller and a state-machine diagram. Implements Thrust 1 + 2 of the HAHACS methodology (../thesis/3-research-approach/approach.tex).

The pipeline is four stages:

FRET JSON         -->  fret_to_synth.py  -->  synthesis config JSON
synthesis config  -->  synthesize.sh     -->  AIGER circuit (.aag)
AIGER circuit     -->  trace_aiger.py    -->  DOT + PNG + SVG state machine
AIGER circuit     -->  aag2dot.py        -->  gate-level circuit diagram

Running

python3 scripts/fret_to_synth.py pwr_hybrid_3.json specs/synthesis_config_v3.json
bash scripts/synthesize.sh specs/synthesis_config_v3.json circuits
python3 scripts/trace_aiger.py circuits/PWR_HYBRID_3_DRC.aag diagrams
dot -Tpng diagrams/PWR_HYBRID_3_DRC_states.dot -o diagrams/PWR_HYBRID_3_DRC_states.png

All scripts are pure Python 3 stdlib + bash. External binaries required:

  • ltlsynt (Spot) — brew install spot
  • dot (Graphviz) — brew install graphviz

Architecture

scripts/fret_to_synth.py — Auto-discovers mode groups by regex-scanning LTL formulas for (control_X = q_Y) patterns. Decomposes multi-valued mode variables into independent booleans and generates mutual-exclusion constraints so the synthesizer can't assert two modes simultaneously. Classifies every other variable as an environment input. See docs/fret_to_synth.md.

scripts/synthesize.sh — Thin wrapper around ltlsynt that reads the synthesis config, extracts inputs/outputs/formula, and calls ltlsynt with AIGER output. Strips the REALIZABLE header line from the output. See docs/synthesize.md.

scripts/trace_aiger.py — Exhaustive circuit evaluation: enumerates all reachable latch states, extracts guard conditions on transitions via boolean function simplification, emits DOT. See docs/trace_aiger.md.

scripts/aag2dot.py — Gate-level diagram of the AIGER circuit (wires, AND gates, latches). Useful for debugging unexpectedly large circuits. See docs/aag2dot.md.

Key design decisions

  • Mode decomposition with mutex constraint. FRET's control_mode = q_X is a single integer variable that inherently holds one value. ltlsynt works over independent booleans. So we decompose into in_mode_shutdown, in_mode_heatup, etc., and add a "G(exactly one active)" constraint. The mutex is a synthesis encoding artifact, not a missing FRET requirement.
  • Prefer ftInfAUExpanded over ft. FRET emits multiple LTL forms; we use the expanded infinite-horizon form because ltlsynt works over infinite traces. The ft form can contain LAST operators that bias toward finite traces.
  • Regex-based mode discovery. Fully automatic — no hardcoded variable lists. Add a new mode in FRET and re-export; the script picks it up.
  • Strict sanity check. If any control_ or q_ token survives the boolean encoding, the script errors out rather than producing silent bugs.

FRET naming conventions

Enforced by fret_to_synth.py. See README.md for the full rules.

  • Mode variables: control_<group> with values q_<value>. Decomposed to in_<group_suffix>_<value_suffix>.
  • Environment inputs: anything else. Assumed boolean; continuous quantities should be abstracted to predicates at the FRET level (e.g., t_avg_above_min).

Extending

  • New requirement. Add it in FRET, re-export JSON, re-run the pipeline. No code changes needed as long as the new variables follow the naming rule.
  • New mode group. Same as above — fret_to_synth.py auto-discovers.
  • Unrealizable spec. Use FRET's realizability checking first to isolate the conflicting requirement. synthesize.sh will print UNREALIZABLE if the full spec is inconsistent.
  • Output format. Current targets are DOT and AIGER. Translating AIGER to Stateflow is the next planned extension (see parent CLAUDE.md — this is flagged as the known pain point in the thesis workflow).

Conventions in this subtree

  • Scripts are self-contained and take explicit I/O paths as args — no global config file, no env vars.
  • Generated artifacts live in circuits/, diagrams/, and specs/. Treat them as derived; regenerate rather than hand-edit.
  • pwr_hybrid_3.json is the source of truth. Never hand-edit the generated synthesis_config_v3.json.