Purpose: Code generation for simulation frameworks from parsed GNN/POMDP specifications.
Pipeline Step: Step 11: Code rendering (11_render.py)
Category: Code Generation / Simulation Framework Integration
Status: ✅ Production Ready
Version: 1.6.0
Last Updated: 2026-04-24
- Generate simulation code for multiple frameworks
- Convert GNN specifications to executable implementations
- Support framework-specific optimizations
- Provide framework compatibility validation
- Generate documentation and usage examples
- Multi-framework code generation (see Supported Frameworks)
- POMDP-aware rendering via
POMDPRenderProcessor(per-model/per-framework output folders) - Framework compatibility checks and matrix normalization before rendering
- Structured summaries written to
render_processing_summary.json
- Purpose: Active Inference simulation in Python
- Features: Full PyMDP agent implementation
- Output: Complete Python simulation scripts
- Optimization: Matrix optimization, memory efficiency
- Purpose: Probabilistic programming and inference
- Features: Reactive inference engine
- Output: Julia scripts with TOML configuration
- Optimization: Reactive constraints, efficient inference
- Purpose: Active Inference framework implementation
- Features: Complete Active Inference agent
- Output: Julia simulation scripts
- Optimization: Hierarchical processing, temporal dynamics
- Purpose: Categorical diagrams for compositional models
- Features: String diagram generation
- Output: Python DisCoPy diagrams
- Optimization: Categorical composition, type checking
- Purpose: High-performance numerical computing
- Features: JIT compilation, automatic differentiation
- Output: JAX-optimized simulation code
- Optimization: GPU acceleration, vectorization
- Purpose: Neural integration backend
- Output: Python scripts under
pytorch/when the renderer is available
- Purpose: Probabilistic programming backend
- Output: Python scripts under
numpyro/when the renderer is available
- Purpose: Probabilistic programming model backend
- Output: Stan models under
stan/when requested
- Purpose: Bayesian network / causal model backend
- Output: Python scripts under
bnlearn/when requested
The canonical framework inventory lives in framework_registry.py; update that
registry before changing public framework lists, MCP enums, or processor configs.
process_render(target_dir: Path, output_dir: Path, verbose: bool = False, frameworks: Optional[List[str] | str] = None, strict_validation: bool = True, strict_framework_success: bool = False, **kwargs) -> Union[bool, int]
Description: Main rendering processing function called by orchestrator (11_render.py). Processes GNN files and generates code for multiple simulation frameworks.
Parameters:
target_dir(Path): Directory containing GNN files to processoutput_dir(Path): Output directory for rendered filesverbose(bool): Enable verbose logging (default: False)frameworks(Optional[List[str] | str]): Restrict rendering to a subset of frameworks. AcceptsNone/"all"for all configured frameworks,"lite"forpymdp,jax,discopy, andbnlearn, or a comma-separated string such as"pymdp,jax".strict_validation(bool): Passed to POMDP extraction (Trueby default)strict_framework_success(bool): WhenTrue, every requested framework render must succeed for every input file. Explicit framework requests such as"pymdp"or"pymdp,jax"are strict even when this flag is omitted;"all"and"lite"keep aggregate pipeline policy unless the flag is set.**kwargs: Additional options forwarded to framework renderers (e.g.timesteps,simulation_params)
Returns: Union[bool, int] - True when the render policy succeeds, False when it fails, or 2 when no input files are found.
Example:
from render import process_render
from pathlib import Path
success = process_render(
target_dir=Path("input/gnn_files"),
output_dir=Path("output/11_render_output"),
verbose=True,
frameworks=["pymdp", "rxinfer"],
strict_validation=True,
strict_framework_success=True,
)render_gnn_spec(gnn_spec: Dict[str, Any], target: str, output_directory: Union[str, Path], options: Optional[Dict[str, Any]] = None) -> Tuple[bool, str, List[str]]
Description: Render a GNN specification dictionary to a target framework.
Parameters:
gnn_spec(Dict[str, Any]): Parsed GNN specification dictionarytarget(str): Target framework ("pymdp", "rxinfer", "activeinference_jl", "jax", "discopy")output_directory(Union[str, Path]): Output directory for generated codeoptions(Optional[Dict[str, Any]]): Framework-specific options (default: None)
Returns: Tuple[bool, str, List[str]] - Tuple containing:
success(bool): Whether rendering succeededmessage(str): Status messagegenerated_files(List[str]): List of generated file paths
Location: src/render/processor.py
For POMDP targets, render_gnn_spec(...) and Step 11 both route through the same validated renderers:
render_gnn_to_pymdp(...)render_gnn_to_rxinfer(...)render_gnn_to_activeinference_jl(...)
The shared contract is canonical_pomdp_v1; B is stored as (next_state, previous_state, action).
Description: Get information about the render module capabilities.
Returns: Dict[str, Any] - Dictionary with module information containing:
name(str): Module nameversion(str): Module versiondescription(str): Module descriptionsupported_targets(List[str]): List of supported target frameworksavailable_targets(List[str]): List of currently available targetsfeatures(List[str]): List of available featuressupported_formats(List[str]): List of supported output formatsprocessing_modes(List[str]): List of available processing modes
Location: src/render/processor.py
Description: Get information about available renderers for each framework.
Returns: Dict[str, Dict[str, Any]] - Dictionary mapping framework names to renderer information:
- Each framework entry contains:
name(str): Framework namedescription(str): Framework descriptionlanguage(str): Target languagefile_extension(str): Output file extensionsupported_features(List[str]): List of supported featuresfunction(str): Function name for renderingoutput_format(str): Output format typepomdp_compatible(bool): Whether POMDP-aware processing is supported
Location: src/render/processor.py
Description: Validate POMDP state space structure for rendering compatibility.
Parameters:
pomdp_space(Any): POMDP state space object to validate
Returns: Tuple[bool, List[str]] - Tuple containing:
is_valid(bool): Whether POMDP structure is validerrors(List[str]): List of validation error messages
Location: src/render/processor.py
Description: Normalize POMDP matrices for consistent rendering.
Parameters:
pomdp_space(Any): POMDP state space objectlogger: Logger instance for logging
Returns: Any - Normalized POMDP state space object
Location: src/render/processor.py
Parameters:
model_data: GNN model dataoutput_path: Optional output file path
Returns: Generated JAX code as string
numpy- Numerical computationspathlib- Path manipulationtyping- Type hints
- PyMDP:
pymdppackage - RxInfer.jl: Julia with RxInfer.jl package
- ActiveInference.jl: Julia with ActiveInference.jl package
- DisCoPy:
discopypackage - JAX:
jax,jaxlibpackages
gnn.parsers- GNN parsing and validationutils.pipeline_template- Pipeline utilities
PYMDP_CONFIG = {
'inference_algorithm': 'VMP',
'learning_rate': 0.1,
'num_iterations': 100,
'convergence_threshold': 1e-6
}
RXINFER_CONFIG = {
'inference_engine': 'reactive',
'optimization': 'auto',
'constraints': 'default'
}Configuration is primarily controlled by the Step 11 orchestrator (src/11_render.py) and forwarded parameters to process_render(...). Avoid documenting configuration keys that are not backed by code.
Step 11 CLI options relevant to framework scoping:
uv run python src/11_render.py \
--target-dir input/gnn_files \
--output-dir output \
--frameworks pymdp \
--strict-framework-successExplicit --frameworks selections are strict by default. --strict-framework-success applies the same all-requested-frameworks policy to broader "all" or "lite" runs.
from render.renderer import render_gnn_spec
# Render GNN to PyMDP
success, message, files = render_gnn_spec(
gnn_spec=model_data,
target="pymdp",
output_directory="output/11_render_output",
options={"include_examples": True}
)from render.renderer import render_gnn_spec
for framework in ["pymdp", "rxinfer", "activeinference_jl"]:
success, message, files = render_gnn_spec(model_data, framework, "output/11_render_output")
assert success, message# Framework-specific options
options = {
'pymdp': {
'inference_algorithm': 'VMP',
'num_iterations': 200
},
'rxinfer': {
'constraints': 'custom',
'optimization': 'performance'
}
}uv run python src/main.py \
--only-steps 11 \
--target-dir input/gnn_files/pymdp_scaling_study \
--output-dir output/pymdp_scaling_pipeline \
--frameworks pymdp \
--strict-framework-success- Framework artifacts are written under per-model/per-framework subfolders (POMDP-aware mode), typically one primary script per framework:
pymdp/<model_name>_pymdp.pyrxinfer/<model_name>_rxinfer.jlactiveinference_jl/<model_name>_activeinference.jljax/<model_name>_jax.pydiscopy/<model_name>_discopy.py- optional/requested backends:
pytorch/,numpyro/,stan/,bnlearn/
render_processing_summary.json- Processing summary
output/11_render_output/
├── render_processing_summary.json
└── [model_stem]/
├── pymdp/
├── rxinfer/
├── activeinference_jl/
├── jax/
├── discopy/
├── pytorch/ # if requested and available
├── numpyro/ # if requested and available
├── stan/ # if requested and available
└── bnlearn/ # if requested and available
Performance is tracked by the pipeline execution summaries and render summary JSON output. Avoid hard-coding numeric claims in docs unless they are generated from current benchmark outputs.
- Syntax Errors: Invalid GNN specification
- Framework Errors: Framework-specific generation issues
- Dependency Errors: Missing framework packages
- Configuration Errors: Invalid framework options
- Framework Scope: Use
--frameworks <name>to isolate a backend while debugging. - Strict Policy: Use explicit
--frameworksselections for focused strict runs; add--strict-framework-successwhen"all"or"lite"should also fail on any framework render failure. - Partial Generation: Omit strict framework success when exploratory runs should keep usable artifacts.
- Error Documentation: Review
render_processing_summary.json, includingfailed_framework_renderings.
- Script:
11_render.py(Step 11) - Function:
process_render()
gnn.parsers- GNN parsing and validationutils.pipeline_template- Pipeline utilities
tests.test_render_*- Render testsexecute.executor- Execution framework integration
GNN Parsing → Model Validation → Framework Selection → Code Generation → Framework-Specific Optimization → Output Generation
src/tests/render/test_render_integration.py- Integration testssrc/tests/render/test_render_overall.py- Overall functionality testssrc/tests/render/test_render_performance.py- Performance tests
Measure on demand:
uv run --extra dev python -m pytest src/tests/test_render*.py \
--cov=src/render --cov-report=term-missing- Multi-framework code generation
- Framework-specific optimizations
- Error handling and recovery
- Performance benchmarking
- Integration with execution step
render.generate_pymdp- Generate PyMDP coderender.generate_rxinfer- Generate RxInfer.jl coderender.generate_activeinference- Generate ActiveInference.jl coderender.generate_discopy- Generate DisCoPy coderender.generate_jax- Generate JAX coderender.validate_framework- Validate framework compatibility
@mcp_tool("render.generate_pymdp")
def generate_pymdp_tool(model_data, options=None):
"""Generate PyMDP simulation code"""
# Implementationsrc/render/mcp.py- MCP tool registrations
Symptom: Code generation fails for specific framework
Cause: Missing framework dependencies or invalid GNN model structure
Solution:
- Check framework dependencies are installed
- Verify GNN model has required sections for framework
- Use
--verboseflag for detailed error messages - Check framework-specific requirements in documentation
Symptom: POMDP-aware rendering reports validation errors
Cause: GNN model missing POMDP-required components or invalid structure
Solution:
- Ensure GNN model has complete state space, observations, actions
- Verify connections follow POMDP structure (s->o, s->s, a->s)
- Use
--strict-validation=Falsefor lenient validation - Review POMDP requirements in documentation
Symptom: Rendered code has syntax errors or import failures
Cause: Framework version mismatch or template issues
Solution:
- Verify framework versions match requirements
- Check generated code for syntax errors
- Review framework-specific documentation
- Report template issues if systematic
- Pipeline Overview
- Architecture Guide
- PyMDP Integration
- RxInfer Integration
- ActiveInference.jl Integration
- DisCoPy Integration
Maintainer: GNN Pipeline Team