Files
LithosAnanake/include/inference_engine.h
T

264 lines
9.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef INFERENCE_ENGINE_H
#define INFERENCE_ENGINE_H
#include <stdint.h>
#include <stddef.h>
#include "vm.h" /* For RollingWindowOfTruth, VM structure */
#include "q48_16.h" /* For Q48.16 fixed-point math */
/* ============================================================================
* OpAmp Model: Inference Engine Architecture
* ============================================================================
*
* The inference engine unifies all VM adaptive tuning into a single loop:
*
* Rolling Window of Truth (execution_heat trajectory, metrics)
* ↓
* [Inference Engine]
* ├─ ANOVA Early-Exit: Check if variance stable
* ├─ Window Width Inference: Variance inflection detection
* ├─ Decay Slope Inference: Closed-form linear regression
* └─ Diagnostics: Fit quality, variance metrics
* ↓
* Tuning Outputs (adaptive_window_width, adaptive_decay_slope)
* ↓
* [Apply to VM]
* ↓
* [System Adapts]
* ↓
* [Feedback Loop Repeats]
*
* Key Design Principles:
* - Q48.16 math only (no floating-point)
* - ANOVA early-exit for efficiency (5% variance threshold)
* - Closed-form algorithms (deterministic, fast)
* - Observable diagnostics (RStudio dashboard feed)
*/
/* ============================================================================
* Input Data Structure: Metrics snapshot + window context
* ============================================================================
*/
typedef struct {
VM *vm; /* Owning VM (for dictionary heat snapshots) */
/* === Window Context === */
RollingWindowOfTruth *window; /* Pointer to window of truth */
uint64_t trajectory_length; /* Number of heat entries to analyze */
/* === Current Metrics Snapshot === */
uint64_t prefetch_hits; /* Successful prefetch predictions */
uint64_t prefetch_attempts; /* Total prefetch attempts */
uint64_t hot_word_count; /* Words above execution_heat threshold */
uint64_t stale_word_count; /* Words with execution_heat in low range */
uint64_t total_heat; /* Sum of all execution_heat values */
uint32_t word_count; /* Total dictionary entries */
/* === Baseline (For Trending) === */
uint64_t last_total_heat; /* Total heat from previous check */
uint64_t last_stale_count; /* Stale count from previous check */
} InferenceInputs;
/* ============================================================================
* Output Data Structure: Tuning parameters + diagnostics
* ============================================================================
*/
struct InferenceOutputs {
/* === Tuning Outputs (Apply to VM) === */
uint32_t adaptive_window_width; /* Inferred optimal window size (from variance inflection) */
uint64_t adaptive_decay_slope; /* Inferred decay slope in Q48.16 (from regression) */
/* === Diagnostics (RStudio Dashboard Feed) === */
uint64_t window_variance_q48; /* Variance of heat across window in Q48.16 */
uint64_t slope_fit_quality_q48; /* R² or residual metric in Q48.16 (0.0 to 1.0) */
/* === Status Tracking === */
uint32_t early_exited; /* 1 if ANOVA check skipped full inference, 0 if full run */
uint64_t last_check_tick; /* Timestamp of last full inference (for monitoring) */
};
/* ============================================================================
* Main API: Run Inference Engine
* ============================================================================
*
* Single entry point that handles:
* 1. ANOVA early-exit (check variance stability)
* 2. Full inference (if variance changed significantly)
* 3. Update tuning outputs
*
* Thread-Safety: Safe for synchronous calls from vm_tick()
* (No shared state written; outputs struct is caller-allocated)
*/
/**
* @brief Run adaptive inference engine on window data
*
* High-level flow:
* 1. ANOVA Check: Is variance delta < 5%?
* - YES: Return cached outputs immediately (cost: ~100 cycles)
* - NO: Continue to full inference
*
* 2. Extract trajectory: Fresh execution_heat snapshot from dictionary
*
* 3. Window Width Inference:
* - Compute variance across entire window
* - Detect inflection point (where d(variance)/d(size) → 0)
* - Return optimal window size
*
* 4. Decay Slope Inference:
* - Transform trajectory to log space (ln(heat[t]))
* - Fit linear regression: ln(heat) = a - slope*t
* - Extract slope coefficient in Q48.16
*
* 5. Diagnostics:
* - Compute fit quality (R² or residual)
* - Store variance metric for next early-exit check
*
* @param inputs Snapshot of window + metrics (caller-provided)
* @param outputs Tuning parameters + diagnostics (caller-provided, will be updated)
*
* @return void (results_run_01_2025_12_08 in outputs struct)
*
* Preconditions:
* - inputs != NULL
* - outputs != NULL
* - inputs->window != NULL
* - inputs->window->is_warm == 1 (window has enough data)
* - inputs->trajectory_length > 1
*
* Side Effects:
* - Modifies outputs struct (caller must preserve if caching)
* - Allocates temporary trajectory buffer (freed on return)
*/
void inference_engine_run(InferenceInputs *inputs, InferenceOutputs *outputs);
/* ============================================================================
* Configuration Constants (In vm.h, but referenced here)
* ============================================================================
*
* User-tunable via Makefile:
*
* #define HEARTBEAT_INFERENCE_FREQUENCY 5000
* - Ticks between full inference runs
* - Decreasing = faster response, more CPU
* - Increasing = slower response, less CPU
*
* #define VARIANCE_SIGNIFICANCE_THRESHOLD 5
* - Percentage (0-100) at which variance change triggers re-inference
* - Default: 5% (skip inference if variance changed < 5%)
* - Decreasing = more frequent re-inference (conservative)
* - Increasing = less frequent re-inference (aggressive)
*
* #define ADAPTIVE_MIN_WINDOW_SIZE 256
* - Minimum effective_window_size (never shrink below this)
* - Ensures minimum statistical validity
* - Increasing = higher overhead, more accuracy
*/
/* ============================================================================
* Helper Functions (For Testing / Diagnostics)
* ============================================================================
*/
/*
* @brief Pretty-print inference outputs for logging
*
* Format: "window_width=XXX variance_q48=YYYY slope_q48=ZZZZ fit_quality=WWWW"
*
* @param outputs Inference outputs struct
* @return Pointer to static string (valid until next call)
*/
const char* inference_outputs_to_string(const InferenceOutputs *outputs);
/*
* @brief Validate inference outputs for sanity
*
* Checks:
* - window_width is within [ADAPTIVE_MIN_WINDOW_SIZE, ROLLING_WINDOW_SIZE]
* - slope_q48 is reasonable (between 0.001 and 100 in Q48.16)
* - variance and fit_quality are between 0.0 and 1.0 in Q48.16
*
* @param outputs Inference outputs to validate
* @return 1 if valid, 0 if suspicious
*/
int inference_outputs_validate(const InferenceOutputs *outputs);
/* ============================================================================
* Internal Functions (Exposed for Unit Testing)
* ============================================================================
*/
/*
* @brief Compute variance of heat data in Q48.16 format
*
* @param heat_data Array of heat values
* @param length Number of elements in array
* @return Variance in Q48.16 format
*/
q48_16_t compute_variance_q48(const uint64_t *heat_data, uint64_t length);
/*
* @brief Find variance inflection point for optimal window width
*
* @param heat_data Array of heat values
* @param trajectory_length Total trajectory length
* @param full_variance Variance of full trajectory
* @return Optimal window width
*/
uint32_t find_variance_inflection(const uint64_t *heat_data, uint64_t trajectory_length, q48_16_t full_variance);
/*
* @brief Infer decay slope from heat trajectory using linear regression
*
* @param heat_data Array of heat values
* @param length Number of elements
* @return Decay slope in Q48.16 format
*/
uint64_t infer_decay_slope_q48(const uint64_t *heat_data, uint64_t length);
#endif /* INFERENCE_ENGINE_H */