There are 4 packages in this repo:
- morsegraph (from /MorseGraph/) - installed via root pyproject.toml
- CMGDB (from /cmgdb/) - C++ package with Python bindings (@marciogameiro)
- hybrid-dynamics (from /hybrid_boxmap/) - imported as hybrid_dynamics (@bernardorivas)
- MORALS (from /morals/) - depends on CMGDB (@ewertonvieira)
From repo root
pip install -e . # Installs morsegraph
pip install -e ./cmgdb # Installs CMGDB (requires cmake)
pip install -e ./hybrid_boxmap # Installs hybrid-dynamics
pip install -e ./morals # Installs MORALS
Once installed, you import them by their package names (not directory names):
from MorseGraph import Model
import CMGDB
from hybrid_dynamics import HybridSystem
import MORALS
MorseGraph is a lightweight Python library for computing and analyzing Morse graphs of dynamical systems using computational topology methods. It's mostly useful for toy problems. For faster computations, we recommend @cmgdb
MorseGraph provides tools to study the global structure of dynamical systems through discrete abstractions on grids. The library implements outer approximations of dynamics and uses graph-theoretic methods to identify attractors, basins of attraction, and connecting orbits.
Key Features:
- Support for discrete maps, ODEs, data-driven and latent dynamics
- Outer approximation using epsilon-enlargement of boxes
- Parallel computation of box-to-box transitions
- Morse decomposition via (non-trivial) strongly connected components
- Computation of basin of attraction
- ML integration for learning low-dimensional representations
- Built-in visualization utilities
Install the core library with standard dependencies:
pip install -e .This includes: numpy, scipy, networkx, matplotlib, joblib
For machine learning features (Example 5 - learned latent dynamics):
pip install -e .[ml]This adds: torch, scikit-learn
For running tests:
pip install -e .[test]This adds: pytest
import numpy as np
from MorseGraph.grids import UniformGrid
from MorseGraph.dynamics import BoxMapFunction
from MorseGraph.core import Model
from MorseGraph.analysis import compute_morse_graph
from MorseGraph.systems import henon_map
# Define domain and grid
domain = np.array([[-2.5, -0.5], [2.5, 0.5]])
grid = UniformGrid(domain, depth=8)
# Create dynamics
dynamics = BoxMapFunction(henon_map, epsilon=0.01)
# Build model and compute Morse graph
model = Model(grid, dynamics)
morse_graph = compute_morse_graph(model)-
grids.py- Grid discretizationUniformGrid: Rectangular uniform grid with subdivision support
-
dynamics.py- Dynamics implementationsBoxMapFunction: Explicit function-based dynamics with interval arithmeticBoxMapODE: ODE-based dynamics using scipy integrationBoxMapData: Data-driven dynamics with spatial indexing (cKDTree)BoxMapLearnedLatent: Learned latent dynamics for dimensionality reduction
-
core.py- Main computation engineModel: Connects grids and dynamicscompute_box_map(): Parallel computation of box-to-box transitions
-
analysis.py- Graph analysiscompute_morse_graph(): Morse decomposition via SCC analysiscompute_all_morse_set_basins(): Basin of attraction computation
-
plot.py- Visualization utilities- Morse sets, Morse graphs, basins of attraction, data coverage
-
systems.py- Pre-defined dynamical systemshenon_map: Classic chaotic 2D maptoggle_switch_ode: Bistable genetic regulatory networkvan_der_pol_ode: Nonlinear oscillatorlorenz_ode: Chaotic 3D attractor
-
utils.py- Helper functions- Trajectory data generation and I/O
- Latent space utilities for ML workflows
-
models.py- Neural network models (requirestorch)Encoder,Decoder,LatentDynamics: Autoencoder framework
-
training.py- Training utilities for ML models
All examples are located in the examples/ directory with well-organized configuration sections for easy customization.
Analyzes the Hénon map, a classic chaotic 2D discrete dynamical system. Demonstrates:
BoxMapFunctionfor discrete maps- Epsilon-bloating for rigorous outer approximation
- Morse graph computation and visualization
Studies a genetic toggle switch - a bistable biological system with mutual inhibition. Demonstrates:
BoxMapODEfor continuous-time systems- Analysis of multistable dynamics
- Basin of attraction computation
Analyzes the Van der Pol oscillator, a nonlinear system with limit cycle behavior. Demonstrates:
- ODE integration with configurable time horizon
- Visualization of periodic attractors
Computes Morse graphs from trajectory data (Van der Pol). Demonstrates:
BoxMapDatawith k-nearest neighbor interpolation- Data coverage visualization
- Working with sampled trajectories instead of analytical models
Learns a 2D latent representation of the 3D Lorenz system using autoencoders. Demonstrates:
BoxMapLearnedLatentfor ML-based dynamics- Encoder-decoder framework for dimensionality reduction
- Comparing Morse graphs in full vs. latent space
- Requires ML dependencies (
pip install -e .[ml])
cd examples
python 1_map_dynamics.py
python 2_ode_dynamics.py
python 3_ode_dynamics.py
python 4_data_driven.py
python 5_learned_dynamics.py # Requires torchFigures are saved to examples/figures/.
Run the test suite:
pytest # Run all tests
pytest tests/test_dynamics.py # Run specific test file
pytest -v # Verbose output- Python >= 3.8
- Core:
numpy,scipy,networkx,matplotlib,joblib - Optional (ML):
torch,scikit-learn - Testing:
pytest
Box Representation: All boxes are numpy arrays of shape (2, D) where D is dimension.
Rigorous Approximation: The library uses epsilon-bloating to compute rigorous outer approximations of dynamics, ensuring that all true dynamics are captured.
Modularity: Clean separation between grids, dynamics, computation, analysis, and visualization layers.
Performance: Parallel processing via joblib and optimized spatial indexing with scipy's cKDTree.
For detailed architectural information, see CLAUDE.md in the repository.
(License information to be added)
(Citation information to be added)