From 33a0647a51183b6338d81bb22ade6d5ad786e8ff Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 26 Jul 2026 23:04:43 +0200 Subject: [PATCH] Add CLAUDE.md with build commands and architecture overview Documents the PRJ/CONFIG-based Makefile build, external deps (Armadillo, JsonCpp, JUCE), and the Rbm/Layer/AStack (DeepStack/RnnStack) core architecture plus the three entry points (main.cpp, poet.cpp, gui.cpp). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_019113s2pJdTtsUqsBdFgQAk --- CLAUDE.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9081f01 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,97 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +C++11 library and set of executables implementing Restricted Boltzmann Machines (RBMs), stacked into +deep belief networks (`DeepStack`) or recurrent structures (`RnnStack`) for character-level text generation +("poet"). There are three build targets sharing the same core sources: a JUCE-based desktop GUI (`GUI`), a +console test harness (`TEST`), and a text-generation CLI (`POET`). + +## Build + +Build system is a hand-written `Makefile` (no CMake). Select the target with `PRJ` and the build flavor with +`CONFIG`: + +```sh +make PRJ=POET CONFIG=release # builds build/release/poet.elf (default PRJ=POET, CONFIG=release) +make PRJ=TEST CONFIG=debug # builds build/debug/test.elf +make PRJ=GUI # builds build/release/rbm.elf, also builds the JUCE static lib first +make clean # removes build/${CONFIG} +``` + +The `GUI` target additionally depends on `juce/build/${CONFIG}/libjuce.a`, built via `make -C juce` (uses +`juce/Makefile`, `juce/pkg.mk`, `juce/JUCE-3.1.1.mk` against the vendored `juce/JUCE-3.1.1` source tree). +`install` copies `build/release/rbm.elf` to `${HOME}/bin`. + +Object/dependency files land in `build/${CONFIG}/`; `.d` files are auto-included for header dependency +tracking. There is no separate lint or test-runner command — `TEST_CXX_SRCS` builds `main.cpp` into +`test.elf`, which is a manual smoke-test program (load a project, train, print matrices), not a unit test +suite. Run it directly to sanity-check core behavior: + +```sh +make PRJ=TEST CONFIG=debug && ./build/debug/test.elf +``` + +### External dependencies (system-installed, not vendored) + +- **Armadillo** (``, linked `-larmadillo`) — all matrix/vector math goes through `arma::mat`. +- **JsonCpp** (``, linked `-ljsoncpp`) — project files (`*.prj`) and layer weight + metadata serialize to/from `Json::Value`. +- JUCE (vendored under `juce/`, only needed for the `GUI` target) plus its Linux deps: freetype, X11, + Xinerama, Xext, GL, pthread, dl, rt. + +## Architecture + +### Core RBM hierarchy + +- **`Rbm`** (`Rbm.hpp/cpp`) — a single restricted Boltzmann machine: visible/hidden units, weights (`m_whv`), + biases (`m_bh`, `m_bv`), `Params` (learning rate, momentum, Gibbs sampling options, etc.), and the + contrastive-divergence training step (`cd`, `cd_hinton`, `cd_jens`, ...). Params and trained state + round-trip through `toJson()`/`fromJson()`. +- **`Layer`** (`Layer.hpp/cpp`) — wraps an `Rbm` with 2D visible geometry (`numVisibleX/Y`, for image-like + data) plus an optional context block (`numContext`, used by the RNN stack to feed in previous state). + Layers form an intrusive doubly-linked list via raw `next`/`prev` pointers (not `std::vector`); `root()` + walks to the first layer. Per-layer weights persist as separate `.Layer..{w,bh,bv}.dat` files + (`weightsLoad`/`weightsSave`), independent from the JSON project file. +- **`AStack`** (`AStack.hpp/cpp`) — abstract base owning the `Layer` linked list for a named project + ("stack"). Handles layer add/remove, weight init/load/save for the whole stack, and the training-batch + matrix (`m_trainingBatch`, loaded from `*.training.dat`). Declares `train()` as pure virtual — subclasses + decide how data flows between layers. + - **`DeepStack`** — classic layer-wise DBN: `upPass`/`downPass`/`upDownPass` propagate a sample through + the full stack; `train()` greedily trains each layer on the representation produced by the layers below. + - **`RnnStack`** — treats the stack as a recurrent cell operating on one-hot character codes + (`NUM_CODES = 37`: space + a-z + 0-9). `step_forward` advances the recurrent state one timestep; + `v_to_vc`/`vc_to_v` pack/unpack the visible+context vector. Used by `poet.cpp` for text generation. +- **`StackCreator`** (`StackCreator.hpp/cpp`) — serializes/deserializes an `AStack` (and its `Layer`s) to/from + a `.prj` JSON file. Reads `stack.type` to decide whether to instantiate a `DeepStack` or `RnnStack`. + Accepts an optional `LayerConstructor` callback so callers (e.g. the GUI) can substitute their own + `Layer` subclass (see `RbmComponent`) when building layers from JSON. +- **`RnnTextHelper`** / **`Matutils`** (`matutils.hpp`) — character <-> one-hot vector encoding + (`char2vec`/`vec2char`, `ch2idx`/`idx2ch`), training-batch construction from text files, and small + Armadillo helpers (`sample`, `prob`, `normalize`, `uniform`) used by the CD training routines. + +### Entry points + +- **`source/main.cpp`** — `TEST` target; exercises `DeepStack` directly (build/train/save a small DBN, + or load an existing one, depending on `CREATE_TEST`/`TRAIN_TEST` compile-time flags). +- **`source/poet.cpp`** — `POET` target; loads an `RnnStack` project (default `poet_2v_5s`) and dispatches + on `argv[1]`: `c`(reate)/`r`(eset weights)/`t`(rain, optionally with a training-text path in `argv[2]`)/ + `f`(orward-generate text, optional seed string in `argv[2]`). Training periodically calls back into + `forward()` to sample generated text as a progress check. +- **`source/gui.cpp`** + **`MainComponent`** — JUCE app entry point; `MainComponent` implements + `LayerConstructor` to build `RbmComponent` layers (interactive `Layer` subclass with sliders/toggles bound + to `Rbm::Params`) and drives training via the `Rbm::IListener` progress callback, mirroring what + `RbmListener` does in the CLI tools. + +### Project files on disk + +Each named project `` (e.g. `mnist`, `poet_2v_5s`, `context99` — see the many `*.prj` files at repo +root, mostly saved experiment artifacts) consists of: +- `.prj` — JSON describing the stack type and layer geometry (via `StackCreator`). +- `.training.dat` — the training batch matrix. +- `.Layer..w.dat` / `.bh.dat` / `.bv.dat` — per-layer weights/biases (Armadillo binary/text format). + +These root-level `.dat`/`.prj`/`.txt` files are experiment data and generated artifacts, not something to +edit by hand; treat them as fixtures unless a task specifically concerns training data or saved models.