Skip to content

nolanwelch/tensor-logic

Repository files navigation

Tensor Logic

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).

Features

  • 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

Installation

From Source

git clone https://github.com/nolanwelch/tensor-logic.git
cd tensor-logic
pip install -e .

Requirements

  • Python 3.8+
  • PyTorch 2.0+
  • NumPy 1.24+
pip install -r requirements.txt

Quick Start

from 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'))  # True

Language Syntax

Facts

Boolean facts define ground truth:

Parent(Alice, Bob)
Sibling(John, Jane)

Tensor Equations

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]

Nonlinearities

Supported activation functions:

  • step(x) - Heaviside step function
  • relu(x) - ReLU activation
  • sigmoid(x) - Sigmoid (temperature-controlled)
  • tanh(x) - Hyperbolic tangent
  • softmax(x) - Softmax
  • sqrt(x) - Square root
  • sigma(x, T) - Temperature-controlled sigmoid

Boolean Operators

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.

Index Notation

  • Square brackets [i,j] for numeric tensors
  • Parentheses (x,y) for Boolean relations (syntactic sugar)
  • Repeated indices are summed (einsum convention)

Temperature Annealing

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")

Temperature Schedules

  • linear: Linear interpolation
  • exponential: Exponential decay (recommended)
  • sigmoid: Slow start, fast middle, slow end

Advanced Features

Embeddings

# Initialize entity embeddings
tl.initialize_embeddings('Person_arg0', method='random', learnable=True)

# Embed relations for continuous reasoning
tl.kb.embed_relation('Parent')

Learning

# 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)

State Persistence

# Save trained state
tl.save_state('model.pt')

# Load later
tl.load_state('model.pt')

Architecture

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

Examples

Transitive Closure

# 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.

Running Tests

# 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/

Core Concepts

Neurosymbolic Unification

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 as Reasoning Mode

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.

Multi-Pass Annealing

The system performs multiple inference passes with decreasing temperature:

  1. Start with high T for soft, neural-like reasoning
  2. Gradually decrease T to sharpen decisions
  3. End at T=0 for exact logical deduction

This combines the generalization of neural networks with the guarantees of symbolic reasoning.

Citation

If you use this implementation, please cite:

@article{domingos2025tensorlogic,
  title={Tensor Logic: Unifying Neural and Symbolic Computation},
  author={Domingos, Pedro},
  year={2025}
}

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Submit a pull request

Roadmap

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 (∀, ∃)

Contact

For questions and feedback, please open an issue on GitHub.

About

An interpreter for the Tensor Logic language from Domingos (2025)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages