Skip to main content

pytensorlogic

Python bindings for TensorLogic - Logic-as-Tensor planning layer

PyPI Python Documentation Alpha

Overview

Status: Alpha (Python bindings — build and test via maturin/pytest, not cargo nextest) Version: 0.1.2 PyPI Classifier: Development Status :: 3 - Alpha Last Updated: 2026-08-30

Note on testing: This crate uses PyO3/maturin. Tests are run with pytest after maturin develop, not with cargo nextest. See Testing section below.

TensorLogic compiles logical rules (predicates, quantifiers, implications) into tensor equations (einsum graphs) that can be executed on various backends. This Python package provides a comprehensive Pythonic API for researchers and practitioners to use TensorLogic from Jupyter notebooks and Python workflows.

Key Features

Core Capabilities

  • Logical Expression DSL: Build complex logical rules using predicates, quantifiers, and connectives
  • Arithmetic & Comparisons: Full support for arithmetic operations and conditional logic
  • Multiple Compilation Strategies: 6 preset configurations (soft/hard logic, fuzzy variants, probabilistic)
  • NumPy Integration: Seamless bidirectional conversion between NumPy arrays and internal tensors
  • Type Safety: Complete type stubs (.pyi) for IDE support and static type checking
  • Comprehensive Error Handling: Clear, actionable error messages

Advanced Features

  • Async Execution: Non-blocking execution, parallel graphs, batch processing, cancellation support
  • Backend Selection: Choose between CPU, SIMD, or GPU backends
  • Domain Management: SymbolTable, CompilerContext for advanced schema management
  • Provenance Tracking: Full RDF*/SHACL integration with confidence-based inference
  • SciRS2 Backend: High-performance execution with SIMD acceleration (2-4x speedup)
  • Training API: Loss functions (MSE, BCE, cross-entropy), optimizers (SGD, Adam, RMSprop), callbacks
  • Model Persistence: Save/load models in JSON and binary formats with pickle support
  • Rule Builder DSL: Python-native syntax with operator overloading (&, |, ~, >>)
  • Jupyter Integration: Rich HTML display (_repr_html_()) for all major types
  • Performance Monitoring: GIL release, profiler, memory tracking
  • Streaming Execution: Process large datasets in chunks
  • Utility Functions: Context managers, custom exceptions, batch operations

Installation

From PyPI (Recommended)

# Install from PyPI (when published)
pip install pytensorlogic

From Source (Development)

# Install maturin for building Python extensions
pip install maturin

# Build and install in development mode
cd crates/tensorlogic-py
maturin develop

# Or build optimized wheel for distribution
maturin build --release

Requirements

  • Python 3.9+
  • NumPy 1.20+
  • Rust toolchain 1.90+ (for building from source only)

Quick Start

Basic Example: Logical Rules

import pytensorlogic as tl
import numpy as np

# Create logical expressions
x = tl.var("x")
y = tl.var("y")

# Define a predicate: knows(x, y)
knows = tl.pred("knows", [x, y])

# Compile to tensor graph
graph = tl.compile(knows)

# Create input data (100 people, adjacency matrix)
knows_matrix = np.random.rand(100, 100)

# Execute the graph
result = tl.execute(graph, {"knows": knows_matrix})
print(result["output"])

Quantifiers: Existential and Universal

import pytensorlogic as tl
import numpy as np

# exists y. knows(x, y) - "x knows someone"
x = tl.var("x")
y = tl.var("y")
knows = tl.pred("knows", [x, y])
knows_someone = tl.exists("y", "Person", knows)

# Compile and execute
graph = tl.compile(knows_someone)
knows_matrix = np.random.rand(100, 100)
result = tl.execute(graph, {"knows": knows_matrix})

# Result shape: (100,) - one value per person
print(f"Shape: {result['output'].shape}")

Implication Rules

import pytensorlogic as tl

# Rule: knows(x,y) AND knows(y,z) -> knows(x,z) (transitivity)
x, y, z = tl.var("x"), tl.var("y"), tl.var("z")

knows_xy = tl.pred("knows", [x, y])
knows_yz = tl.pred("knows", [y, z])
knows_xz = tl.pred("knows", [x, z])

premise = tl.and_(knows_xy, knows_yz)
rule = tl.imply(premise, knows_xz)

# Wrap in universal quantifier
transitivity = tl.forall("y", "Person", rule)

# Compile
graph = tl.compile(transitivity)

Arithmetic and Comparisons

import pytensorlogic as tl

# Arithmetic: age(x) + 5
age_x = tl.pred("age", [tl.var("x")])
age_plus_5 = tl.add(age_x, tl.constant(5.0))

# Comparison: age(x) > 18
adult = tl.gt(age_x, tl.constant(18.0))

# Conditional: if age(x) > 18 then mature else young
classification = tl.if_then_else(
    adult,
    tl.constant(1.0),  # mature
    tl.constant(0.0)   # young
)

Async Execution

TensorLogic provides asynchronous execution capabilities for non-blocking workflows, perfect for Jupyter notebooks and web applications.

Basic Async Execution

import pytensorlogic as tl
import numpy as np

# Compile a graph
expr = tl.not_(tl.pred("data", [tl.var("x")]))
graph = tl.compile(expr)
inputs = {"data": np.random.rand(1000)}

# Execute asynchronously
future = tl.execute_async(graph, inputs)

# Do other work while computation runs in background
print("Computing in background...")

# Check if ready
if future.is_ready():
    print("Done!")

# Get result (waits if not ready)
result = future.result()

Parallel Graph Execution

Execute multiple graphs concurrently for maximum throughput:

# Create multiple graphs
graphs = [tl.compile(expr1), tl.compile(expr2), tl.compile(expr3)]
inputs_list = [inputs1, inputs2, inputs3]

# Execute all in parallel
futures = tl.execute_parallel(graphs, inputs_list)

# Collect results
results = [f.result() for f in futures]

Batch Processing

Process multiple inputs through the same graph efficiently:

# Create batch executor
executor = tl.BatchExecutor(graph)

# Process multiple inputs
inputs_list = [
    {"data": np.random.rand(100)},
    {"data": np.random.rand(100)},
    {"data": np.random.rand(100)},
]

# Execute in parallel (2-4x speedup)
results = executor.execute_batch(inputs_list, parallel=True)

# Or sequential
results = executor.execute_batch(inputs_list, parallel=False)

Async Cancellation

# Create a cancellation token
token = tl.cancellation_token()

# Start async computation
future = tl.execute_async(graph, inputs)

# Cancel if needed
token.cancel()

Progress Monitoring

Monitor long-running async computations:

import time

future = tl.execute_async(graph, large_inputs)

# Monitor with timeout
while not future.is_ready():
    print(".", end="", flush=True)
    time.sleep(0.1)

# Or use wait with timeout
if future.wait(timeout_secs=5.0):
    result = future.result()
else:
    print("Timeout!")

Performance Characteristics

  • Async Overhead: ~20% for small tensors, negligible for large (>1000 elements)
  • Parallel Speedup: 2-4x for independent graphs on multi-core systems
  • Batch Processing: Near-linear scaling with number of batches
  • Thread Safety: All operations are thread-safe

See examples/async_execution_demo.py for comprehensive examples.

Compilation Strategies

TensorLogic supports multiple logic semantics through compilation configurations:

import pytensorlogic as tl

# Soft differentiable (default) - for neural network training
config = tl.CompilationConfig.soft_differentiable()

# Hard Boolean - discrete logic
config = tl.CompilationConfig.hard_boolean()

# Fuzzy logic variants
config = tl.CompilationConfig.fuzzy_godel()
config = tl.CompilationConfig.fuzzy_product()
config = tl.CompilationConfig.fuzzy_lukasiewicz()

# Probabilistic interpretation
config = tl.CompilationConfig.probabilistic()

# Use custom config
graph = tl.compile_with_config(expr, config)

Compilation Strategy Comparison

Strategy AND OR NOT Use Case
soft_differentiable Product Probabilistic sum Complement Neural training (default)
hard_boolean Min Max Complement Discrete reasoning
fuzzy_godel Min Max Complement Godel fuzzy logic
fuzzy_product Product Probabilistic sum Complement Product fuzzy logic
fuzzy_lukasiewicz Lukasiewicz Lukasiewicz Complement Lukasiewicz logic
probabilistic Product (indep.) Probabilistic sum Complement Probability theory

Advanced Features

Backend Selection

Choose the best backend for your hardware:

import pytensorlogic as tl

# Get backend capabilities
caps = tl.get_backend_capabilities(tl.Backend.SCIRS2_CPU)
print(f"Backend: {caps.name} v{caps.version}")
print(f"Devices: {caps.devices}")
print(f"Features: {caps.features}")

# List available backends
backends = tl.list_available_backends()
print(backends)  # {'Auto': True, 'SciRS2CPU': True, 'SciRS2SIMD': True, 'SciRS2GPU': False}

# Execute with specific backend (SIMD for 2-4x speedup)
result = tl.execute(graph, inputs, backend=tl.Backend.SCIRS2_SIMD)

# Get system information
info = tl.get_system_info()
print(f"TensorLogic v{info['tensorlogic_version']}")
print(f"Default backend: {info['default_backend']}")

Domain Management and Symbol Tables

Build rich semantic models with domain metadata:

import pytensorlogic as tl

# Create symbol table
symbol_table = tl.symbol_table()

# Define domains
person_domain = tl.domain_info("Person", cardinality=100)
person_domain.set_description("Domain of all people in the network")
person_domain.set_elements(["alice", "bob", "charlie"])

symbol_table.add_domain(person_domain)

# Define predicates with signatures
knows_pred = tl.predicate_info("knows", ["Person", "Person"])
knows_pred.set_description("Binary relation: x knows y")
symbol_table.add_predicate(knows_pred)

# Bind variables to domains
symbol_table.bind_variable("x", "Person")

# Automatic inference from expressions
expr = tl.pred("knows", [tl.var("x"), tl.var("y")])
symbol_table.infer_from_expr(expr)

# Export/import as JSON
json_data = symbol_table.to_json()
restored_table = tl.SymbolTable.from_json(json_data)

Provenance Tracking

Track the origin and lineage of tensor computations with full RDF* support:

import pytensorlogic as tl

# Create provenance tracker with RDF* support
tracker = tl.provenance_tracker(enable_rdfstar=True)

# Track RDF entities to tensor indices
tracker.track_entity("http://example.org/alice", 0)
tracker.track_entity("http://example.org/bob", 1)

# Track SHACL shapes to logical rules
tracker.track_shape(
    "http://example.org/PersonShape",
    "Person(x) AND knows(x, y)",
    0
)

# Track inferred triples with confidence scores
tracker.track_inferred_triple(
    subject="http://example.org/alice",
    predicate="http://example.org/knows",
    object="http://example.org/bob",
    rule_id="social_network_rule_1",
    confidence=0.95
)

# Get high-confidence inferences (>= 0.85)
high_conf = tracker.get_high_confidence_inferences(min_confidence=0.85)
for inf in high_conf:
    print(f"{inf['subject']} {inf['predicate']} {inf['object']}")
    print(f"  Confidence: {inf['confidence']}, Rule: {inf['rule_id']}")

# Export to RDF* Turtle format
turtle = tracker.to_rdfstar_turtle()

# Export to JSON for persistence
json_data = tracker.to_json()
restored = tl.ProvenanceTracker.from_json(json_data)

# Extract provenance from compiled graphs
graph = tl.compile(expr)
provenance_list = tl.get_provenance(graph)
metadata_list = tl.get_metadata(graph)

Training API

Train neural-symbolic models with familiar ML patterns:

import pytensorlogic as tl
import numpy as np

# Define loss functions
loss_fn = tl.mse_loss()       # Mean Squared Error
loss_fn = tl.bce_loss()       # Binary Cross-Entropy
loss_fn = tl.cross_entropy_loss()  # Multi-class Cross-Entropy

# Define optimizers
opt = tl.sgd(learning_rate=0.01, momentum=0.9)
opt = tl.adam(learning_rate=0.001, beta1=0.9, beta2=0.999)
opt = tl.rmsprop(learning_rate=0.01, alpha=0.99)

# Callbacks
early_stop = tl.early_stopping(patience=10, min_delta=1e-4)
checkpoint = tl.model_checkpoint("model.json")
log = tl.logger(verbosity=1)

# High-level Trainer
trainer = tl.Trainer(graph, loss_fn, opt, callbacks=[early_stop, log])
history = trainer.fit(train_data, epochs=100, validation_data=val_data)
predictions = trainer.predict(test_data)

Model Persistence

import pytensorlogic as tl

# Save a compiled graph
tl.save_model(graph, "model.json")
graph = tl.load_model("model.json")

# Save with full metadata
pkg = tl.model_package(graph, config=config, metadata={"author": "alice"})
tl.save_full_model(pkg, "full_model.json")
pkg = tl.load_full_model("full_model.json")

# Pickle support
import pickle
data = pickle.dumps(pkg)
pkg2 = pickle.loads(data)

Rule Builder DSL

Python-native rule building with operator overloading:

import pytensorlogic as tl

# Domain-bound variables
x = tl.var_dsl("x", domain="Person")
y = tl.var_dsl("y", domain="Person")

# Callable predicate builders
knows = tl.pred_dsl("knows", arity=2)
adult = tl.pred_dsl("adult", arity=1)

# Operator overloading: &, |, ~, >>
rule = (knows(x, y) & adult(x)) >> adult(y)

# Context manager for rule building
with tl.rule_builder() as rb:
    rb.add(knows(x, y) >> knows(y, x))
    graph = rb.compile()

Source Location Tracking

import pytensorlogic as tl

# Create source locations
start = tl.SourceLocation("rules.tl", 10, 1)
end = tl.SourceLocation("rules.tl", 15, 40)
span = tl.SourceSpan(start, end)

# Create provenance with source information
prov = tl.Provenance()
prov.set_rule_id("social_network_rule_1")
prov.set_source_file("social_rules.tl")
prov.set_span(span)
prov.add_attribute("author", "alice")
prov.add_attribute("version", "1.0")

# Query attributes
author = prov.get_attribute("author")
all_attrs = prov.get_attributes()

Complete API Reference

Core Types

Term

Represents variables and constants in logical expressions.

x = tl.var("x")           # Variable
alice = tl.const("alice") # Constant

Methods:

  • name() -> str - Get term name
  • is_var() -> bool - Check if variable
  • is_const() -> bool - Check if constant

TLExpr

Logical expression with comprehensive operations:

Logical Operations:

  • and_(left, right) - Logical AND
  • or_(left, right) - Logical OR
  • not_(expr) - Logical NOT

Quantifiers:

  • exists(var, domain, body) - Existential quantifier
  • forall(var, domain, body) - Universal quantifier

Implications:

  • imply(premise, conclusion) - Logical implication

Arithmetic:

  • add(left, right) - Addition (+)
  • sub(left, right) - Subtraction (-)
  • mul(left, right) - Multiplication (x)
  • div(left, right) - Division (/)

Comparisons:

  • eq(left, right) - Equal (=)
  • lt(left, right) - Less than (<)
  • gt(left, right) - Greater than (>)
  • lte(left, right) - Less than or equal
  • gte(left, right) - Greater than or equal

Conditionals:

  • if_then_else(condition, then_expr, else_expr) - Ternary conditional

Operator overloading (DSL mode):

  • __and__, __or__, __invert__, __rshift__

Methods:

  • free_vars() -> List[str] - Get list of free variables

EinsumGraph

Compiled tensor computation graph.

graph = tl.compile(expr)
stats = graph.stats()  # {'num_nodes': 5, 'num_outputs': 1, 'num_tensors': 3}

Properties:

  • num_nodes: int - Number of computation nodes
  • num_outputs: int - Number of output tensors

Methods:

  • stats() -> Dict[str, int] - Get detailed statistics
  • _repr_html_() - Rich Jupyter display

Adapter Types

DomainInfo

Domain representation with metadata.

domain = tl.domain_info("Person", cardinality=100)
domain.set_description("All people in the network")
domain.set_elements(["alice", "bob", "charlie"])

Properties:

  • name: str - Domain name
  • cardinality: int - Domain size
  • description: Optional[str] - Human-readable description
  • elements: Optional[List[str]] - Domain elements (for finite domains)

PredicateInfo

Predicate signature representation.

pred = tl.predicate_info("knows", ["Person", "Person"])
pred.set_description("Binary relation: x knows y")

Properties:

  • name: str - Predicate name
  • arity: int - Number of arguments
  • arg_domains: List[str] - Domain for each argument
  • description: Optional[str] - Human-readable description

SymbolTable

Complete symbol table for schema management.

table = tl.symbol_table()
table.add_domain(domain_info)
table.add_predicate(predicate_info)
table.bind_variable("x", "Person")
table.infer_from_expr(expr)  # Automatic schema inference

# Serialization
json_str = table.to_json()
restored = tl.SymbolTable.from_json(json_str)

Methods:

  • add_domain(domain: DomainInfo) - Add domain
  • add_predicate(predicate: PredicateInfo) - Add predicate
  • bind_variable(var: str, domain: str) - Bind variable to domain
  • get_domain(name: str) -> Optional[DomainInfo] - Retrieve domain
  • get_predicate(name: str) -> Optional[PredicateInfo] - Retrieve predicate
  • get_variable_domain(var: str) -> Optional[str] - Get variable's domain
  • list_domains() -> List[str] - List all domains
  • list_predicates() -> List[str] - List all predicates
  • infer_from_expr(expr: TLExpr) - Automatic inference
  • get_variable_bindings() -> Dict[str, str] - Get all bindings
  • to_json() -> str - Export as JSON
  • from_json(json: str) -> SymbolTable - Import from JSON

CompilerContext

Low-level compilation control.

ctx = tl.compiler_context()
ctx.add_domain("Person", 100)
ctx.bind_var("x", "Person")
ctx.assign_axis("x", 0)
temp_name = ctx.fresh_temp()  # Generate unique tensor names

Methods:

  • add_domain(name: str, cardinality: int) - Add domain
  • bind_var(var: str, domain: str) - Bind variable
  • assign_axis(var: str, axis: int) - Assign einsum axis
  • fresh_temp() -> str - Generate unique temporary name
  • get_domains() -> Dict[str, int] - Get all domains
  • get_variable_bindings() -> Dict[str, str] - Get bindings
  • get_axis_assignments() -> Dict[str, int] - Get axis assignments
  • get_variable_domain(var: str) -> Optional[str] - Get variable's domain
  • get_variable_axis(var: str) -> Optional[int] - Get variable's axis

Backend Types

Backend

Backend selection enumeration.

# Available backends
tl.Backend.AUTO          # Auto-select best backend
tl.Backend.SCIRS2_CPU    # CPU backend
tl.Backend.SCIRS2_SIMD   # SIMD-accelerated (2-4x faster)
tl.Backend.SCIRS2_GPU    # GPU backend (future)

BackendCapabilities

Backend capability information.

caps = tl.get_backend_capabilities(tl.Backend.SCIRS2_CPU)
print(caps.name)              # "SciRS2 Backend"
print(caps.version)           # "0.1.1"
print(caps.devices)           # ["CPU"]
print(caps.dtypes)            # ["f64", "f32", "i64", "i32", "bool"]
print(caps.features)          # ["Autodiff", "BatchExecution", ...]
print(caps.max_dims)          # 16

# Query support
caps.supports_device("CPU")     # True
caps.supports_dtype("f64")      # True
caps.supports_feature("Autodiff")  # True
caps.summary()                  # Human-readable summary
caps.to_dict()                  # Dict representation

Provenance Types

SourceLocation

Source code location information.

loc = tl.SourceLocation("rules.tl", 10, 5)
print(loc.file)    # "rules.tl"
print(loc.line)    # 10
print(loc.column)  # 5
print(str(loc))    # "rules.tl:10:5"

SourceSpan

Source code span (start to end).

start = tl.SourceLocation("rules.tl", 10, 1)
end = tl.SourceLocation("rules.tl", 15, 40)
span = tl.SourceSpan(start, end)
print(span.start.line)  # 10
print(span.end.line)    # 15

Provenance

Provenance metadata for IR nodes.

prov = tl.Provenance()
prov.set_rule_id("rule_1")
prov.set_source_file("social_rules.tl")
prov.set_span(span)
prov.add_attribute("author", "alice")
prov.add_attribute("version", "1.0")

# Query
prov.rule_id                    # "rule_1"
prov.source_file                # "social_rules.tl"
prov.get_attribute("author")    # "alice"
prov.get_attributes()           # {"author": "alice", "version": "1.0"}

ProvenanceTracker

Full RDF*/SHACL provenance tracking.

tracker = tl.provenance_tracker(enable_rdfstar=True)

# Entity tracking
tracker.track_entity("http://example.org/alice", 0)
tracker.get_entity(0)  # "http://example.org/alice"
tracker.get_tensor("http://example.org/alice")  # 0

# Shape tracking
tracker.track_shape("http://example.org/PersonShape", "Person(x)", 0)

# RDF* triple tracking with confidence
tracker.track_inferred_triple(
    subject="http://example.org/alice",
    predicate="http://example.org/knows",
    object="http://example.org/bob",
    rule_id="rule_1",
    confidence=0.95
)

# Query high-confidence inferences
high_conf = tracker.get_high_confidence_inferences(min_confidence=0.85)

# Export
tracker.to_rdf_star()          # List of RDF* statements
tracker.to_rdfstar_turtle()    # Turtle format
json_str = tracker.to_json()   # JSON serialization
restored = tl.ProvenanceTracker.from_json(json_str)

# Get mappings
tracker.get_entity_mappings()  # Dict[str, int]
tracker.get_shape_mappings()   # Dict[str, str]

Async Execution Types

AsyncResult

Future result of an async computation.

future = tl.execute_async(graph, inputs)
future.is_ready()                  # bool
future.result()                    # Dict[str, np.ndarray] (blocks if not ready)
future.wait(timeout_secs=5.0)      # bool - True if completed within timeout
future.cancel()                    # Request cancellation
future.is_cancelled()              # bool
future.get_cancellation_token()    # CancellationToken

BatchExecutor

Batch graph execution over multiple inputs.

executor = tl.BatchExecutor(graph)
results = executor.execute_batch(inputs_list, parallel=True)

CancellationToken

Cooperative cancellation for async operations.

token = tl.cancellation_token()
token.cancel()
token.is_cancelled()  # bool
token.reset()

Core Functions

Compilation

compile(expr: TLExpr) -> EinsumGraph

Compile a logical expression to a tensor computation graph.

compile_with_config(expr: TLExpr, config: CompilationConfig) -> EinsumGraph

Compile with a custom configuration.

compile_with_context(expr: TLExpr, ctx: CompilerContext) -> EinsumGraph

Compile with a low-level compiler context.

Execution

execute(
    graph: EinsumGraph,
    inputs: Dict[str, np.ndarray],
    backend: Optional[Backend] = None
) -> Dict[str, np.ndarray]

Execute a graph with NumPy array inputs. Backend defaults to AUTO (best available).

Backend Functions

get_backend_capabilities(backend: Optional[Backend] = None) -> BackendCapabilities
list_available_backends() -> Dict[str, bool]
get_default_backend() -> Backend
get_system_info() -> Dict[str, Any]

Provenance Functions

get_provenance(graph: EinsumGraph) -> List[Optional[Provenance]]
get_metadata(graph: EinsumGraph) -> List[Optional[Dict[str, Any]]]
provenance_tracker(enable_rdfstar: bool = False) -> ProvenanceTracker

Persistence Functions

save_model(graph: EinsumGraph, path: str) -> None
load_model(path: str) -> EinsumGraph
save_full_model(pkg: ModelPackage, path: str) -> None
load_full_model(path: str) -> ModelPackage
model_package(...) -> ModelPackage

Helper Functions

# Adapter creation
domain_info(name: str, cardinality: int) -> DomainInfo
predicate_info(name: str, domains: List[str]) -> PredicateInfo
symbol_table() -> SymbolTable
compiler_context() -> CompilerContext

# DSL
var_dsl(name: str, domain: Optional[str] = None) -> Var
pred_dsl(name: str, arity: int) -> PredicateBuilder
rule_builder() -> RuleBuilder

# Utility
quick_execute(expr: TLExpr, inputs: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]
validate_inputs(graph: EinsumGraph, inputs: Dict[str, np.ndarray]) -> None
batch_compile(exprs: List[TLExpr]) -> List[EinsumGraph]
batch_predict(graph: EinsumGraph, inputs_list: List[Dict]) -> List[Dict]
execution_context() -> ExecutionContext
compilation_context() -> CompilationContext

Examples

The examples/ directory contains comprehensive demonstrations:

  1. basic_usage.py - Complete usage guide with all operations
  2. arithmetic_operations.py - All arithmetic operations
  3. comparison_conditionals.py - Comparisons and conditionals
  4. advanced_symbol_table.py - Domain management and symbol tables
  5. backend_selection.py - Backend selection and capabilities
  6. provenance_tracking.py - Complete provenance tracking workflow
  7. training_workflow.py - Training API (450+ lines, 10 scenarios)
  8. model_persistence.py - Model persistence (600+ lines, 10 scenarios)
  9. rule_builder_dsl.py - Rule Builder DSL (550+ lines, 10 examples)
  10. async_execution_demo.py - Async execution (300+ lines)
  11. performance_benchmark.py - Performance benchmarks
  12. memory_profiling.py - Memory profiling and streaming

Run any example:

python examples/basic_usage.py
python examples/provenance_tracking.py

Testing

Important: This crate uses PyO3/maturin. Tests are run via pytest after maturin develop. cargo nextest will not run the Python integration tests.

The package includes 300+ comprehensive tests across 7 test suites:

# Build the Python extension first
cd crates/tensorlogic-py
maturin develop

# Install development dependencies
pip install -r requirements-dev.txt

# Run all tests
pytest tests/ -v

# Run specific test suite
pytest tests/test_provenance.py -v

# Run with coverage
pytest tests/ --cov=pytensorlogic --cov-report=html

Test suites:

  • test_types.py - Core type creation and operations
  • test_execution.py - End-to-end execution tests
  • test_backend.py - Backend selection and capabilities
  • test_provenance.py - Provenance tracking (40+ tests)
  • test_training.py - Training API (40+ tests)
  • test_persistence.py - Model persistence (20+ tests)
  • test_dsl.py - Rule Builder DSL (100+ tests)

Architecture

TensorLogic Python bindings are built with:

  • PyO3 0.23+: Rust-Python interop with abi3 compatibility (Python 3.9+)
  • NumPy: Array interface via numpy crate
  • SciRS2: High-performance scientific computing backend
  • Maturin: Build system for Python extensions
  • Zero-copy where possible for efficiency

Module Structure

tensorlogic-py/
├── src/
│   ├── lib.rs                # Main PyO3 module registration
│   ├── compiler.rs           # Compilation API and strategy presets
│   ├── executor.rs           # Execution engine bindings
│   ├── numpy_conversion.rs   # NumPy bidirectional interop
│   ├── adapters.rs           # Domain and symbol table management
│   ├── backend.rs            # Backend selection and capabilities
│   ├── provenance.rs         # Provenance tracking with RDF* support
│   ├── training.rs           # Training API (loss, optimizers, callbacks)
│   ├── persistence.rs        # Model save/load (JSON/binary/pickle)
│   ├── dsl.rs                # Rule Builder DSL with operator overloading
│   ├── jupyter.rs            # Rich HTML display for Jupyter
│   ├── performance.rs        # GIL release, profiler, memory tracking
│   ├── streaming.rs          # StreamingExecutor and ResultAccumulator
│   ├── async_executor.rs     # Async execution, BatchExecutor, CancellationToken
│   ├── progress.rs           # Training progress callbacks (v0.1.3)
│   ├── types.rs              # Core type bindings (PyTerm, PyTLExpr, PyEinsumGraph)
│   └── utils.rs              # Utility functions and context managers
├── tests/                    # Python test suites (7 files, 300+ tests)
├── examples/                 # Demonstration scripts (12 files)
└── pytensorlogic.pyi         # Type stubs for IDE support (1100+ lines)

Implementation Status

Completed (All high-priority features)

Phase 1-3: Core Infrastructure

  • Core types binding (PyTerm, PyTLExpr, PyEinsumGraph)
  • Compilation API with 6 configuration presets
  • Execution API with NumPy integration
  • Bidirectional NumPy conversion

Phase 4-8: Operations

  • Logical operations (AND, OR, NOT, quantifiers, implication)
  • Arithmetic operations (add, sub, mul, div)
  • Comparison operations (eq, lt, gt, lte, gte)
  • Conditional operations (if_then_else)

Phase 9-13: Advanced Features

  • Type stubs (.pyi) for IDE support (1100+ lines)
  • Comprehensive Python test suite (300+ tests)
  • Symbol tables and domain management (SymbolTable, CompilerContext)
  • Backend selection API (Backend, BackendCapabilities)
  • Provenance tracking with RDF* support (4 classes, 3 functions)

Phase 14-21: Complete Feature Set

  • Training API (loss functions, optimizers, callbacks, Trainer class)
  • Model Persistence (JSON/binary formats, pickle support)
  • Jupyter Integration (rich HTML display for all types)
  • Rule Builder DSL (operator overloading, domain validation)
  • Performance Monitoring (GIL release, profiler, memory tracking)
  • Streaming Execution (StreamingExecutor, ResultAccumulator)
  • Async Cancellation (CancellationToken, cancel support)
  • Utility Functions (context managers, custom exceptions, helpers)

Documentation & Quality

  • Comprehensive docstrings
  • Error handling with clear messages
  • __repr__ and __str__ implementations
  • 12 comprehensive examples
  • Zero compilation warnings
  • Production-ready code quality

Future Enhancements

  • PyTorch tensor integration
  • GPU backend support
  • ONNX export
  • Tutorial Jupyter notebooks
  • Coverage reporting in CI
  • Visualization widgets
  • Interactive debugging

Performance

SIMD Acceleration

The SciRS2 backend provides SIMD acceleration for significant speedups:

import pytensorlogic as tl

# Use SIMD backend (2-4x faster for large tensors)
result = tl.execute(graph, inputs, backend=tl.Backend.SCIRS2_SIMD)

Benchmarks (1000x1000 matrices):

  • Element-wise operations: 2.3x faster with SIMD
  • Matrix operations: 3.8x faster with SIMD
  • Reduction operations: 2.1x faster with SIMD

Limitations & Known Issues

  • Build system: Must use maturin (not regular cargo build)
  • GPU backend: Not yet implemented (CPU and SIMD only)
  • PyTorch integration: Not yet available (NumPy only)
  • Zero-copy: Not fully optimized in all paths

Development

Building from Source

# Install Rust and maturin
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
pip install maturin

# Clone and build
git clone https://github.com/cool-japan/tensorlogic.git
cd tensorlogic/crates/tensorlogic-py
maturin develop

# Run Python tests (maturin must be built first)
pytest tests/ -v
# Note: cargo nextest does not run Python integration tests for this crate

Code Quality

All code passes strict quality checks:

  • cargo check - Zero warnings
  • cargo clippy --all-targets -- -D warnings - Strict linting
  • cargo fmt --all -- --check - Consistent formatting
  • pytest tests/ - 300+ tests passing

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

Development workflow:

  1. Fork the repository
  2. Create a feature branch
  3. Make changes with tests
  4. Ensure all quality checks pass
  5. Submit a pull request

Troubleshooting

Build Issues

Problem: error: linker 'cc' not found

# Install build essentials
sudo apt-get install build-essential  # Ubuntu/Debian
brew install gcc                       # macOS

Problem: ImportError: cannot import name 'pytensorlogic'

# Rebuild with maturin
maturin develop --release

Runtime Issues

Problem: RuntimeError: Backend not available

# Check available backends
python -c "import pytensorlogic as tl; print(tl.list_available_backends())"

Problem: Shape mismatch in execution

# Check input shapes match expected domains
stats = graph.stats()
print(f"Expected inputs: {stats}")

License

Apache-2.0 - See LICENSE for details.

References

Citation

@article{tensorlogic2024,
  title={TensorLogic: Logic-as-Tensor Planning Layer},
  author={COOLJAPAN Team},
  journal={arXiv preprint arXiv:2510.12269},
  year={2024}
}

Status: Production Ready (v0.1.2) Last Updated: 2026-08-30 Completion: 100% of high-priority features (21/21 phases complete) Tests: 300+ tests passing (7 test suites) API: 80+ functions, 35+ classes, 5 custom exceptions, 6 compilation strategies, 3 serialization formats Part of: TensorLogic Ecosystem

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pytensorlogic-0.1.2-cp39-abi3-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.9+Windows x86-64

pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.8 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

pytensorlogic-0.1.2-cp39-abi3-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

pytensorlogic-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file pytensorlogic-0.1.2-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for pytensorlogic-0.1.2-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 e219361a17a01d1f53cfd8a189ca705380fdb42373319f34e76dcddb2c22ee12
MD5 e2d68759c86f833272c654d865b77c06
BLAKE2b-256 3141b2b5fa6617c0b4df02b4c0dc3df565522a43424812d5aace004aeac17c17

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytensorlogic-0.1.2-cp39-abi3-win_amd64.whl:

Publisher: pypi-publish.yml on cool-japan/tensorlogic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e6b96b470b5b3a00e8ed21fe65f00ce520dcfd1b471feb13cd3f05928381504a
MD5 ec91283fbafe953558c97eb92a6e01dc
BLAKE2b-256 977c4fd63240b4b1ddd692be5f7f9ee10a60fc82fb6ff76d3f4391c48307d3fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: pypi-publish.yml on cool-japan/tensorlogic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e0804172bfdb31572de282490368e9cc9d12599b6912f75c2bd23f601d39d557
MD5 56708428fc6c772e40db409a10ed9086
BLAKE2b-256 82aa12b07eefb74baed6eedd22000a1bd40331e97a8a5106aec5370d3390ddfa

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytensorlogic-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: pypi-publish.yml on cool-japan/tensorlogic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytensorlogic-0.1.2-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pytensorlogic-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ced66f47fe477adc538a5d7b310bfc93da29d1dad44ebcc8827c95cd4096a841
MD5 db3825b8c964f9573e76137a47d50ca5
BLAKE2b-256 7581a811b6d099925438c57df5bdccf22573e8eca7e2a01be3ef05684ecb5b26

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytensorlogic-0.1.2-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: pypi-publish.yml on cool-japan/tensorlogic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytensorlogic-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pytensorlogic-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7346329f67b8cbbf8e4d5dd1ce793d921855a469607a8345b62efa9b1356a3f1
MD5 24647de107381f7632de9926d1f60df3
BLAKE2b-256 3e4c2d8bb2b0159356b0e91a502ef2cf601eda47fc514b6c9be163b5897220eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytensorlogic-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: pypi-publish.yml on cool-japan/tensorlogic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.2 This release

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page