A neurosymbolic reasoning system that unifies neural and symbolic computation through tensor equations with temperature annealing.
Based on the Tensor Logic language from Domingos (2025), this interpreter enables smooth interpolation between analogical reasoning (high temperature) and pure deduction (T=0).
- Unified Neurosymbolic Computation: Single primitive (tensor equation) for both neural and symbolic operations
- Boolean Compositionality: Full support for logical operators (and, or, not, xor, implies, iff) with temperature control
- Temperature Annealing: Gradual transition from analogical (fuzzy) to deductive (crisp) reasoning
- Declarative Programming: Logic-like syntax for facts and rules
- Automatic Einsum: Implicit tensor operations with index notation
- Forward & Backward Chaining: Both data-driven and query-driven inference
- Stratification Checking: Ensures safe use of negation without logical paradoxes
- Gradient-Based Learning: Train embeddings and weights with PyTorch autograd
- GPU Support: Automatic acceleration with CUDA when available
git clone https://github.com/nolanwelch/tensor-logic.git
cd tensor-logic
pip install -e .- Python 3.8+
- PyTorch 2.0+
- NumPy 1.24+
pip install -r requirements.txtfrom tensor_logic import TensorLogic
# Initialize system
tl = TensorLogic(device='cpu', embedding_dim=64)
# Define a program with facts and rules
program = """
# Facts
Parent(Alice, Bob)
Parent(Bob, Charlie)
# Rules for transitive closure
Ancestor(x,y) = Parent(x,y)
Ancestor(x,z) = Ancestor(x,y) Parent(y,z)
"""
# Load and run
tl.load_program(program)
result = tl.run(max_iterations=10)
# Query results
print(tl.kb.query_relation('Ancestor', 'Alice', 'Charlie')) # TrueBoolean facts define ground truth:
Parent(Alice, Bob)
Sibling(John, Jane)
Rules define how to compute new tensors:
# Transitive closure
Ancestor(x,y) = Parent(x,y)
Ancestor(x,z) = Ancestor(x,y) Parent(y,z)
# Neural network layer
Y[i] = relu(W[i,j] X[j] + B[i])
# Matrix multiplication with einsum
C[i,k] = A[i,j] B[j,k]
Supported activation functions:
step(x)- Heaviside step functionrelu(x)- ReLU activationsigmoid(x)- Sigmoid (temperature-controlled)tanh(x)- Hyperbolic tangentsoftmax(x)- Softmaxsqrt(x)- Square rootsigma(x, T)- Temperature-controlled sigmoid
Full support for Boolean logic with temperature control:
# Negation
NotP(x) = not P(x)
# Conjunction
Both(x) = P(x) and Q(x)
# Disjunction
Either(x) = P(x) or Q(x)
# Exclusive OR
OneOnly(x) = P(x) xor Q(x)
# Implication
IfThen(x) = P(x) implies Q(x)
# Equivalence
Same(x) = P(x) iff Q(x)
# Complex expressions
Complex(x, y) = (Parent(x, y) or Friend(x, y)) and not Colleague(x, y)
At T=0: Crisp Boolean logic (classical logic) At T>0: Fuzzy logic (continuous, differentiable)
See BOOLEAN_COMPOSITIONALITY.md for details.
- Square brackets
[i,j]for numeric tensors - Parentheses
(x,y)for Boolean relations (syntactic sugar) - Repeated indices are summed (einsum convention)
The key innovation: multi-pass inference with gradually decreasing temperature:
# Run with annealing
result = tl.anneal(
T_start=1.0, # High T = analogical reasoning
T_end=0.0, # Low T = pure deduction
num_steps=5,
schedule_type='exponential'
)
# Examine reasoning trajectory
for temp, snapshot in zip(result.temperatures, result.trajectory):
print(f"T={temp:.3f}: {snapshot['Ancestor'].sum()} relationships")linear: Linear interpolationexponential: Exponential decay (recommended)sigmoid: Slow start, fast middle, slow end
# Initialize entity embeddings
tl.initialize_embeddings('Person_arg0', method='random', learnable=True)
# Embed relations for continuous reasoning
tl.kb.embed_relation('Parent')# Setup optimizer
tl.setup_learning(learning_rate=0.01, optimizer='adam')
# Define loss
loss_program = "Loss[s] = (Predicted[s] - Target[s]) ** 2"
# Train
losses = tl.train(loss_program, num_epochs=100)# Save trained state
tl.save_state('model.pt')
# Load later
tl.load_state('model.pt')tensor_logic/
├── lexer.py # Tokenization
├── ast_nodes.py # Abstract syntax tree
├── parser.py # Recursive descent parser
├── knowledge_base.py # Domain management, tensor storage
├── evaluator.py # Expression evaluation with einsum & Boolean ops
├── executor.py # Forward/backward chaining
├── annealing.py # Temperature annealing engine
├── stratification.py # Negation safety checker
├── learner.py # Gradient-based training
└── system.py # Main TensorLogic API
# Family relationships with transitive closure
program = """
Parent(Alice, Bob)
Parent(Bob, Charlie)
Parent(Charlie, Diana)
Ancestor(x,y) = Parent(x,y)
Ancestor(x,z) = Ancestor(x,y) Parent(y,z)
"""
tl.load_program(program)
tl.run(max_iterations=10)
# Query: Is Alice an ancestor of Diana?
print(tl.kb.query_relation('Ancestor', 'Alice', 'Diana')) # True
# Query: Who are Alice's descendants?
print(tl.kb.query_relation('Ancestor', 'Alice', None))
# ['Bob', 'Charlie', 'Diana']See examples/ directory for more comprehensive examples.
# Run all tests
python -m pytest tests/
# Run specific test file
python -m pytest tests/test_parser.py
# Or use unittest
python -m unittest discover tests/Tensor Logic unifies neural and symbolic computation through a single primitive: the tensor equation. Every operation, whether discrete logic or continuous neural computation, is expressed as tensor operations with einsum.
Temperature controls the "sharpness" of reasoning:
- High T (≥1.0): Soft, analogical reasoning. Sigmoid activations are smooth, allowing gradient flow and generalization.
- Low T (→0): Sharp, deductive reasoning. Sigmoid becomes step function, recovering classical logic.
The system performs multiple inference passes with decreasing temperature:
- Start with high T for soft, neural-like reasoning
- Gradually decrease T to sharpen decisions
- End at T=0 for exact logical deduction
This combines the generalization of neural networks with the guarantees of symbolic reasoning.
If you use this implementation, please cite:
@article{domingos2025tensorlogic,
title={Tensor Logic: Unifying Neural and Symbolic Computation},
author={Domingos, Pedro},
year={2025}
}MIT License - see LICENSE file for details.
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
Completed:
- Boolean Compositionality - Full support for logical operators (and, or, not, xor, implies, iff)
- Stratification Checking - Ensures safe use of negation
Future enhancements:
- Distributed execution for large-scale programs
- Sparse tensor optimization
- Probabilistic extensions (weighted rules, probabilistic logic)
- Symbolic compilation to CUDA/ONNX
- Interactive debugger
- Extended syntax (slicing, index functions, quantifiers)
- Universal/existential quantifiers (∀, ∃)
For questions and feedback, please open an issue on GitHub.