tensorlogic-compiler
Engine-agnostic compilation of TensorLogic expressions to tensor computation graphs
Overview
The compiler translates logical rules with quantifiers into optimized tensor operations using Einstein summation notation. It operates as a planning layer only - no execution happens here.
Input: TLExpr (logical expressions with predicates, quantifiers, implications)
Output: EinsumGraph (directed graph of tensor operations)
Key Features
Core Compilation (Production Ready)
- Logic-to-Tensor Mapping: Compiles predicates, AND, OR, NOT, EXISTS, FORALL, IMPLY
- Arithmetic Operations: Add, Subtract, Multiply, Divide with element-wise tensor ops
- Comparison Operations: Equal, LessThan, GreaterThan with boolean result tensors
- Conditional Expressions: If-then-else with soft probabilistic semantics
- Shared Variable Support: Handles variable sharing in AND operations via einsum contraction
- Automatic Axis Marginalization: Implicitly quantifies extra variables in implications
Modal & Temporal Logic (Production Ready)
- Modal Operators: Box for necessity, Diamond for possibility
- Temporal Operators: Eventually (F), Always (G) for temporal reasoning
- Configurable Strategies: 3 modal strategies, 3 temporal strategies
- Automatic Axis Management: World and time dimensions managed transparently
- Combined Reasoning: Support for nested modal/temporal expressions
Type Safety & Validation (Production Ready)
- Scope Analysis: Detects unbound variables with helpful quantifier suggestions
- Type Checking: Validates predicate arity and type consistency across expressions
- Domain Validation: Ensures variables are bound to valid domains
- Enhanced Diagnostics: Rich error messages with source locations and fix suggestions
Optimization Pipeline (Production Ready)
The compiler features a 7-pass optimization pipeline that can reduce expression complexity by up to 80%:
- Negation Optimization: Double negation elimination, De Morgan's laws, quantifier negation pushing
- Constant Folding: Compile-time evaluation of constant expressions (2.0 * 3.0 -> 6.0)
- Algebraic Simplification: Identity elimination (x+0=x, x1=x), annihilation (x0=0), idempotency
- Strength Reduction: Replace expensive ops with cheaper equivalents (x^2->x*x, exp(log(x))->x)
- Distributivity: Factor common subexpressions (ab + ac -> a*(b+c))
- Quantifier Optimization: Loop-invariant code motion (exists x.(a+p(x)) -> a + exists x.p(x))
- Dead Code Elimination: Remove unreachable branches and short-circuit constant conditions
Additional Graph-Level Optimizations:
- Common Subexpression Elimination (CSE): Graph-level deduplication of identical operations
- Einsum Optimization: Operation merging, identity elimination, contraction order optimization
Pipeline Features:
- Configurable: Enable/disable individual passes, set iteration limits
- Fixed-Point Detection: Automatically stops when no more optimizations are possible
- Performance Tracking: Detailed statistics on applied optimizations
- Hardware-Adaptive: GPU-optimized, CPU-optimized, and SIMD-optimized cost models
Parameterized Compilation (Production Ready)
- 26+ Configurable Strategies: Customize logic-to-tensor mappings for different use cases
- 6 Preset Configurations: Soft differentiable, hard Boolean, fuzzy logics, probabilistic
- Fine-Grained Control: Per-operation strategy selection (AND, OR, NOT, quantifiers, implication)
Advanced Analysis & Profiling (Production Ready)
- Compilation Profiling: Track compilation time, memory usage, cache statistics, and pass-level performance
- Dataflow Analysis: Live variable analysis, reaching definitions, use-def chains for optimization
- Graph Dataflow: Tensor liveness tracking, dependency analysis for graph optimization
- Contraction Optimization: Dynamic programming for optimal einsum contraction order (reduces FLOPs)
- Loop Fusion: Fuse multiple loops over the same axes for better cache locality
- Reachability Analysis: Compute dominance, strongly connected components, topological ordering
- Integrated Post-Compilation: Unified pipeline combining validation and graph-level optimizations
Advanced Logic (Production Ready)
- Counting Quantifiers: CountingExists, CountingForAll, ExactCount, Majority
- Higher-Order Logic: Lambda expressions, Apply with beta reduction
- Set Theory Operations: Membership, Union, Intersection, Difference, Cardinality, Comprehension
- Fixed-Point Operators: LeastFixpoint, GreatestFixpoint with configurable unrolling depth
- Hybrid Logic: Nominal (@i), At operator (@i phi), Somewhere (E phi), Everywhere (A phi)
- Constraint Programming: AllDifferent, GlobalCardinality
- Abductive Reasoning: Abducible with costs, Explain operator
- Probabilistic Logic: WeightedRule, ProbabilisticChoice, SoftExists, SoftForAll
- Fuzzy Logic: TNorm (6 variants), TCoNorm (6 variants), FuzzyNot (3 variants), FuzzyImplication (6 variants)
Import/Export (Production Ready)
- Import: Prolog syntax, S-Expressions, TPTP format with auto-detection
- Export to ONNX: Full protobuf message generation
- Export to TensorFlow GraphDef: TensorFlow op translation
- Export to PyTorch: Human-readable Python nn.Module code generation
Performance Features (Production Ready)
- Parallel Compilation: Multi-threaded with configurable parallelization strategy
- Incremental Compilation: Expression dependency tracking, change detection
- Compilation Caching: Thread-safe LRU cache with statistics
Quick Start
use compile_to_einsum;
use ;
// Define a logic rule: exists y. knows(x, y)
// "Find all persons x who know someone"
let rule = exists;
// Compile to tensor operations
let graph = compile_to_einsum?;
// Graph contains:
// - Tensors: ["knows[ab]", "temp_0"]
// - Operations: [Reduce{op: "sum", axes: [1]}]
// - Outputs: [1]
Logic-to-Tensor Mapping
Default Strategy (Soft Differentiable)
| Logic Operation | Tensor Equivalent | Notes |
|---|---|---|
P(x, y) |
Tensor with axes ab |
Predicate as multi-dimensional array |
P AND Q |
Hadamard product or einsum | Element-wise if same axes, contraction if shared vars |
P OR Q |
max(P, Q) |
Or soft variant (configurable) |
NOT P |
1 - P |
Or temperature-controlled |
exists x. P(x) |
sum(P, axis=x) |
Or max for hard quantification |
forall x. P(x) |
NOT(exists x. NOT(P(x))) |
Dual of EXISTS |
P -> Q |
ReLU(Q - P) |
Soft implication |
Modal & Temporal Logic Operations
| Logic Operation | Tensor Equivalent | Notes |
|---|---|---|
Box P (necessity) |
min(P, axis=world) or prod(P, axis=world) |
Necessity over possible worlds |
Diamond P (possibility) |
max(P, axis=world) or sum(P, axis=world) |
Possibility over possible worlds |
F(P) (Eventually) |
max(P, axis=time) or sum(P, axis=time) |
True in some future state |
G(P) (Always) |
min(P, axis=time) or prod(P, axis=time) |
True in all future states |
Modal Logic Example:
use ;
// Box(exists y. knows(x, y)) - "In all possible worlds, x knows someone"
let expr = Box;
Temporal Logic Example:
// F(completed(t)) - "Task t will eventually be completed"
let expr = Eventually;
// G(safe(s)) - "System s is always safe"
let expr = Always;
Combined Modal & Temporal:
// Box(F(goal(a))) - "In all possible worlds, agent a eventually achieves goal"
let expr = Box;
See examples/10_modal_temporal_logic.rs for comprehensive demonstrations.
Parameterized Compilation
The compiler defines 6 preset configurations and 26+ configurable strategies:
use ;
// Use preset configurations
let config = soft_differentiable; // Default (neural training)
let config = hard_boolean; // Discrete reasoning
let config = fuzzy_godel; // Godel fuzzy logic
let config = probabilistic; // Probabilistic semantics
// Or build a custom configuration
let config = new
.and_strategy // Product t-norm
.or_strategy // Probabilistic s-norm
.not_strategy // Standard complement
.exists_strategy // Max aggregation
.build;
Available Strategies:
| Operation | Strategies | Use Cases |
|---|---|---|
| AND | Product, Min, ProbabilisticSum, Godel, ProductTNorm, Lukasiewicz | T-norms for conjunctions |
| OR | Max, ProbabilisticSum, Godel, ProbabilisticSNorm, Lukasiewicz | S-norms for disjunctions |
| NOT | Complement (1-x), Sigmoid | Negation with or without temperature |
| EXISTS | Sum, Max, LogSumExp, Mean | Different quantifier semantics |
| FORALL | DualOfExists, Product, Min, MeanThreshold | Universal quantification strategies |
| IMPLY | ReLU, Material, Godel, Lukasiewicz, Reichenbach | Various implication operators |
| MODAL | AllWorldsMin, AllWorldsProduct, Threshold | Necessity/possibility operators |
| TEMPORAL | Max, Sum, LogSumExp | Eventually/always operators |
Advanced: Transitivity Rules
The compiler handles complex rules like transitivity with shared variables:
// knows(x,y) AND knows(y,z) -> knows(x,z)
let knows_xy = pred;
let knows_yz = pred;
let knows_xz = pred;
let premise = and;
let rule = imply;
let graph = compile_to_einsum?;
// Generates:
// 1. knows[ab] AND knows[bc] -> einsum("ab,bc->abc") [contraction over shared 'b']
// 2. Marginalize over 'b' to align with conclusion axes 'ac'
// 3. Apply ReLU(knows[ac] - marginalized_premise[ac])
Optimization Pipeline Usage
Unified Pipeline (Recommended)
use ;
use ;
let pipeline = new;
let expr = negate;
let = pipeline.optimize;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
Configurable Pipeline
use PipelineConfig;
// Aggressive optimization (more iterations)
let config = aggressive;
let pipeline = with_config;
// Custom configuration
let config = default
.with_negation_opt
.with_constant_folding
.with_algebraic_simplification
.with_strength_reduction
.with_distributivity
.with_quantifier_opt
.with_dead_code_elimination
.with_max_iterations;
let pipeline = with_config;
let = pipeline.optimize;
Individual Pass Usage
use ;
let = optimize_negations;
let = fold_constants;
let = simplify_algebraic;
let = reduce_strength;
Complexity Analysis
use ;
let complexity = analyze_complexity;
println!;
println!;
println!;
// Use GPU-optimized cost weights
let gpu_weights = gpu_optimized;
let gpu_cost = complexity.total_cost_with_weights;
println!;
println!;
println!;
Graph-Level Optimizations
use ;
let graph = compile_to_einsum?;
let = optimize_graph;
println!;
Advanced Analysis Features
Compilation Profiling
use CompilationProfiler;
let mut profiler = new;
profiler.start;
profiler.start_phase;
let graph = compile_to_einsum?;
profiler.end_phase;
profiler.record_pass;
let report = profiler.generate_report;
println!;
let json = profiler.generate_json_report;
Profiling capabilities:
- Phase-level time tracking with nesting support
- Memory usage snapshots and peak memory detection
- Pass-level statistics (execution count, time, optimizations)
- Cache statistics (hits, misses, evictions, hit rate)
- Performance recommendations based on profiling data
Dataflow Analysis
use ;
let analysis = analyze_dataflow;
println!;
println!;
println!;
println!;
let graph_analysis = analyze_graph_dataflow;
println!;
println!;
Contraction Optimization
use ;
use ContractionOptConfig;
let = optimize_contractions;
println!;
println!;
println!;
let config = ContractionOptConfig ;
let = optimize_contractions_with_config;
Loop Fusion
use ;
use LoopFusionConfig;
let = fuse_loops;
println!;
println!;
println!;
Reachability Analysis
use ;
let reachability = analyze_reachability;
if reachability.reachable.contains
println!;
if let Some = &reachability.topological_order
let dominance = analyze_dominance;
println!;
println!;
Integrated Post-Compilation Pipeline
use ;
let options = PostCompilationOptions ;
let mut graph = compile_to_einsum?;
let result = post_compilation_passes?;
if result.is_valid
See examples/21_profiling_and_optimization.rs for comprehensive demonstrations of all these features.
Compiler Architecture
TLExpr
|
[Pre-Compilation Passes]
- Scope analysis (detect unbound variables)
- Type checking (validate arity, types)
- Negation optimization
- Common subexpression elimination
|
[Compiler Context]
- Assign axes to variables
- Track domains
- Manage temporary tensors
- Apply compilation config
|
[compile_expr recursion]
- compile_predicate -> tensor with axes
- compile_and -> einsum contraction (configurable)
- compile_or -> element-wise max (configurable)
- compile_not -> 1 - x (configurable)
- compile_exists -> reduction (configurable)
- compile_forall -> dual or product (configurable)
- compile_imply -> marginalize + operator (configurable)
- compile_arithmetic -> element-wise ops
- compile_comparison -> boolean tensors
|
[Post-Compilation Passes]
- Dead code elimination
- Einsum operation merging
- Identity elimination
- Contraction order optimization
|
EinsumGraph
- Tensors: Vec<String>
- Nodes: Vec<EinsumNode>
- Outputs: Vec<usize>
Scope Analysis & Type Checking
Scope Analysis
use analyze_scopes;
let expr = exists;
let analysis = analyze_scopes;
if !analysis.unbound_vars.is_empty
Type Checking
use TypeChecker;
use PredicateSignature;
let mut checker = new;
checker.register_predicate;
let result = checker.check_types;
if let Some = result.type_errors.first
Enhanced Diagnostics
use ;
let diagnostics = diagnose_expression;
for diag in diagnostics
Compiler Context
The CompilerContext manages compilation state:
use CompilerContext;
let mut ctx = new;
// Register domains
ctx.add_domain; // 100 possible persons
ctx.add_domain; // 50 cities
// Bind variables to domains
ctx.bind_var?;
ctx.bind_var?;
// Axes are automatically assigned: x->'a', y->'b', ...
Operation Types
The compiler generates 4 types of operations:
1. Einsum (Tensor Contraction)
// Spec: "ab,bc->ac" (matrix multiplication)
einsum
2. Element-Wise Unary
// Operations: not, relu, sigmoid, etc.
elem_unary
3. Element-Wise Binary
// Operations: add, subtract, multiply, etc.
elem_binary
4. Reduction
// Reduce over axis 1 (sum/max/min)
reduce
Error Handling
The compiler performs extensive validation:
// Arity validation
let p1 = pred;
let p2 = pred; // Different arity!
validate_arity?; // Error: Predicate 'P' has inconsistent arity
// Domain validation
ctx.bind_var?; // Error: Domain 'NonExistent' not found
Integration with Other Crates
tensorlogic-adapters
Use SymbolTable to provide domain and predicate metadata:
use SymbolTable;
let table = new;
// Add domains and predicates...
// Pass to compiler for enhanced type checking
tensorlogic-scirs-backend
Execute the compiled graph:
use Scirs2Exec;
use TlExecutor;
let executor = new;
let outputs = executor.execute?;
Performance Considerations
- Operation Fusion: Einsum operation merging (completed)
- Common Subexpression Elimination: Expression-level and graph-level CSE (completed)
- Negation Optimization: De Morgan's laws and double negation elimination (completed)
- Dead Code Elimination: Removes unused operations from the graph (completed)
- Axis Assignment: Uses lexicographic order ('a', 'b', 'c', ...) for determinism
- Temporary Tensors: Named as
temp_0,temp_1, ... for debugging
Testing & Quality
The compiler has comprehensive test coverage:
# Run all tests with nextest (recommended)
# Run with standard cargo test
# Run with coverage
Current Test Status (v0.1.0-rc.1):
- 437 tests (100% passing)
- Zero warnings (strict clippy compliance)
- Production-ready quality
Current Status & Roadmap
Production Ready (v0.1.0-rc.1)
- Core logic compilation (AND, OR, NOT, quantifiers, implications)
- Arithmetic and comparison operations
- Conditional expressions (if-then-else)
- Type checking and scope analysis
- Enhanced diagnostics with helpful error messages
- Parameterized compilation (26+ strategies, 6 presets)
- Optimization passes (negation, CSE, einsum, DCE)
- SymbolTable integration for metadata
- Modal & temporal logic (Box, Diamond, Eventually, Always)
- Advanced logic: counting quantifiers, higher-order logic, set theory, fixed-points
- Hybrid logic, constraint programming, abductive reasoning
- Probabilistic logic, fuzzy logic operators
- Import: Prolog, S-Expression, TPTP formats
- Export: ONNX, TensorFlow GraphDef, PyTorch code generation
- Parallel compilation (feature-gated)
- Incremental compilation and caching
- Compilation profiling
- Dataflow analysis
- Contraction optimization
- Loop fusion
- Reachability analysis
- Property-based testing (21 property tests)
- Fuzzing infrastructure (4 fuzz targets)
- Benchmark suite
Known Limitations
Next(X) temporal operator requires backend shift operationsUntil(U) temporal operator requires backend scan operations- JIT compilation for hot paths: not yet implemented
- First-class functions/predicates: not yet implemented
- Higher-order quantification: not yet implemented
Examples
See the test suite and examples directory for demonstrations:
Key examples:
examples/10_modal_temporal_logic.rs: Box, Diamond, Eventually, Always operatorsexamples/11_fuzzy_logic.rs: All 19 fuzzy operators with real-world applicationsexamples/14_parallel_compilation.rs: Multi-threaded compilationexamples/15_onnx_export.rs: ONNX format exportexamples/16_tensorflow_export.rs: TensorFlow GraphDef exportexamples/17_pytorch_export.rs: PyTorch code generationexamples/18_logic_import.rs: Import from Prolog, S-Expression, TPTPexamples/19_set_operations.rs: Set theory operationsexamples/20_constraint_programming.rs: AllDifferent, GlobalCardinalityexamples/21_profiling_and_optimization.rs: Profiling and advanced analysisexamples/22_hybrid_logic.rs: Hybrid logic operatorsexamples/23_abductive_reasoning.rs: Abductive reasoning
Key test cases:
test_transitivity_rule_shared_variables: Transitivity with contractiontest_and_with_different_axes: Partial variable overlaptest_and_with_disjoint_variables: Outer product (no shared vars)test_implication: Soft implication with ReLUtest_exists_quantifier: Reduction over quantified variables
Contributing
When adding new features:
- Update
compile_exprto handle new TLExpr variants - Add tests in the
testsmodule - Update this README and TODO.md
- Ensure all tests pass:
cargo nextest run -p tensorlogic-compiler
License
Apache-2.0
Status: Production Ready (v0.1.0-rc.1) Last Updated: 2026-03-06 Tests: 437/437 passing (100%) Part of: TensorLogic Ecosystem