Symbios
A Sovereign Derivation Engine for Parametric L-Systems.
Symbios is a pure-Rust, high-performance engine for generating Lindenmayer Systems. It is designed for "Sovereign" applications where the logic must run locally, deterministically, and safely (e.g., WASM environments, embedded simulation).
It fully implements the syntax and semantics described in The Algorithmic Beauty of Plants (Prusinkiewicz & Lindenmayer, 1990).
Key Features
- Structure-of-Arrays (SoA): Data layout optimized for cache locality and WASM memory limits.
- Parametric & Context-Sensitive: Full support for
(k,l)-systems, arithmetic guardsA(x) : x > 5 -> ..., and variable binding. - Adversarial Hardening: Protected against recursion bombs, memory exhaustion, and floating-point fragility.
- Deterministic: Seedable RNG (
rand_pcg) ensures reproducible procedural generation.
Usage
[]
= "1.2"
use System;
Genetic Algorithm Support
Symbios includes built-in support for evolutionary optimization of L-Systems through mutation and crossover operations.
Mutation
use ;
let mut sys = new;
sys.add_rule.unwrap;
sys.add_rule.unwrap;
sys.add_directive.unwrap;
// Mutate rule probabilities and constants
let config = MutationConfig ;
sys.mutate;
// Structural mutation: insert/delete/swap modules, perturb bytecode
let structural_config = StructuralMutationConfig ;
sys.structural_mutate;
Crossover
use ;
let mut parent_a = new;
parent_a.add_rule.unwrap;
parent_a.add_directive.unwrap;
let mut parent_b = new;
parent_b.add_rule.unwrap;
parent_b.add_directive.unwrap;
let config = CrossoverConfig ;
let offspring = parent_a.crossover?;
// offspring.constants["ANGLE"] == 45.0 (blended)
Reproducibility
All mutation and crossover operations have _with_rng variants that accept an external RNG for deterministic results:
use SeedableRng;
use Pcg64;
let mut rng = seed_from_u64;
sys.mutate_with_rng;
sys.structural_mutate_with_rng;
let offspring = parent_a.crossover_with_rng;
Rule Export
Symbios can decompile compiled rules back to source text. This is useful for inspecting mutated rules, serialization, and debugging.
Export All Rules
use System;
let mut sys = new;
sys.add_rule.unwrap;
sys.add_rule.unwrap;
// Export all rules as (predecessor, source) pairs
for in sys.export_rules
// Output:
// A: A(p0) : p0 > 10 -> B(p0 + 1)
// A: A(p0) : p0 <= 10 -> A(p0 + 1)
Export Rules for a Specific Symbol
// Get all rules for symbol "A"
let rules = sys.export_rules_for;
for rule in rules
Export a Specific Rule
// Get rule at index 0 for symbol "A"
let rule = sys.export_rule_at.unwrap;
println!;
Custom Parameter Names
By default, exported rules use synthetic parameter names (p0, p1, ...). You can provide custom names:
// Export with meaningful parameter names
let rule = sys.export_rule_with_params.unwrap;
println!;
// Output: A(age) : age > 10 -> B(age + 1)
Performance
Symbios uses a flat memory arena for parameters and u16 symbol interning.
- Rule Matching: $O(N)$ (HashMap bucketed)
- Context Matching: $O(1)$ (Topology Skip-Links)
See PERFORMANCE.md for detailed benchmarks and optimization tips.
Documentation
- ARCHITECTURE.md - System design, SoA layout, VM architecture, and design decisions
- PERFORMANCE.md - Benchmark results, optimization tips, and profiling guide
- TROUBLESHOOTING.md - Common errors, solutions, and debugging patterns
Examples
See examples/ for complete working examples:
- anabaena.rs - Simple discrete L-System from ABOP
- monopodial_tree.rs - Complex tree with branches and constants
- stochastic_decay.rs - Stochastic rule demonstration
- adaptive_plant.rs - Advanced example with age, context, and environment
License
MIT