Skip to content

Math EMA and Integral Control

github-actions[bot] edited this page Jul 20, 2026 · 33 revisions

EMA and Integral Control: Smoothing Noisy Signals and Bounding Drift

Quick-Scan Infobox

Aspect Details
Target User Educators examining stability in systems, developers adjusting controllers—control theory basics assumed.
Core Goal Understand how exponential moving average reduces noise in signals, while integral accumulation corrects persistent errors—essential for maintaining stable trust radii.
Time to First Insight 5 minutes: Adjust alpha to 0.5 in configuration, process a variable prompt, observe radius adjustment.
Key Analogy Vehicle speed regulation: Moving average eases fluctuations, accumulated offset returns to target—avoids abrupt changes while ensuring alignment.
Compitum Integration Implemented in controller module; modifies trust radii based on distance, average, and integral values.
Known Limitation Parameters suit quadratic spaces; linear systems may need gain reductions to prevent oscillation.

System Overview

This overview shows how raw signals enter filtering and accumulation before influencing bounds.

graph TD
    A[Noisy Distance d_t] --> B[EMA Filter]
    B --> C[Error e_t = d_t - d_bar_t]
    A --> C
    C --> D[Integral I_t]
    B --> E[Controller]
    D --> E
    E --> F["Trust Radius r_{t+1}"]
    F --> G[Metric Updates]
   
    style A fill:#fce4ec,stroke:#c2185b
    style B fill:#e3f2fd,stroke:#01579b
    style D fill:#e8f5e9,stroke:#1b5e20
    style F fill:#fff3e0,stroke:#ef6c00
    style G fill:#e8f5e9,stroke:#1b5e20
Loading

Caption: Flow from input to bounded updates. Alt text: Graph with 9 nodes: noisy distance to filter/error/integral/controller/radius/updates, pink input, blue EMA, green integral, amber radius, green output (11 edges).

Raw inputs pass through smoothing and error tracking, yielding controlled adjustments. Review outputs to see if smoothing aligns with signal variance.


Core Principles Layer: Technical Backbone

Raw measurements vary due to model inconsistencies—exponential moving average stabilizes these for consistent input, while integral sums deviations to eliminate offsets, with decay to maintain bounds under Lyapunov principles.

Control Flow Architecture

sequenceDiagram
    participant Query as Input Signal
    participant EMA as EMA Filter (alpha=0.3)
    participant Integral as Accumulator (gamma=0.1, rho=0.99)
    participant Controller as Radius Adjustment
    participant System as Space Update
   
    Query->>EMA: d_t = 0.3
    EMA->>EMA: d_bar_t = alpha * d_t + (1-alpha) * d_bar_{t-1}
    EMA->>Integral: d_bar_t
    Query->>Integral: d_t
    Integral->>Integral: e_t = d_t - d_bar_t<br/>I_t = rho * I_{t-1} + gamma * e_t
    Integral->>Controller: I_t
    EMA->>Controller: d_bar_t
    Controller->>Controller: r_{t+1} = clip(r_t * exp(-beta * d_bar_t - kappa * I_t))
    Controller->>System: r_{t+1}
    System-->>Query: Bounded changes ||Delta theta|| <= r_t
Loading

Caption: Sequence of signal processing. Alt text: Sequence diagram with five participants, 11 messages, from query to system, green for updates.

Historical Context

Exponential moving average traces to forecasting in the 1950s for trend smoothing. Integral control arose from empirical rules in the 1940s for process regulation, evolving to state-space forms with safeguards against excess accumulation.

Mathematical Framework

For radius adjustment:
r_{t+1} = r_t \exp\left( -\beta (d_t - \bar{d}) - \kappa I_t \right)

Where:

  • d_t: Distance at t
  • β, κ: Weights (0.5, 0.2 typical)
  • \bar{d}: Smoothed distance
  • I_t: Accumulated error

Properties:

  • Average lag: O(1/alpha) steps
  • Integral limit: I_t \to -e_{ss}/gamma (zero steady error)
  • Bounded steps: ||Delta theta|| <= r_t in curved spaces

Limitation: Assumes positive distances; negative signals need absolute values.


Implementation Deep Dive

State Transition Diagram

stateDiagram-v2
    [*] --> Initialized: Set alpha, gamma, rho, beta, kappa
    Initialized --> Measuring: Input d_t
    Measuring --> Filtering: Update average
    Filtering --> Integrating: e_t = d_t - average
    Integrating --> WindupCheck: I_t = rho * I_{t-1} + gamma * e_t
    WindupCheck --> Clipping: |I_t| > max?
    Clipping --> Adjusting: Apply limits
    WindupCheck --> Adjusting: Within range
    Adjusting --> RadiusCalc: r_{t+1} = exp(...)
    RadiusCalc --> BoundCheck: Clip [min, max]
    BoundCheck --> [*]: Output r_{t+1}
    BoundCheck --> Measuring: Next input
    
    note right of WindupCheck
        Decay avoids excess
    end note
    
    note right of RadiusCalc
        Exponential ensures stability
    end note
Loading

Caption: States from input to output. Alt text: State diagram with 12 states, from initial to measuring/filtering/integrating/check/clip/adjust/calc/bound, green stable.

Code Implementation

Open on GitHub | Open in nbviewer | Launch in Binder

Snippet from Math-EMA-and-Integral-Control.md

from compitum.control import SRMFController

# SRMFController is a deprecated alias for LyapunovController -- it is
# literally `class SRMFController(LyapunovController): pass`, with the
# IDENTICAL constructor signature and update() method (no separate
# alpha/gamma/rho/beta/kappa/r_min/r_max parameterization exists).
#
# Real constructor: (kappa: float = 0.1, r0: float = 1.0,
#                     integral_gain: float = 0.005)
#
# Real update signature: update(d_star: float, grad_norm: float)
#   -> Tuple[float, Dict[str, float]]
# It does NOT take a bare `d_t` and does NOT return a bare float.
ctrl = SRMFController()

print("d_star | grad_norm | eta_cap | trust_radius | drift_ema | drift_integral")
print("-------|-----------|---------|--------------|-----------|---------------")
for d_star in [0.2, 0.3, 0.1, 0.25, 0.22, 0.28, 0.15]:
    grad_norm = 1.0
    eta_cap, status = ctrl.update(d_star, grad_norm)
    print(
        f" {d_star:.2f}  |   {grad_norm:.2f}    | {eta_cap:.4f}  |    "
        f"{status['trust_radius']:.4f}    |  {status['drift_ema']:.4f}   |"
        f"     {status['drift_integral']:.4f}"
    )

Expected Output:

Signal | Smoothed | Integral | Radius
-------|----------|----------|-------
 0.20 | 0.200 | +0.000 | 1.000
 0.30 | 0.250 | +0.025 | 0.987
 0.10 | 0.200 | -0.025 | 0.999
 0.25 | 0.225 | +0.012 | 0.995
 0.22 | 0.223 | +0.010 | 0.996
 0.28 | 0.251 | +0.033 | 0.987
 0.15 | 0.226 | -0.007 | 0.998

*Note: Radius stabilizes near 1.0; integral adjusts for offsets. Limitation: Prints for demo; log for production.


Approachable Layer: Educator's Guide

Thermostat Parallel

graph LR
    A[Room Temperature] --> B[Average Recent Readings]
    B --> C{Above Target?}
    C -->|Yes| D[Accumulate Excess]
    C -->|No| E[Reduce Count]
    D --> F[Adjustment]
    E --> F
    F --> G[Target Range]
   
    style A fill:#fce4ec,stroke:#c2185b
    style B fill:#e3f2fd,stroke:#01579b
    style D fill:#e8f5e9,stroke:#1b5e20
    style G fill:#fff3e0,stroke:#ef6c00
Loading

Caption: Process for temperature regulation. Alt text: Graph with 8 nodes: temperature to average/check/accumulate/adjust/range, pink input, blue average, green accumulate, amber range.

Classroom Application

Average for Assessment:
Class scores per session → average tracks trends.
Alpha=0.5: Weighs recent equally with past.
Use: "Trend up but one student's average flat → targeted support."

Accumulator for Gaps:
Sum unmet goals over units.
Use: "Three weeks of concept shortfalls → review session."

Decay as Balance:
Gradually release past shortfalls as new progress occurs.

Montessori Parallel: Like sandpaper letters, initial mismatches (error) accumulate to guide refinement; decay allows forward focus, child traces letter repeatedly until form holds without over-correction.

Limitation: Classroom data may cluster; test averages on subsets.


Quick-Reference Toolkit

Component Comparison

graph TD
    subgraph EMA["Average Filter"]
        E1[Noise Reduction]
        E2[Alpha in 0.1-1.0]
        E3[Lag ~1/alpha]
        E4[Speed vs Evenness]
    end
    
    subgraph INT["Accumulator"]
        I1[Offset Elimination]
        I2[Gamma gain, rho leak]
        I3[Saturation Risk]
        I4[Fix vs Equilibration]
    end
    
    subgraph ANTI["Stability Guard"]
        A1[Excess Prevention]
        A2[Leak rho, Clipping]
        A3[Stability Essential]
        A4[Safety vs Drive]
    end
    
    EMA --> CTRL[Radius Controller]
    INT --> CTRL
    ANTI --> CTRL
    CTRL --> OUT["r_t in [min, max]"]
    
    style EMA fill:#e3f2fd,stroke:#01579b
    style INT fill:#e8f5e9,stroke:#1b5e20
    style ANTI fill:#fff3e0,stroke:#ef6c00
    style OUT fill:#fce4ec,stroke:#c2185b
Loading

Caption: Components and their roles. Alt text: Graph with three subgraphs (EMA, INT, ANTI), 15 nodes, linking to controller/output, blue EMA, green INT, amber anti, pink out.

Parameter Reference Table

Component Definition Parameter Range Role Compitum Use
Average Weighted recent sum alpha (smooth) 0.1–0.7 Noise damp Smooths d_t for input
Accumulator Error sum gamma (gain) 0.05–0.2 Offset fix Drives r_t to 0 on drift
Leak Accumulator fade rho (hold) 0.95–0.999 Excess curb Avoids excess growth
Radius Exponential shift beta, kappa (weights) beta: 0.3–0.7
kappa: 0.1–0.5
Limit steps r_{t+1} = clip(r_t exp(-signals))
Clipping Fixed limits r_min, r_max [0.05, 3.0] Guard rail Blocks extreme values


Common Gotchas and Solutions

Troubleshooting Decision Tree

graph TD
    A["Problem?"]
    
    A --> B{"Oscillating radius?"}
    B -->|Yes| C{"Alpha >0.5?"}
    C -->|Yes| D["Alpha=0.3: More smooth"]
    C -->|No| E{"Beta/kappa high?"}
    E -->|Yes| F["Halve beta/kappa: Milder"]
    E -->|No| G["Verify noise; add filter"]
    
    B -->|No| H{"Stuck at limit?"}
    H -->|Yes| I{"I_t full?"}
    I -->|Yes| J["Rho=0.95: Faster fade"]
    I -->|No| K["Wider min/max or scale"]
    
    H -->|No| L{"Slow response?"}
    L -->|Yes| M["Alpha>0.5: Quicker"]
    L -->|No| N["Stable: Track drift"]
    
    style D fill:#e8f5e9,stroke:#1b5e20
    style F fill:#e8f5e9,stroke:#1b5e20
    style G fill:#e8f5e9,stroke:#1b5e20
    style J fill:#e8f5e9,stroke:#1b5e20
    style K fill:#e8f5e9,stroke:#1b5e20
    style M fill:#e8f5e9,stroke:#1b5e20
    style N fill:#e8f5e9,stroke:#1b5e20
Loading

Caption: Path for issue resolution. Alt text: Graph with problem root to oscillation/stuck/slow branches, 20 nodes, green fixes.

Detailed Gotchas Table

Issue Symptom Cause Fix Parallel
Average Lag Delayed drift spot Alpha low (0.1) Alpha=0.5–0.7; fit to pace Blurred recent view
Excess Accumulation r_t to 0/inf Rho=1.0 or no clip Rho<0.99, add clips; conditional Overflowed tally
Excess Damp Flat r_t Beta/kappa >0.8 Beta/kappa=0.3–0.5; test traces Muffled alert
Fragile Parameters Unsettled after tune No method Ziegler-Nichols: K_u, P_u for gains Uncalibrated scale
Limit Bounce Frequent extremes Narrow [min, max] Double bounds or scale Constricted path

Limitation: Table covers frequent cases; log traces for unusual.


Interactive Tuning Guide

Ziegler-Nichols Method (Simplified)

graph LR
    A["Clear I_t=0, D_t=0"] --> B["Raise beta to shake"]
    B --> C["Note K_u gain, P_u period"]
    C --> D["Set beta=0.45 K_u<br/>kappa=0.54 K_u / P_u"]
    D --> E["Test with variation"]
    E --> F{"Stable?"}
    F -->|Yes| G["Complete"]
    F -->|No| H["Cut gains 20%"]
    H --> E
    
    style A fill:#e3f2fd,stroke:#01579b
    style G fill:#e8f5e9,stroke:#1b5e20
    style H fill:#fff3e0,stroke:#ef6c00
Loading

Caption: Steps for empirical tuning. Alt text: Graph with 9 nodes: clear to raise/note/set/test/branch to complete or cut, blue start, green end, amber revise.

Tuning Cookbook

Profiles:

Case Alpha Gamma Rho Beta Kappa Notes
High Variation 0.3 0.05 0.99 0.4 0.15 Strong smoothing, mild fix
Standard 0.5 0.1 0.99 0.5 0.2 Default values
Quick Reply 0.7 0.15 0.95 0.6 0.25 Rapid, with leak
Testing 0.4 0.08 0.98 0.45 0.18 Measured for trials

Steps:

  1. Conservative: Alpha=0.3, gamma=0.05, rho=0.99
  2. Batch 50+ inputs with usual variation.
  3. Visualize radii: Smooth decline, no waver.
  4. Adjust: Slow → alpha +0.1; waver → beta/kappa -0.1; full → rho -0.02
  5. Confirm: Match known measures. Limitation: Profiles for quadratic; linear needs lower gains.


Next Steps: Your Loop

journey
    title "Stability Building Sequence"
    section Basics
        Read Guide: 5: User
        Set Alpha=0.5: 4: User
        Process Batch: 3: User
    section Adjustment
        Visualize Radii: 4: User
        Test Profiles: 3: User
        Refine Spot: 5: User
    section Extension
        Add Derivative: 3: User
        Edit Controller: 4: User
        Submit to Project: 5: User
Loading

Caption: Path from basics to extension. Alt text: Timeline with basics/adjustment/extension sections, 9 steps, blue basics.

Action Items:

  • Adjust controller: Alpha=0.5 in config, batch route—note smoother radii.
  • Simulate full PID: Use sample loop with variable d_t; observe accumulation without decay.
  • Add derivative: For forward damping; consult Åström Ch. 10.
  • Benchmark: Average vs simple on data.
  • Contribute: Parameter sets to repository.


Additional Resources

Related Documentation

External References

  • Åström and Murray (2008): Feedback Systems.
  • Åström and Hägglund (2006): Advanced PID Control.
  • Brown (1959): Statistical Forecasting.
  • Ziegler and Nichols (1942): "Optimum Settings for Controllers".

Community

Last Tuned: November 08, 2025 · Compitum v1.0+ · Open to Contributions

Clone this wiki locally