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.1.3
Last Updated: 2026-03-17
- 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 backend
- Output: Stan models under
stan/when the renderer is available
process_render(target_dir: Path, output_dir: Path, verbose: bool = False, frameworks=None, strict_validation: bool = True, **kwargs) -> bool
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]]): Restrict to a subset of frameworks (default: all available)strict_validation(bool): Passed to POMDP extraction (Trueby default)**kwargs: Additional options forwarded to framework renderers (e.g.timesteps,simulation_params)
Returns: bool - True if processing succeeded, False otherwise
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
)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
src/render/generators.py also exports convenience generators used by parts of the module:
generate_pymdp_code(model_data: Dict, output_path: Optional[Union[str, Path]] = None) -> strgenerate_rxinfer_code(model_data: Dict, output_path: Optional[Union[str, Path]] = None) -> strgenerate_activeinference_jl_code(model_data: Dict, output_path: Optional[Union[str, Path]] = None) -> strgenerate_discopy_code(model_data: Dict, output_path: Optional[Union[str, Path]] = None) -> str
These functions take a loosely-structured model_data dictionary and return code as a string (and optionally write it to output_path). The authoritative, pipeline-facing interface remains process_render(...).
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 implemented in code.
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 generate_pymdp_code, generate_rxinfer_code
# Generate code for multiple frameworks
pymdp_code = generate_pymdp_code(model_data)
rxinfer_code = generate_rxinfer_code(model_data)# Framework-specific options
options = {
'pymdp': {
'inference_algorithm': 'VMP',
'num_iterations': 200
},
'rxinfer': {
'constraints': 'custom',
'optimization': 'performance'
}
}- 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 backends (when available):
pytorch/,numpyro/,stan/
render_processing_summary.json- Processing summary
output/11_render_output/
├── render_processing_summary.json
└── [model_stem]/
├── pymdp/
├── rxinfer/
├── activeinference_jl/
├── jax/
├── discopy/
├── pytorch/ # if available
├── numpyro/ # if available
└── stan/ # if 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 Recovery: Try alternative frameworks
- Template Simplification: Use simpler templates
- Partial Generation: Generate what is possible
- Error Documentation: Provide detailed error reports
- 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/test_render_integration.py- Integration testssrc/tests/test_render_overall.py- Overall functionality testssrc/tests/test_render_performance.py- Performance tests
- Current: 78%
- Target: 85%+
- 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