206 lines
9.3 KiB
Markdown
206 lines
9.3 KiB
Markdown
<!-- Moved from docs/03-architecture/physics-engine/feedback-loops.md to docs/working/architecture/03-architecture/physics-engine/feedback-loops.md on 2026-06-16 (docs reorg Phase 2) -->
|
||
# StarForth Physics Feedback Loops
|
||
|
||
This document describes the 7 feedback loops in StarForth's physics-driven adaptive runtime, including their positive (accumulation) and negative (stabilization) feedback mechanisms.
|
||
|
||
## Overview
|
||
|
||
StarForth implements a physics-grounded self-adaptive runtime with 7 configurable feedback loops. Each loop can be toggled via Makefile flags (`ENABLE_LOOP_N_*`). The loops build cumulatively for Design of Experiments (DoE) measurement.
|
||
|
||
## Feedback Loop Reference
|
||
|
||
| Loop | Name | Positive Signal (Accumulation) | Negative Feedback (Stabilization) |
|
||
|------|------|-------------------------------|-----------------------------------|
|
||
| **#1** | **Execution Heat Tracking** | Word execution increments `execution_heat` counter | **Loop #3** applies time-based decay; `HEAT_CACHE_DEMOTION_THRESHOLD` demotes cold words from cache |
|
||
| **#2** | **Rolling Window History** | Circular buffer records every word execution (up to `ROLLING_WINDOW_SIZE`) | Oldest entries overwritten on wrap; **adaptive shrinking** reduces `effective_window_size` when pattern diversity growth < `ADAPTIVE_GROWTH_THRESHOLD` (1%) |
|
||
| **#3** | **Linear Decay** | Heat decay rate (`decay_slope_q48`) starts at 1/3 | Decay itself IS negative feedback—reduces heat over time at rate `DECAY_RATE_PER_US_Q16`; slope adjusts ±5% based on hot/stale word ratio trends |
|
||
| **#4** | **Pipelining Metrics** | Records word→word transitions in `transition_metrics`; builds context windows for prediction | Transition counts age out; **miss rate feedback**—if `prefetch_accuracy` drops, suggested window size changes via binary chop |
|
||
| **#5** | **Window Width Inference** | Expands `effective_window_size` when pattern diversity increases | **Levene's test** for variance stability (α=0.05, critical W≈6.5); if variance stable → shrink to minimum sufficient size; `ADAPTIVE_SHRINK_RATE=75` (shrinks to 75% per cycle) |
|
||
| **#6** | **Decay Slope Inference** | Extracts optimal decay rate via exponential regression on heat trajectory | **ANOVA early-exit**: if variance changed <5% since last check, skip inference (cached results); slope bounded by fit quality (`slope_fit_quality_q48`) |
|
||
| **#7** | **Adaptive Heartrate** | `tick_count` increments; monitors system responsiveness | If system stable (variance stabilized), inference runs less frequently (`HEARTBEAT_INFERENCE_FREQUENCY`); **inference cost vs benefit** tradeoff—high cost triggers less frequent ticks |
|
||
|
||
## Detailed Loop Descriptions
|
||
|
||
### Loop #1: Execution Heat Tracking
|
||
|
||
**Purpose:** Count word usage to identify hot paths.
|
||
|
||
**Positive feedback:**
|
||
- Every word execution increments `DictEntry.execution_heat`
|
||
- Hot words get promoted to `hotwords_cache` for O(1) lookup
|
||
|
||
**Negative feedback:**
|
||
- Loop #3 (Linear Decay) reduces heat over time
|
||
- Words falling below `HEAT_CACHE_DEMOTION_THRESHOLD=10` are demoted from cache
|
||
- `PHYSICS-RESET-STATS` word can reset all heat counters
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_1_HEAT_TRACKING`
|
||
|
||
---
|
||
|
||
### Loop #2: Rolling Window History
|
||
|
||
**Purpose:** Capture execution sequence for deterministic metric seeding.
|
||
|
||
**Positive feedback:**
|
||
- Circular buffer (`execution_history`) records every word ID executed
|
||
- Window grows to `ROLLING_WINDOW_SIZE` (default 4096) before wrapping
|
||
- Becomes "warm" after 1024 executions (representative data)
|
||
|
||
**Negative feedback:**
|
||
- Oldest entries overwritten when buffer wraps
|
||
- Adaptive shrinking reduces `effective_window_size` when:
|
||
- Pattern diversity growth rate < `ADAPTIVE_GROWTH_THRESHOLD` (1%)
|
||
- Checked every `ADAPTIVE_CHECK_FREQUENCY` (256) executions
|
||
- Shrinks by `ADAPTIVE_SHRINK_RATE` (75% retained per cycle)
|
||
- Floor at `ADAPTIVE_MIN_WINDOW_SIZE` (256)
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_2_ROLLING_WINDOW`
|
||
|
||
---
|
||
|
||
### Loop #3: Linear Decay
|
||
|
||
**Purpose:** Age words over time to prevent unbounded heat accumulation.
|
||
|
||
**Positive feedback:**
|
||
- Decay slope (`decay_slope_q48`) starts at 1/3 in Q48.16 fixed-point
|
||
- Slope can increase if too many words are stale
|
||
|
||
**Negative feedback (this loop IS primarily negative feedback):**
|
||
- Heat decays at rate `DECAY_RATE_PER_US_Q16` (1/65536 heat/μs)
|
||
- Half-life approximately 6-7 seconds for 100-heat word
|
||
- Slope adjusts ±5% based on hot/stale word ratio:
|
||
- Too many hot words → increase decay slope
|
||
- Too many stale words → decrease decay slope
|
||
- Minimum interval `DECAY_MIN_INTERVAL` (1μs) prevents over-decay
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_3_LINEAR_DECAY`
|
||
|
||
---
|
||
|
||
### Loop #4: Pipelining Metrics
|
||
|
||
**Purpose:** Track word-to-word transitions for speculative prefetch.
|
||
|
||
**Positive feedback:**
|
||
- Records transitions in `WordTransitionMetrics` per word
|
||
- Builds context windows (`TRANSITION_WINDOW_SIZE`, default 2) for prediction
|
||
- `prefetch_attempts` and `prefetch_hits` track accuracy
|
||
|
||
**Negative feedback:**
|
||
- Transition counts age out over time
|
||
- Miss rate feedback: if `prefetch_accuracy` drops, binary chop suggests different window size
|
||
- `PipelineGlobalMetrics.suggested_next_size` guides tuning
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_4_PIPELINING_METRICS`
|
||
|
||
---
|
||
|
||
### Loop #5: Window Width Inference
|
||
|
||
**Purpose:** Find optimal rolling window size via statistical testing.
|
||
|
||
**Positive feedback:**
|
||
- `effective_window_size` can grow when pattern diversity increases
|
||
- Growth rate > threshold → window expands toward `ROLLING_WINDOW_SIZE`
|
||
|
||
**Negative feedback:**
|
||
- **Levene's test** for equality of variance (statistically valid):
|
||
- Divides trajectory into K disjoint chunks
|
||
- Computes variance of each chunk independently
|
||
- Test statistic W compared to critical value (~6.5 for α=0.05)
|
||
- If W ≤ critical: variances stable → found minimum sufficient window
|
||
- Shrinks to smallest size where variance is statistically stable
|
||
- Prevents over-capture of redundant pattern data
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_5_WINDOW_INFERENCE`
|
||
|
||
---
|
||
|
||
### Loop #6: Decay Slope Inference
|
||
|
||
**Purpose:** Extract optimal decay rate via exponential regression.
|
||
|
||
**Positive feedback:**
|
||
- Linear regression on log-transformed heat trajectory
|
||
- Model: `ln(heat[t]) = ln(h0) - slope*t` (exponential decay)
|
||
- Closed-form solution extracts `adaptive_decay_slope`
|
||
|
||
**Negative feedback:**
|
||
- **ANOVA early-exit**: if variance changed <5% since last inference, skip computation
|
||
- `has_variance_stabilized()` compares current vs cached variance
|
||
- Saves ~5-10k CPU cycles when stable
|
||
- Slope bounded by fit quality (`slope_fit_quality_q48`)
|
||
- Invalid slopes (0 or >100) rejected by `inference_outputs_validate()`
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_6_DECAY_INFERENCE`
|
||
|
||
---
|
||
|
||
### Loop #7: Adaptive Heartrate
|
||
|
||
**Purpose:** Dynamic tick frequency adjustment for system responsiveness.
|
||
|
||
**Positive feedback:**
|
||
- `tick_count` increments every heartbeat
|
||
- Heartbeat thread wakes at `HEARTBEAT_TICK_NS` (1ms default)
|
||
- Monitors hot word count, total heat, window width
|
||
|
||
**Negative feedback:**
|
||
- If system is stable (variance stabilized), inference runs less frequently
|
||
- `HEARTBEAT_INFERENCE_FREQUENCY` (5000 ticks) controls full inference cadence
|
||
- Cost vs benefit tradeoff: expensive inference → less frequent ticks
|
||
- Background thread (`HeartbeatWorker`) can be disabled via `HEARTBEAT_THREAD_ENABLED=0`
|
||
|
||
**Makefile flag:** `ENABLE_LOOP_7_ADAPTIVE_HEARTRATE`
|
||
|
||
---
|
||
|
||
## Key Negative Feedback Mechanisms Summary
|
||
|
||
1. **Heat Decay (Loop #3)** — The primary stabilizer: prevents unbounded heat accumulation
|
||
2. **Window Shrinking (Loop #2 + #5)** — Pattern diversity plateau triggers size reduction via Levene's test
|
||
3. **ANOVA Early-Exit (Loop #6)** — Variance stability (<5% change) skips expensive inference
|
||
4. **Cache Demotion (Loop #1)** — Words below `HEAT_CACHE_DEMOTION_THRESHOLD=10` exit hot-words cache
|
||
5. **Slope Direction Reversal (Loop #3)** — If hot/stale ratio inverts, decay slope adjusts ±5%
|
||
|
||
## Configuration
|
||
|
||
### Enabling/Disabling Loops
|
||
|
||
```bash
|
||
# Disable a specific loop
|
||
make ENABLE_LOOP_3_LINEAR_DECAY=0
|
||
|
||
# Baseline build (all loops off)
|
||
make ENABLE_LOOP_1_HEAT_TRACKING=0 \
|
||
ENABLE_LOOP_2_ROLLING_WINDOW=0 \
|
||
ENABLE_LOOP_3_LINEAR_DECAY=0 \
|
||
ENABLE_LOOP_4_PIPELINING_METRICS=0 \
|
||
ENABLE_LOOP_5_WINDOW_INFERENCE=0 \
|
||
ENABLE_LOOP_6_DECAY_INFERENCE=0 \
|
||
ENABLE_LOOP_7_ADAPTIVE_HEARTRATE=0
|
||
```
|
||
|
||
### Tuning Knobs
|
||
|
||
| Knob | Default | Description |
|
||
|------|---------|-------------|
|
||
| `ROLLING_WINDOW_SIZE` | 4096 | Initial/maximum window size |
|
||
| `ADAPTIVE_SHRINK_RATE` | 75 | % retained when shrinking (75 = discard 25%) |
|
||
| `ADAPTIVE_MIN_WINDOW_SIZE` | 256 | Floor for window shrinking |
|
||
| `ADAPTIVE_CHECK_FREQUENCY` | 256 | Executions between diversity checks |
|
||
| `ADAPTIVE_GROWTH_THRESHOLD` | 1 | Growth rate (%) that signals saturation |
|
||
| `DECAY_RATE_PER_US_Q16` | 1 | Heat decay per microsecond (Q16 fixed-point) |
|
||
| `HEARTBEAT_INFERENCE_FREQUENCY` | 5000 | Ticks between full inference runs |
|
||
| `TRANSITION_WINDOW_SIZE` | 2 | Context depth for pipelining prediction |
|
||
|
||
## Related Files
|
||
|
||
- `src/rolling_window_of_truth.c` — Loop #2 implementation
|
||
- `src/dictionary_heat_optimization.c` — Loop #1, #3 heat management
|
||
- `src/inference_engine.c` — Loop #5, #6 unified inference
|
||
- `src/physics_pipelining_metrics.c` — Loop #4 transition tracking
|
||
- `src/vm.c` — `vm_tick()` heartbeat dispatcher (Loop #7)
|
||
- `include/rolling_window_knobs.h` — Tuning knob definitions |