Energy-efficient AI architecture optimization derived from first principles in information theory and thermodynamics.
Thermo-NN is a Python library that quantifies and minimizes the thermodynamic cost of neural network computation. Standard neural networks erase information constantly — ReLU zeros negative activations, softmax destroys scale, backpropagation discards gradients. Each erasure event costs exactly kT ln 2 joules (Landauer's principle). Modern hardware runs ~10⁹× above this theoretical minimum.
Thermo-NN bridges that gap: it analyzes where information is lost, models the physics of reversible alternatives, and maps neural network components to thermodynamically-optimal hardware — including neuromorphic processors that approach the Landauer bound through sparse spiking computation.
The causal structure was derived before the first line of code, using formal causal derivation methods. That derivation proved which NN components generate Landauer cost and which hardware alternatives reduce it. The library implements those findings. See docs/paper_draft.md for the academic paper describing the methodology.
git clone https://github.com/boonzy00/thermo-nn.git
cd thermo-nn
python -m venv venv && source venv/bin/activate
pip install -e ".[dev]"Get started immediately with PyTorch integration to profile your model's thermodynamic cost:
import torch
import torch.nn as nn
from thermo_nn.interfaces.pytorch import LandauerModelProfiler
model = nn.Sequential(
nn.Linear(128, 256),
nn.ReLU(),
nn.Linear(256, 4),
nn.Linear(4, 256),
nn.ReLU(),
nn.Linear(256, 64),
)
model.eval()
x = torch.randn(64, 128)
with LandauerModelProfiler(model, temperature=300.0) as profiler:
profile = profiler.run(x)
print(f"Peak loss layer: {profile.peak_loss_layer}")
print(f"Total bits lost: {profile.total_information_loss_bits:.3f} bits")
print(f"Total cost: {profile.total_landauer_cost_joules:.3e} J")Attach to any nn.Module — hooks fire on every forward pass, activations become Landauer profiles.
import torch
import torch.nn as nn
from thermo_nn.interfaces.pytorch import LandauerModelProfiler
model = nn.Sequential(
nn.Linear(128, 256),
nn.ReLU(),
nn.Linear(256, 4), # <- bottleneck: 256 → 4
nn.Linear(4, 256),
nn.ReLU(),
nn.Linear(256, 64),
)
model.eval()
x = torch.randn(64, 128)
with LandauerModelProfiler(model, temperature=300.0) as profiler:
profile = profiler.run(x)
print(f"Peak loss layer: {profile.peak_loss_layer}") # '2' (the 256→4 layer)
print(f"Total bits lost: {profile.total_information_loss_bits:.3f} bits")
print(f"Total cost: {profile.total_landauer_cost_joules:.3e} J")
for name, stats in profile.layers.items():
print(f" {name:<6} {stats.input_entropy_bits:.3f} → {stats.output_entropy_bits:.3f} bits "
f"loss={stats.information_loss_bits:.3f} bits "
f"eff_rank {stats.effective_rank_in:.1f}→{stats.effective_rank_out:.1f}")Verified on real models (64-sample batch, 300K):
| Layer | H_in | H_out | Loss | Eff. rank change | Cost |
|---|---|---|---|---|---|
| fc1 | 5.835 bits | 5.835 bits | 0.000 bits | 57.1 → 57.1 | 0 J |
| bottle_down | 5.835 bits | 1.950 bits | 3.886 bits | 57.1 → 3.9 | 1.12×10⁻²⁰ J |
| bottle_up | 1.950 bits | 1.864 bits | 0.086 bits | 3.9 → 3.6 | 2.5×10⁻²² J |
| fc3 | 1.864 bits | 2.855 bits | 0.000 bits | 3.6 → 7.2 | 0 J |
The 256→4 bottleneck destroys 3.886 bits. The tool identifies it as peak_loss_layer with no configuration — it fires automatically because spectral entropy drops from 57 effective dimensions to 3.9. The bottleneck model has 5.7× more total information loss than the equivalent model without the chokepoint.
Options:
# Hook only Linear layers, skip Dropout
with LandauerModelProfiler(
model,
layer_types=(nn.Linear,),
skip_types=(nn.Dropout,),
temperature=310.0,
) as profiler:
profile = profiler.run(x)
# Manual attach/detach
profiler = LandauerModelProfiler(model)
profiler.attach()
for batch in dataloader:
profile = profiler.run(batch) # re-profile each batch
profiler.detach()Layer-by-layer information destruction measured via spectral entropy. Converts information loss directly to Landauer cost. The peak_loss_layer is the alignment prediction: the layer where the most information is irreversibly destroyed is structurally upstream of alignment failures.
import numpy as np
from thermo_nn.core import LandauerInformationEngine
engine = LandauerInformationEngine(temperature=300.0)
# Pass any dict of layer activations: {name: numpy array (n_samples, n_features)}
# Works with activations captured from any framework via forward hooks.
profile = engine.profile({
"embedding": np.random.randn(64, 768),
"attention_0": np.random.randn(64, 768),
"ffn_0": np.random.randn(64, 3072),
"attention_1": np.random.randn(64, 768),
"ffn_1": np.random.randn(64, 64), # large compression here
"output": np.random.randn(64, 10),
})
print(f"Peak loss layer: {profile.peak_loss_layer}")
print(f"Total bits lost: {profile.total_information_loss_bits:.2f} bits")
print(f"Total cost: {profile.total_landauer_cost_joules:.3e} J")
print(f"Landauer units: {profile.landauer_multiple():.1f} × kT ln 2")
# Per-layer breakdown
for name, stats in profile.layers.items():
print(f" {name:<15} loss={stats.information_loss_bits:.2f} bits "
f"rank {stats.effective_rank_in:.1f}→{stats.effective_rank_out:.1f} "
f"cost={stats.landauer_cost_joules:.2e} J")
# Alignment risk ranking — top layers most likely to originate failures
print(f"Alignment risk layers: {profile.alignment_risk_layers(top_k=3)}")
# Compare two models: positive diff = A destroys more information at that layer
profile_b = engine.profile({ ... })
diff = engine.compare(profile, profile_b)The alignment prediction is grounded in the causal finding (Boonzy00, 2026) that information loss — not goal misalignment — is the primary upstream driver of alignment failure: 42 of 51 counterfactually removable risk paths flow through information destruction. The layer with maximum Landauer cost is where the model loses the information it needs to distinguish between inputs requiring different behavior.
Key functions:
| Function | Returns | Physics |
|---|---|---|
spectral_entropy(matrix) |
bits | Shannon entropy of SVD singular value spectrum |
effective_rank(matrix) |
float | exp(H(σ/‖σ‖₁)) — Roy & Vetterli 2007 |
information_loss_bits(in, out) |
bits | max(0, H_in − H_out) |
landauer_cost_from_bits(bits, T) |
joules | bits × kT ln 2 |
ANN→SNN conversion with Landauer-grounded energy analysis and neuromorphic hardware interfaces.
from thermo_nn.optimizers.spiking import SpikingConverter
from thermo_nn.interfaces.neuromorphic import NeuromorphicInterface
# SNN thermodynamic cost: E = activity_rate × N × kT ln 2
sc = SpikingConverter(temperature=300.0, encoding="ttfs")
r = sc.analyze_layer("attention", input_size=768, activity_rate=0.2)
print(f"ANN energy: {r.ann_energy_joules:.3e} J") # standard CMOS full-precision
print(f"SNN energy: {r.snn_energy_joules:.3e} J") # Landauer minimum, sparse
print(f"Reduction: {r.energy_reduction_factor:.2e}×") # ~10^7× at 300K
print(f"TTFS target: {r.meets_ttfs_target}") # <0.3 spikes/neuron
# Full transformer stack
layers = [
{"type": "linear", "input_size": 768},
{"type": "attention", "input_size": 768},
{"type": "relu", "input_size": 3072},
]
arch = sc.analyze_architecture(layers)
print(f"Total ANN: {arch.total_ann_energy_joules:.3e} J")
print(f"Total SNN: {arch.total_snn_energy_joules:.3e} J")
# Map to neuromorphic hardware
ni = NeuromorphicInterface()
cmp = ni.compare_platforms("attention", input_size=768, activity_rate=0.3)
print(f"Best platform: {cmp.best_platform}") # "loihi2"
print(f"GPU → Loihi 2: {cmp.results['loihi2'].hardware_reduction_factor:.0f}×")
print(f"Above Landauer: {cmp.results['loihi2'].multiples_above_landauer:.1e}×")Neuromorphic hardware profiles:
| Platform | Neurons | Energy/spike | Efficiency | vs GPU | Learning |
|---|---|---|---|---|---|
| Intel Loihi 2 | 1,048,576 | 1.18 pJ | 847 GOp/s/W | 312× | Yes |
| IBM TrueNorth | 1,048,576 | 2.69 pJ | 371 GOp/s/W | ~185× | No |
The 330× system improvement (NeuEdge 2026) is the hardware ratio (Loihi 2 vs GPU). The thermodynamic ratio (SNN Landauer bound vs ANN standard CMOS) is ~10⁷× — the practical hardware hasn't reached the thermodynamic floor.
CAMOS (Causal-Aware Multi-Objective Search) extends NSGA-II with causal reasoning, counterfactual prediction, entropy pruning, and adaptive objective weighting. Multi-objective neural architecture search using spectral entropy and information-theoretic objectives to guide co-design of neural architectures and hardware mapping.
Standard NSGA-II Search:
from thermo_nn.optimizers.codesign import (
ArchitectureSearchSpace,
CoDesignSearch,
LandauerCostObjective,
InformationLossObjective,
HardwareObjective,
HardwareMapper,
)
# Initialize search space and objectives
search_space = ArchitectureSearchSpace()
mapper = HardwareMapper()
profile = mapper.get_profile("neuroscale")
objectives = [
LandauerCostObjective(),
InformationLossObjective(),
HardwareObjective(profile, metric="energy"),
]
# Run NSGA-II search
search = CoDesignSearch(search_space, objectives)
final_population = search.search(
generations=50,
population_size=100,
early_stopping=True,
patience=10,
)
# Get Pareto front
pareto_front = search.get_pareto_front()
for individual in pareto_front:
print(f"Landauer: {individual.objectives['landauer_cost']:.2e} J")
print(f"Hardware: {individual.objectives['hardware_energy']:.2e} J")CAMOS (Causal-Aware Multi-Objective Search):
CAMOS extends NSGA-II with causal reasoning, counterfactual prediction, entropy pruning, and adaptive objective weighting. Based on causal analysis showing 66.3% effect from causal ordering and 60.2% effect from reversibility detection.
from thermo_nn.optimizers.codesign import (
ArchitectureSearchSpace,
CausalAwareSearch,
CAMOSConfig,
LandauerCostObjective,
InformationLossObjective,
HardwareObjective,
HardwareMapper,
)
# Initialize search space and objectives
search_space = ArchitectureSearchSpace()
mapper = HardwareMapper()
profile = mapper.get_profile("neuroscale")
objectives = [
LandauerCostObjective(),
InformationLossObjective(),
HardwareObjective(profile, metric="energy"),
]
# Configure CAMOS (selective mode - counterfactual disabled due to accuracy limitations)
camos_config = CAMOSConfig(
use_causal_graph=True,
use_counterfactual=False, # Disabled - predictions not accurate enough
use_reversibility=True,
use_entropy_pruning=True,
use_adaptive_weighting=True,
entropy_threshold=0.8,
)
# Run CAMOS search
search = CausalAwareSearch(search_space, objectives, camos_config)
final_population = search.search(
generations=50,
population_size=100,
verbose=True,
)
# Get statistics
stats = search.get_statistics()
print(f"Pruned: {stats['pruned_count']}")
print(f"Counterfactual filtered: {stats['counterfactual_filtered_count']}")
print(f"Reversibility bonus applied: {stats['reversibility_bonus_count']}")CLI Usage:
# Standard NSGA-II search
thermo-nn codesign search --hardware neuroscale --generations 50 --population 100
# CAMOS search with causal reasoning
thermo-nn codesign search --hardware neuroscale --generations 50 --population 100 --algorithm camosBenchmark Results:
Selective CAMOS mode (causal guidance + reversibility bonus + entropy pruning) vs NSGA-II:
| Metric | NSGA-II | CAMOS | Improvement |
|---|---|---|---|
| Time (s) | 0.05 | 0.01 | +79.1% |
| Pareto front size | 30 | 30 | 0% |
| Best Landauer cost (J) | 5.20e-19 | 4.90e-19 | +5.9% |
CAMOS-Specific Statistics:
- Pruned architectures: 25 (entropy pruning working)
- Reversibility bonus applied: 75 (reversibility detection working)
- Counterfactual filtered: 0 (disabled - predictions not accurate enough)
Note: Selective CAMOS mode shows significant speed improvements over NSGA-II with modest cost improvements. Counterfactual filtering is disabled due to prediction inaccuracy (simplified SCM model insufficient for complex architecture-objective mapping). Adaptive weighting is disabled for single-objective case (not applicable). See CHANGELOG for detailed investigation findings and known issues.
Multi-substrate co-design engine for algorithm-hardware joint optimization:
from thermo_nn.optimizers.codesign.hardware_substrate import (
SubstrateType, SubstrateConfig, SubstrateFactory
)
# Configure memristor substrate with ADC optimization
memristor_config = SubstrateConfig(
substrate_type=SubstrateType.MEMRISTOR,
adc_bits=8,
synaptic_precision=16,
approximation_level=0.1
)
# Create substrate instance
substrate = SubstrateFactory.create_substrate(memristor_config)
# Evaluate architecture on substrate
from thermo_nn.optimizers.codesign.search_space import ArchitectureConfig
arch_config = ArchitectureConfig(
layers=[...], # layer configurations
)
metrics = substrate.evaluate_architecture(arch_config)
print(f"Energy: {metrics.energy:.2e} J")
print(f"Latency: {metrics.latency:.2e} s")
print(f"Throughput: {metrics.throughput:.2e} ops/s")Supported Substrates:
| Substrate | Technology | Key Benefits | Research Basis |
|---|---|---|---|
| Memristor | ReRAM | ADC optimization (1.6-2.3x power reduction) | Zhang et al. 2024 |
| Spintronic | STT-RAM | 4x GSOPS/W/mm² improvement | Babu et al. 2020 |
| Photonic | Optical | (future research) | - |
| CMOS | Baseline | Reference implementation | - |
Key Features:
- Unified substrate interface via
HardwareSubstrateabstract base class - Substrate-specific optimization suggestions
- Hardware-aware evaluation integrated into CAMOS pipeline
- Combines theoretical Landauer cost with actual hardware energy
- Adds hardware-specific objectives (latency, power) for multi-objective optimization
CLI usage:
# Run co-design search
thermo-nn codesign search --hardware neuroscale --generations 50 --population 100
# Evaluate specific architecture
thermo-nn codesign evaluate --architecture arch.json --hardware texel
# Profile hardware mapping
thermo-nn codesign profile --hardware thermodynamicImplements fast-slow memory organization inspired by cortical fast-slow organization in the brain. Based on Sun et al. (2025) research showing 4x throughput and 5x energy efficiency improvements.
Key Features:
- Fast Pathway: Event-driven spiking activity for immediate processing
- Slow Pathway: Compact low-dimensional state for long-term context
- Benefits: 4x throughput, 5x energy efficiency, 40-60% parameter reduction
- Integration: Seamlessly integrates with hardware substrate layer
Usage Example:
from thermo_nn.optimizers.codesign.dual_memory_pathway import (
SpikingDMP, DMPConfig, DMPFactory, estimate_dmp_benefits
)
# Create spiking DMP with custom configuration
config = DMPConfig(
fast_threshold=1.0,
slow_state_dim=16,
parameter_reduction=0.5
)
dmp = SpikingDMP(input_dim=10, hidden_dim=32, output_dim=5, config=config)
# Forward pass
input_data = np.random.randn(10)
fast_output, slow_modulation, metrics = dmp.forward(input_data)
# Estimate benefits for baseline architecture
benefits = estimate_dmp_benefits(
baseline_params=1000,
baseline_throughput=1e9,
baseline_energy=1e-9
)
# Expected: 4x throughput, 5x energy efficiency, 50% parameter reductionHardware Substrate Integration:
from thermo_nn.optimizers.codesign.hardware_substrate import SubstrateConfig, SubstrateType
# Enable DMP in hardware substrate
config = SubstrateConfig(
substrate_type=SubstrateType.MEMRISTOR,
use_dmp=True,
dmp_config={'fast_threshold': 1.0, 'slow_state_dim': 16}
)Research Basis:
- Sun et al. (2025): "Algorithm-hardware co-design of neuromorphic networks with dual memory pathways"
- 4x throughput increase through event-driven sparsity preservation
- 5x energy efficiency through compact state representation
- 40-60% parameter reduction via fast-slow pathway separation
Implements tile-based distributed-memory architecture with data-local execution and traffic-aware scheduling. Based on Orenes-Vera et al. (2022) research showing 2 orders of magnitude performance and energy improvement for memory-bound applications.
Key Features:
- Data-Local Execution: Minimizes data movement by executing tasks where data resides
- Traffic-Aware Scheduling: Optimizes inter-tile communication based on network load
- Scalable Topology: Supports mesh, ring, and torus network topologies
- Benefits: 100x performance, 100x energy efficiency for memory-bound workloads
Usage Example:
from thermo_nn.optimizers.codesign.tile_memory_architecture import (
DataLocalTBMA, TBMAConfig, TBMAFactory, estimate_tbma_benefits
)
# Create TBMA with custom configuration
config = TBMAConfig(
num_tiles=16,
tile_memory_size=1024,
network_topology="mesh",
scheduling_policy="traffic_aware"
)
tbma = DataLocalTBMA(config)
# Execute tasks
tasks = [{'id': i, 'operation': 'compute'} for i in range(10)]
completed_tasks, metrics = tbma.forward(tasks)
# Estimate benefits for baseline architecture
benefits = estimate_tbma_benefits(
baseline_performance=1e9,
baseline_energy=1e-9,
num_tiles=16
)
# Expected: 100x performance, 100x energy efficiencyHardware Substrate Integration:
from thermo_nn.optimizers.codesign.hardware_substrate import SubstrateConfig, SubstrateType
# Enable TBMA in hardware substrate
config = SubstrateConfig(
substrate_type=SubstrateType.MEMRISTOR,
use_tbma=True,
tbma_config={'num_tiles': 16, 'network_topology': 'mesh'}
)Research Basis:
- Orenes-Vera et al. (2022): "Dalorex: A Data-Local Program Execution and Architecture for Memory-bound Applications"
- 2 orders of magnitude performance improvement through data-local execution
- 2 orders of magnitude energy improvement through traffic-aware scheduling
- Tile-based distributed memory organization for scalable memory-bound workloads
Implements adaptive numerical formats including posit arithmetic and logarithmic representations for hardware efficiency improvements. Based on research showing significant area, power, and latency improvements through tapered precision and dynamic range optimization.
Key Features:
- Posit Arithmetic: Tapered precision with wide dynamic range and improved numerical robustness
- Multiple Formats: Posit(8,0), Posit(16,1), Posit(32,2), logarithmic, and block posit
- Fused Architecture: Fused dot-product units for 43% area, 64% latency, 70% power reduction
- Block Representation: 80% area reduction without accuracy loss
- Benefits: Up to 80% area reduction, 70% power reduction, 64% latency reduction
Usage Example:
from thermo_nn.optimizers.codesign.numerical_representation import (
PositRepresentation, LogarithmicRepresentation, NumericalFormatFactory,
estimate_numerical_format_benefits, NumericalFormat
)
# Create posit representation with fused architecture
posit = NumericalFormatFactory.create_posit(
bit_width=16,
exponent_bits=1,
use_fused=True
)
# Estimate hardware benefits
benefits = posit.estimate_hardware_benefits(
baseline_area=1.0,
baseline_power=1.0,
baseline_latency=1.0
)
# Expected: 28% area, 17% power, 17% latency improvement
# Create logarithmic representation
log_rep = NumericalFormatFactory.create_logarithmic()
log_benefits = log_rep.estimate_hardware_benefits(1.0, 1.0, 1.0)
# Expected: 50% area, 54.5% power, 50% latency improvementHardware Substrate Integration:
from thermo_nn.optimizers.codesign.hardware_substrate import SubstrateConfig, SubstrateType
# Enable numerical representation in hardware substrate
config = SubstrateConfig(
substrate_type=SubstrateType.MEMRISTOR,
use_numerical_representation=True,
numerical_format_config={
'format': 'posit(16,1)',
'use_fused': True,
'use_block': False
}
)Research Basis:
- Kumar et al. (2026): SPADE SIMD Posit-enabled compute engine - 45.13% LUT reduction, 80% slice reduction
- Li et al. (2023): PDPU open-source posit dot-product unit - 43% area, 64% latency, 70% power reduction
- Hsiao et al. (2024): Block posit DNN accelerator - 80% area reduction without accuracy loss
- Ramachandran et al. (2024): Distribution-aware logarithmic posit - 2x performance/area, 2.2x energy efficiency
Five physics-backed technology profiles with charging model and frequency-energy optimizer.
from thermo_nn.optimizers.adiabatic import AdiabaticCharger, AdiabaticOptimizer
from thermo_nn.research.hardware_models import get_profile
# Adiabatic charging: E = (C×V²/2) × min(1, τ_RC/τ_op)
charger = AdiabaticCharger()
r = charger.charging_energy(C=2e-15, V=0.9, tau_rc_s=10e-12, tau_op_s=1e-9)
print(f"Savings: {r.energy_savings_pct:.1f}%") # 99% at τ_op=1ns, τ_RC=10ps
print(f"Factor: {r.adiabaticity_factor:.4f}") # 0.01 — well below RC limit
# High-level comparison across all 5 technologies
opt = AdiabaticOptimizer()
cmp = opt.compare_technologies("attention", input_size=768)
print(f"Best: {cmp.best_technology}") # "qca" (10^8× improvement)
print(f"Savings: {cmp.best_energy_savings_pct:.1f}%")Technology profiles:
| Technology | Improvement | Temperature | Notes |
|---|---|---|---|
standard_cmos |
1× (baseline) | Room temp | Reference |
adiabatic_cmos |
10× | Room temp | Split-level rails |
low_leakage_cmos |
20,000× | Room temp | Near-threshold 0.3V |
superconductor_rqfp |
10⁶× | 4.2 K | Josephson junctions |
qca |
10⁸× | 77 K | Coulomb-coupling |
Bennett-clocking and block-reversible schemes with exact physics per layer type.
from thermo_nn.optimizers.reversible import BennettClocking, BlockReversibleScheme, ReversibleOptimizer
bc = BennettClocking(temperature=300.0)
r = bc.analyze_layer("attention", input_size=768)
print(f"Standard cost: {r.standard_cost_joules:.3e} J")
print(f"Bennett cost: {r.bennett_cost_joules:.3e} J")
print(f"Energy savings: {r.energy_savings_pct:.1f}%") # ~62% for attention
print(f"Throughput: {r.throughput_penalty}×") # 2× (forward + uncompute)
# Block-reversible (RevNet-style): O(blocks) memory vs O(layers)
br = BlockReversibleScheme()
r = br.analyze(num_layers=12, layer_type="attention", activation_size=768, block_size=4)
print(f"Memory reduction: {r.memory_reduction_factor:.1f}×") # 3×
print(f"Throughput penalty: {r.throughput_penalty:.2f}×") # 1.25×
# Reversible gate circuits — zero Landauer cost with Bennett uncompute
from thermo_nn.research import synthesize_layer
circuit = synthesize_layer("relu", input_size=1000, uncompute_ancilla=True)
print(f"Landauer cost: {circuit.landauer_cost_joules} J") # 0.0Bennett is only beneficial when intermediate_bits × erasure_fraction > output_bits. Attention (3× intermediate multiplier) and transformer blocks (4×) pass this threshold. ReLU does not.
Four independent thermodynamic cost models.
from thermo_nn.core import LandauerEngine
engine = LandauerEngine(temperature=300.0)
engine.equilibrium_cost(bits=1000) # E = bits × kT ln 2
engine.finite_time_cost(bits=1000, operation_time_s=1e-9) # + kT·τ₀/τ speed penalty
engine.many_valued_cost(symbols=1000, logic_base=3) # kT ln N per symbol
engine.non_equilibrium_cost(bits=1000, delta_f=2.5e-18, work_done=3e-18) # Jarzynski
engine.error_correction_cost(data_bits=1000, code_rate=0.5) # ECC overheadLandauer cost calculator, entropy profiler, causal verifier, CLI.
# Analyze a layer
thermo-nn analyze attention --input-size 768
# Optimization recommendations (reversible + adiabatic)
thermo-nn optimize attention --input-size 768 --num-layers 12
# Causal verification (principle lookup + heuristic)
thermo-nn verify information_erasure heat_dissipationthermo-nn/
├── src/thermo_nn/
│ ├── core/
│ │ ├── information.py # Spectral entropy, LandauerInformationEngine
│ │ ├── landauer_engine.py # 4 cost models, Jarzynski, ECC
│ │ ├── analyzer.py # Landauer cost per layer type
│ │ ├── profiler.py # Entropy tracker
│ │ └── verifier.py # Causal claim verifier
│ ├── optimizers/
│ │ ├── reversible.py # Bennett-clocking, block-reversible
│ │ ├── adiabatic.py # 5 technology profiles, freq optimizer
│ │ ├── spiking.py # ANN→SNN, TTFS encoding
│ │ └── hardware.py # Hardware co-design interface
│ ├── research/
│ │ ├── reversible_circuits.py # Toffoli, Fredkin, gate synthesis
│ │ └── hardware_models.py # TechnologyProfile, TECHNOLOGY_PROFILES
│ ├── interfaces/
│ │ ├── neuromorphic.py # Loihi 2, TrueNorth hardware adapters
│ │ ├── pytorch.py # LandauerModelProfiler (live hooks)
│ │ └── tensorflow.py # TensorFlow integration
│ └── utils/
│ ├── reporting.py # JSON/text report generation
│ └── metrics.py # Thermodynamic metrics
├── tests/
│ ├── unit/
│ │ ├── test_information.py # 48 tests
│ │ ├── test_landauer_engine.py # 29 tests
│ │ ├── test_reversible.py # 45 tests
│ │ ├── test_adiabatic.py # 48 tests
│ │ ├── test_spiking.py # 98 tests
│ │ ├── test_analyzer.py
│ │ ├── test_profiler.py
│ │ └── test_verifier.py
│ └── integration/
│ ├── test_pytorch_hooks.py # 26 tests (live hooks proof)
│ └── test_pipeline.py
├── docs/
│ ├── PHYSICS.md # Physics reference — equations, constants, invariants
│ ├── paper_draft.md # Academic paper in progress
│ ├── tutorial.md # Tutorials and examples
│ └── CAMOS_algorithm.md # CAMOS algorithm documentation
├── CHANGELOG.md
└── pyproject.toml
venv/bin/pytest tests/ -v
# 547 tests collected- Landauer (1961): Erasing one bit requires at least
kT ln 2joules. At 300K: 2.87×10⁻²¹ J/bit. Modern hardware: ~10⁹× above this. - Bennett (1982): Any irreversible computation can be made reversible via compute→copy→uncompute. Only the copy step pays Landauer cost.
- Gomez et al. (2017): RevNet — block-reversible residual networks that reconstruct activations rather than storing them.
- Hänninen et al. (2014): Adiabatic CMOS achieves 10× improvement over standard CMOS.
- Lent et al. (1993): Quantum-dot cellular automata — Coulomb-coupling logic, 10⁸× improvement potential.
- Davies et al. (2021): Intel Loihi 2 — 1M neurons, 847 GOp/s/W, 312× vs GPU in SNN inference.
See docs/PHYSICS.md for the complete physics reference.
@software{thermo_nn_2026,
title={Thermo-NN: Thermodynamic Neural Networks},
author={Boonzy00},
year={2026},
url={https://github.com/boonzy00/thermo-nn}
}MIT — see LICENSE.
See CONTRIBUTING.md and docs/PHYSICS.md.
Version: 0.2.0