Architecture

Understanding ControlDESymulation’s Internal Design

Introduction

ControlDESymulation is built on a type-driven, composition-based architecture that achieves mathematical rigor, software engineering excellence, and multi-backend performance simultaneously. This section provides comprehensive documentation of the framework’s internal design for developers and advanced users.

ImportantWho Should Read This?

Most users do NOT need to read architecture documentation. If you’re:

  • Using built-in systems from cdesym.systems.builtin.*
  • Defining custom systems by subclassing ContinuousSymbolicSystem or DiscreteSymbolicSystem
  • Following tutorials and examples

Then you can skip this section entirely. The architecture documentation is intended for:

  • Framework contributors and maintainers
  • Advanced users implementing custom integrators or utilities
  • Researchers studying the framework’s design
  • Developers extending the framework with new capabilities

Architecture Documents

The framework consists of 7 architectural layers, each documented separately:

1. Design Philosophy

Start here to understand the core principles that guide the framework’s design.

Topics covered:

  • Type-driven design philosophy
  • Composition over inheritance
  • Backend agnosticism
  • Zero code duplication
  • Progressive disclosure of complexity
  • Design patterns and trade-offs

Read this if: You want to understand why the framework is built the way it is, or you’re contributing new features.

2. Type System Architecture

The foundational Layer 0 that provides semantic types, structured results, and type-safe interfaces.

Topics covered:

  • Multi-backend array types (NumPy, PyTorch, JAX)
  • Semantic vector/matrix types (StateVector, GainMatrix, etc.)
  • TypedDict structured results (IntegrationResult, LQRResult, etc.)
  • Protocol-based interfaces for duck typing with type safety
  • 200+ type definitions across 8 modules

Read this if: You’re implementing custom components, need to understand type conventions, or want to leverage IDE support.

3. UI Framework Architecture

The user-facing Layer 3 for defining and working with dynamical systems.

Components documented:

  • Layer 0: SymbolicSystemBase - Time-domain agnostic foundation
  • Layer 1: ContinuousSystemBase, DiscreteSystemBase - Time-domain interfaces
  • Layer 2: ContinuousSymbolicSystem, DiscreteSymbolicSystem - Concrete implementations
  • Layer 3: ContinuousStochasticSystem, DiscreteStochasticSystem - Stochastic extensions

Read this if: You’re defining custom systems, extending the framework, or need to understand the class hierarchy.

4. Delegation Layer

The internal service layer that provides specialized utilities through composition.

Components documented:

  • Core Utilities: BackendManager, CodeGenerator, EquilibriumHandler, SymbolicValidator
  • Deterministic Evaluation: DynamicsEvaluator, LinearizationEngine, ObservationEngine
  • Stochastic Support: DiffusionHandler, NoiseCharacterizer, SDEValidator
  • Low-Level Utilities: codegen_utils

Read this if: You’re implementing custom system types or need to understand how symbolic-to-numerical compilation works.

5. Integration Framework

Multi-backend numerical integration for ODEs and SDEs.

Topics covered:

  • Integrator architecture and factories
  • Deterministic integrators (Scipy, TorchDiffEq, Diffrax, DiffEqPy, Fixed-step)
  • Stochastic integrators (TorchSDE, Diffrax SDE, DiffEqPy SDE)
  • 40+ integration methods across 4 backends
  • Integration result types and performance tracking

Read this if: You’re implementing custom integrators, need to understand method selection, or want to optimize integration performance.

6. Control Framework Architecture

Classical control theory algorithms for analysis and synthesis.

Topics covered:

  • Control Design: LQR, Kalman filter, LQG controller design
  • System Analysis: Stability, controllability, observability analysis
  • Pure functional architecture with thin composition wrappers
  • Unified continuous/discrete interface
  • TypedDict results (LQRResult, KalmanFilterResult, StabilityInfo, etc.)

Read this if: You’re using control design methods, need to understand the control API, or want to extend control capabilities.

7. Visualization Framework

Interactive, publication-ready plotting for dynamical systems analysis.

Components documented:

  • Theming layer (colors, styles, themes)
  • TrajectoryPlotter - Time-domain visualization
  • PhasePortraitPlotter - State-space visualization
  • ControlPlotter - Control analysis plots

Read this if: You’re extending visualization capabilities or need to understand the plotting system architecture.

Quick Navigation

By User Level

Beginners: - Skip architecture docs - use Getting Started instead

Intermediate Users: - Read Design Philosophy for conceptual understanding - Skim UI Framework for custom system definition - Skim Visualization Framework for plotting capabilities

Advanced Users: - Study all architecture documents - Focus on Type System for understanding type conventions - Focus on Integration Framework for custom numerical methods - Reference Delegation Layer for system extension - Reference Control Framework for control design algorithms

By Use Case

I want to understand the framework’s design principles:Design Philosophy

I want to understand the type system and conventions:Type System Architecture

I want to define a custom dynamical system:UI Framework Architecture

I want to implement a custom integrator:Integration Framework

I want to extend the system base classes:Delegation Layer

I want to use or extend control design (LQR, Kalman, LQG):Control Framework Architecture

I want to customize or extend plotting:Visualization Framework

I want to understand symbolic-to-numerical compilation:Delegation Layer → CodeGenerator

I want to add a new backend (e.g., TensorFlow):Design Philosophy → Extension Points → Delegation Layer → BackendManager

Architecture Statistics

The framework consists of:

  • 50+ core files organized into 7 architectural layers
  • 200+ types for semantic clarity and IDE support
  • 55+ integration methods across NumPy, PyTorch, JAX, and Julia backends
  • 11 delegation layer utilities providing specialized services
  • Classical control algorithms (LQR, Kalman, LQG, stability, controllability, observability)
  • 8 core UI framework classes for system definition
  • 16+ plot types for comprehensive visualization
  • Zero code duplication through strategic abstraction

Design Principles Summary

TipCore Principles
  1. Type-Driven Design - Types are not just annotations—they are the architecture
  2. Composition Over Inheritance - Build systems from specialized utilities
  3. Backend Agnosticism - Write once, run on NumPy/PyTorch/JAX
  4. Zero Code Duplication - Every line exists in exactly one place
  5. Structured Results - TypedDict for all outputs with IDE support
  6. Protocol-Based Interfaces - Duck typing with type safety
  7. Factory Pattern - Hide complexity behind simple creation methods
  8. Semantic Naming - Names convey mathematical meaning
  9. Progressive Disclosure - Simple things simple, complex things possible

Common Architectural Questions

Why composition instead of inheritance?

Short answer: Single responsibility, testability, and flexibility.

Long answer: See Design Philosophy

Why support multiple backends?

Short answer: Different backends excel at different tasks—NumPy for CPU, PyTorch for GPUs/neural networks, JAX for optimization.

Long answer: See Design Philosophy

Where does symbolic-to-numerical compilation happen?

Short answer: In the CodeGenerator utility, with per-backend caching.

Long answer: See Delegation Layer

How are integrators selected automatically?

Short answer: Through the IntegratorFactory which chooses based on system properties and backend.

Long answer: See Integration Framework

How does the framework avoid code duplication?

Short answer: Through SymbolicSystemBase providing shared functionality to both continuous and discrete systems.

Long answer: See UI Framework Architecture and Design Philosophy

What types should I use for my custom components?

Short answer: Use semantic types like StateVector, ControlVector, and TypedDict results like IntegrationResult.

Long answer: See Type System Architecture

How do I design an LQR controller?

Short answer: Use system.control.design_lqr(A, B, Q, R) after linearizing your system.

Long answer: See Control Framework Architecture

How do I define a custom dynamical system?

Short answer: Subclass ContinuousSymbolicSystem or DiscreteSymbolicSystem and implement define_system().

Long answer: See UI Framework Architecture

Contributing to the Framework

If you’re interested in contributing:

  1. Start with Design Philosophy to understand core principles
  2. Review Type System Architecture to understand type conventions
  3. Study the relevant layer docs for your contribution area:
  4. Follow the established patterns (composition, type-driven design, etc.)
  5. Write comprehensive tests for each component in isolation
  6. Document your additions with clear examples and type annotations

See Contributing Guidelines for more details.

Getting Help

  • Questions about architecture? Open a discussion on GitHub
  • Found a design issue? File an issue with the “architecture” label
  • Want to propose an enhancement? Start with a discussion to align with design principles

Remember: Most users don’t need to read architecture documentation. The framework is designed so you can be productive without understanding its internals. These documents are here when you need them.