Purpose: Execute rendered simulation scripts across multiple frameworks (PyMDP, RxInfer.jl, ActiveInference.jl, JAX, DisCoPy, PyTorch, NumPyro).
Pipeline Step: Step 12: Execution (12_execute.py)
Category: Simulation / Execution
Status: ✅ Production Ready
Version: 1.0.0
Last Updated: 2026-01-21
- Execute Python simulation scripts (PyMDP, JAX, DisCoPy)
- Execute Julia simulation scripts (RxInfer.jl, ActiveInference.jl)
- Capture simulation results and logs
- Handle execution errors gracefully
- Generate execution reports
- Multi-framework execution support
- Skip vs fail: JAX, NumPyro, PyTorch, and DisCoPy are core dependencies; if the environment is incomplete, scripts are skipped (not run) and reported as "skipped" — they do not count as execution failures. Repair with
uv sync. Julia backends still require a local Julia install. - Graceful degradation when frameworks unavailable
- Automatic PyMDP package detection (distinguishes correct vs wrong package variants)
- Path collection with deduplication (prevents nested directory issues)
- Comprehensive error logging
- Result capture and validation
- Execution timeout handling
process_execute(target_dir: Path, output_dir: Path, verbose: bool = False, logger: Optional[logging.Logger] = None, **kwargs) -> bool
Description: Main execution function called by orchestrator (12_execute.py). Executes rendered simulation scripts across multiple frameworks.
Parameters:
target_dir(Path): Directory containing rendered scripts (typically output from Step 11)output_dir(Path): Output directory for execution resultsverbose(bool): Enable verbose logging (default: False)logger(Optional[logging.Logger]): Logger instance (default: None)frameworks(str): Frameworks to execute ("all", "lite", or comma-separated list, default: "all")"all": Execute all available frameworks"lite": Execute only PyMDP, JAX, DisCoPy (no Julia)- Comma-separated:
"pymdp,jax"for specific frameworks
simulation_engine(str): Engine to use ("auto", "pymdp", "rxinfer", etc., default: "auto")validate_only(bool): Only validate scripts, don't execute (default: False)timeout(int): Execution timeout per script in seconds (default: 300)parallel(bool): Execute scripts in parallel (default: False)**kwargs: Additional framework-specific options
Returns: bool - True if execution succeeded, False otherwise
Example:
from execute import process_execute
from pathlib import Path
import logging
logger = logging.getLogger(__name__)
success = process_execute(
target_dir=Path("output/11_render_output"),
output_dir=Path("output/12_execute_output"),
verbose=True,
frameworks="pymdp,jax",
timeout=600
)execute_simulation_from_gnn(gnn_file: Path, framework: str, output_dir: Path, **kwargs) -> Dict[str, Any]
Description: Execute simulation for specific GNN file and framework.
Parameters:
gnn_file(Path): Path to GNN fileframework(str): Framework to use ("pymdp", "rxinfer", "activeinference_jl", "jax", "discopy")output_dir(Path): Output directory for execution results**kwargs: Framework-specific execution options
Returns: Dict[str, Any] - Execution results dictionary with:
success(bool): Whether execution succeededreturn_code(int): Process return codestdout(str): Standard outputstderr(str): Standard errorduration(float): Execution duration in secondsoutput_files(List[Path]): Generated output files
Description: Get health status of execution environment and framework availability.
Returns: Dict[str, Any] - Health status dictionary with:
pymdp_available(bool): PyMDP availabilityrxinfer_available(bool): RxInfer.jl availabilityactiveinference_jl_available(bool): ActiveInference.jl availabilityjax_available(bool): JAX availabilitydiscopy_available(bool): DisCoPy availabilityjulia_available(bool): Julia installation statuspython_version(str): Python versionjulia_version(Optional[str]): Julia version if available
Module: execute.pymdp.package_detector
Functions:
detect_pymdp_installation() -> Dict[str, Any]: Detect which PyMDP package variant is installed- Returns detection results including
correct_package,wrong_package,has_agent,has_mdp_solver
- Returns detection results including
is_correct_pymdp_package() -> bool: Check if correct package (inferactively-pymdp) is installedget_pymdp_installation_instructions() -> str: Get actionable installation instructionsvalidate_pymdp_for_execution() -> Dict[str, Any]: Validate PyMDP is ready for execution- Returns
readystatus, detection results, and installation instructions
- Returns
Usage:
from execute.pymdp.package_detector import detect_pymdp_installation, is_correct_pymdp_package
detection = detect_pymdp_installation()
if detection.get("wrong_package"):
print("Wrong PyMDP package installed - install inferactively-pymdp")
elif not detection.get("correct_package"):
print("PyMDP not installed - install inferactively-pymdp")simulation_engine(str): Engine to use for execution (default:"auto")"auto": Automatically select best available engine"pymdp": Use PyMDP for Python simulations"rxinfer": Use RxInfer.jl for Julia simulations"activeinference_jl": Use ActiveInference.jl"jax": Use JAX framework"discopy": Use DisCoPy for categorical diagrams
timeout(int): Execution timeout in seconds (default:60)validate_only(bool): Only validate scripts, don't execute (default:False)capture_output(bool): Capture stdout/stderr (default:True)parallel_execution(bool): Execute scripts in parallel (default:False)
julia_path(str): Path to Julia executable (default: auto-detect)python_env(str): Python environment to use (default: current environment)jax_device(str): JAX device to use (default:"cpu", options:"cpu","gpu")
subprocess- Script executionjson- Result serialization
inferactively-pymdp- PyMDP simulation engine (package name:inferactively-pymdp, recovery: skip PyMDP)- Note: The correct package name is
inferactively-pymdp, notpymdp - The execute module automatically detects wrong package variants
- Note: The correct package name is
julia- Julia runtime (recovery: skip Julia scripts)jax- JAX framework (recovery: skip JAX)
from execute import process_execute
success = process_execute(
target_dir=Path("input/gnn_files"),
output_dir=Path("output/12_execute_output"),
simulation_engine="auto"
)execution_results.json- Execution results summaryexecution_report.md- Human-readable reportexecution_logs/*.log- Per-script execution logssimulation_data/*.json- Simulation output data
output/12_execute_output/
├── execution_results/
│ ├── execution_results.json
│ ├── execution_report.md
│ └── execution_logs/
│ ├── pymdp_simulation.log
│ ├── rxinfer_simulation.log
│ └── activeinference_simulation.log
└── simulation_data/
└── results_*.json
- Duration: 32.5s
- Memory: Peak 19.26 MB, Final 13.96 MB
- Status: SUCCESS_WITH_WARNINGS
- Scripts Found: 5
- Scripts Failed: 5 (dependency issues)
- PyMDP: ~1-5 seconds
- RxInfer.jl: ~10-20 seconds (JIT compilation)
- ActiveInference.jl: ~10-15 seconds
- JAX: ~2-8 seconds (with GPU)
- DisCoPy: ~1-3 seconds
- PyMDP unavailable: Log warning, skip PyMDP scripts
- Julia unavailable: Log warning, skip Julia scripts
- JAX unavailable: Log warning, skip JAX scripts
- Script errors: Capture stderr, continue with other scripts
- Timeout: 60s per script (configurable)
- Dependency Errors: Framework not installed
- Syntax Errors: Generated code has errors
- Runtime Errors: Simulation crashes
- Timeout Errors: Execution exceeds limit
- Input: Receives rendered simulation scripts from Step 11 (render)
- Output: Generates execution results for Step 13 (llm analysis), Step 16 (analysis), and Step 23 (report generation)
- Dependencies: Requires rendered code from
11_render.pyoutput
- render/: Consumes rendered simulation scripts
- llm/: Provides execution results for LLM analysis
- analysis/: Provides execution data for statistical analysis
- report/: Provides execution summaries for reports
- PyMDP: Executes Python Active Inference simulations
- Julia Runtime: Executes Julia simulation scripts (RxInfer.jl, ActiveInference.jl)
- JAX: Executes JAX-based simulations
- DisCoPy: Executes categorical diagram computations
11_render.py (Code generation)
↓
12_execute.py (Script execution)
↓
├→ 13_llm.py (LLM analysis of results)
├→ 16_analysis.py (Statistical analysis)
├→ 23_report.py (Execution reports)
└→ output/12_execute_output/ (Execution results)
src/tests/test_execute_overall.pysrc/tests/test_execute_pymdp_integration.pysrc/tests/test_execute_pymdp_package.py
- Current: 79%
- Target: 85%+
- Multi-framework execution
- Error handling and recovery
- Result capture and validation
- Timeout handling
execute.run_simulation- Execute simulation scriptexecute.validate_environment- Validate execution environmentexecute.get_health_status- Get framework health statusexecute.analyze_error- Analyze execution errors
@mcp_tool("execute.run_simulation")
def run_simulation_tool(script_path: str, framework: str) -> Dict[str, Any]:
"""Execute simulation script"""
# Implementationsrc/execute/mcp.py- MCP tool registrations
Symptom: Julia scripts fail to execute
Cause: Julia not installed or not in PATH
Solution:
- Install Julia:
brew install julia(macOS) or download from julialang.org - Verify Julia installation:
julia --version - Check Julia is in PATH:
which julia - Install required Julia packages if needed
Symptom: Execution fails with import errors
Cause: Required packages not installed in environment
Solution:
- Install framework dependencies:
uv pip install inferactively-pymdp jax - Note: The correct PyMDP package name is
inferactively-pymdp, notpymdp - For Julia: Install packages via
julia -e 'using Pkg; Pkg.add("RxInfer")' - Check framework-specific requirements in documentation
Symptom: Error message "Wrong pymdp package installed. Found 'pymdp' with MDP/MDPSolver"
Cause: The wrong pymdp package (with MDP/MDPSolver) is installed instead of inferactively-pymdp
Solution:
- Uninstall wrong package:
uv pip uninstall pymdp - Install correct package:
uv pip install inferactively-pymdp - Or use setup module:
python src/1_setup.py --install_optional --optional_groups pymdp - The execute module automatically detects wrong package variants and provides clear error messages
Symptom: Scripts timeout before completion
Cause: Simulation too complex or timeout too short
Solution:
- Increase timeout:
--timeout 600(10 minutes) - Simplify model complexity
- Use faster frameworks (JAX) for large models
- Process models individually instead of batch
Features:
- Multi-framework execution support
- Graceful degradation when frameworks unavailable
- Comprehensive error logging
- Result capture and validation
- Execution timeout handling
Known Issues:
- None currently
- Next Version: Enhanced parallel execution
- Future: Real-time execution monitoring
Last Updated: 2026-01-21 Maintainer: GNN Pipeline Team Status: ✅ Production Ready Version: 1.0.0 Architecture Compliance: ✅ 100% Thin Orchestrator Pattern