git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
637 lines
17 KiB
Rust
637 lines
17 KiB
Rust
//! # Cognitive Thermodynamics
|
|
//!
|
|
//! Deep exploration of Landauer's principle and thermodynamic constraints
|
|
//! on cognitive processing.
|
|
//!
|
|
//! ## Key Concepts
|
|
//!
|
|
//! - **Landauer's Principle**: Erasing 1 bit costs kT ln(2) energy
|
|
//! - **Reversible Computation**: Computation without erasure costs no energy
|
|
//! - **Cognitive Temperature**: Noise/randomness in cognitive processing
|
|
//! - **Maxwell's Demon**: Information-to-work conversion
|
|
//! - **Thought Entropy**: Disorder in cognitive states
|
|
//!
|
|
//! ## Theoretical Foundation
|
|
//!
|
|
//! Based on:
|
|
//! - Landauer (1961) - Irreversibility and Heat Generation
|
|
//! - Bennett - Reversible Computation
|
|
//! - Szilard Engine - Information thermodynamics
|
|
//! - Jarzynski Equality - Non-equilibrium thermodynamics
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::{HashMap, VecDeque};
|
|
|
|
/// Cognitive thermodynamics system
|
|
#[derive(Debug)]
|
|
pub struct CognitiveThermodynamics {
|
|
/// Cognitive temperature (noise level)
|
|
temperature: f64,
|
|
/// Total entropy of the system
|
|
entropy: ThoughtEntropy,
|
|
/// Energy budget tracking
|
|
energy: EnergyBudget,
|
|
/// Maxwell's demon instance
|
|
demon: MaxwellDemon,
|
|
/// Phase state
|
|
phase: CognitivePhase,
|
|
/// History of thermodynamic events
|
|
history: VecDeque<ThermodynamicEvent>,
|
|
/// Boltzmann constant (normalized)
|
|
k_b: f64,
|
|
}
|
|
|
|
/// Entropy tracking for cognitive system
|
|
#[derive(Debug)]
|
|
pub struct ThoughtEntropy {
|
|
/// Current entropy level
|
|
current: f64,
|
|
/// Entropy production rate
|
|
production_rate: f64,
|
|
/// Entropy capacity
|
|
capacity: f64,
|
|
/// Entropy components
|
|
components: HashMap<String, f64>,
|
|
}
|
|
|
|
/// Energy budget for cognitive operations
|
|
#[derive(Debug, Clone)]
|
|
pub struct EnergyBudget {
|
|
/// Available energy
|
|
available: f64,
|
|
/// Total energy consumed
|
|
consumed: f64,
|
|
/// Energy from erasure
|
|
erasure_cost: f64,
|
|
/// Energy recovered from reversible computation
|
|
recovered: f64,
|
|
}
|
|
|
|
/// Maxwell's Demon for cognitive sorting
|
|
#[derive(Debug)]
|
|
pub struct MaxwellDemon {
|
|
/// Demon's memory (cost of operation)
|
|
memory: Vec<bool>,
|
|
/// Memory capacity
|
|
capacity: usize,
|
|
/// Work extracted
|
|
work_extracted: f64,
|
|
/// Information cost
|
|
information_cost: f64,
|
|
/// Operating state
|
|
active: bool,
|
|
}
|
|
|
|
/// Phase states of cognitive matter
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum CognitivePhase {
|
|
/// Solid - highly ordered, low entropy
|
|
Crystalline,
|
|
/// Liquid - flowing thoughts, moderate entropy
|
|
Fluid,
|
|
/// Gas - chaotic, high entropy
|
|
Gaseous,
|
|
/// Critical point - phase transition
|
|
Critical,
|
|
/// Bose-Einstein condensate analog - unified consciousness
|
|
Condensate,
|
|
}
|
|
|
|
/// A thermodynamic event
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ThermodynamicEvent {
|
|
pub event_type: EventType,
|
|
pub entropy_change: f64,
|
|
pub energy_change: f64,
|
|
pub timestamp: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum EventType {
|
|
Erasure,
|
|
Computation,
|
|
Measurement,
|
|
PhaseTransition,
|
|
DemonOperation,
|
|
HeatDissipation,
|
|
}
|
|
|
|
impl CognitiveThermodynamics {
|
|
/// Create a new cognitive thermodynamics system
|
|
pub fn new(temperature: f64) -> Self {
|
|
Self {
|
|
temperature: temperature.max(0.001), // Avoid division by zero
|
|
entropy: ThoughtEntropy::new(100.0),
|
|
energy: EnergyBudget::new(1000.0),
|
|
demon: MaxwellDemon::new(100),
|
|
phase: CognitivePhase::Fluid,
|
|
history: VecDeque::with_capacity(1000),
|
|
k_b: 1.0, // Normalized Boltzmann constant
|
|
}
|
|
}
|
|
|
|
/// Measure current cognitive temperature
|
|
pub fn measure_temperature(&self) -> f64 {
|
|
self.temperature
|
|
}
|
|
|
|
/// Set cognitive temperature
|
|
pub fn set_temperature(&mut self, temp: f64) {
|
|
let old_temp = self.temperature;
|
|
self.temperature = temp.max(0.001);
|
|
|
|
// Check for phase transition
|
|
self.check_phase_transition(old_temp, self.temperature);
|
|
}
|
|
|
|
fn check_phase_transition(&mut self, old: f64, new: f64) {
|
|
// Critical temperatures for phase transitions
|
|
const T_FREEZE: f64 = 100.0;
|
|
const T_BOIL: f64 = 500.0;
|
|
const T_CRITICAL: f64 = 1000.0;
|
|
const T_CONDENSATE: f64 = 10.0;
|
|
|
|
let old_phase = self.phase.clone();
|
|
|
|
self.phase = if new < T_CONDENSATE {
|
|
CognitivePhase::Condensate
|
|
} else if new < T_FREEZE {
|
|
CognitivePhase::Crystalline
|
|
} else if new < T_BOIL {
|
|
CognitivePhase::Fluid
|
|
} else if new < T_CRITICAL {
|
|
CognitivePhase::Gaseous
|
|
} else {
|
|
CognitivePhase::Critical
|
|
};
|
|
|
|
if old_phase != self.phase {
|
|
// Record phase transition
|
|
self.record_event(ThermodynamicEvent {
|
|
event_type: EventType::PhaseTransition,
|
|
entropy_change: (new - old).abs() * 0.1,
|
|
energy_change: -(new - old).abs() * self.k_b,
|
|
timestamp: self.current_time(),
|
|
});
|
|
}
|
|
}
|
|
|
|
/// Compute Landauer cost of erasing n bits
|
|
pub fn landauer_cost(&self, bits: usize) -> f64 {
|
|
// E = n * k_B * T * ln(2)
|
|
bits as f64 * self.k_b * self.temperature * std::f64::consts::LN_2
|
|
}
|
|
|
|
/// Erase information (irreversible)
|
|
pub fn erase(&mut self, bits: usize) -> ErasureResult {
|
|
let cost = self.landauer_cost(bits);
|
|
|
|
if self.energy.available < cost {
|
|
return ErasureResult {
|
|
success: false,
|
|
bits_erased: 0,
|
|
energy_cost: 0.0,
|
|
entropy_increase: 0.0,
|
|
};
|
|
}
|
|
|
|
// Consume energy
|
|
self.energy.available -= cost;
|
|
self.energy.consumed += cost;
|
|
self.energy.erasure_cost += cost;
|
|
|
|
// Increase entropy (heat dissipation)
|
|
let entropy_increase = bits as f64 * std::f64::consts::LN_2;
|
|
self.entropy.current += entropy_increase;
|
|
self.entropy.production_rate = entropy_increase;
|
|
|
|
self.record_event(ThermodynamicEvent {
|
|
event_type: EventType::Erasure,
|
|
entropy_change: entropy_increase,
|
|
energy_change: -cost,
|
|
timestamp: self.current_time(),
|
|
});
|
|
|
|
ErasureResult {
|
|
success: true,
|
|
bits_erased: bits,
|
|
energy_cost: cost,
|
|
entropy_increase,
|
|
}
|
|
}
|
|
|
|
/// Perform reversible computation
|
|
pub fn reversible_compute<T>(
|
|
&mut self,
|
|
input: T,
|
|
forward: impl Fn(T) -> T,
|
|
_backward: impl Fn(T) -> T,
|
|
) -> T {
|
|
// Reversible computation has no erasure cost
|
|
// Only the logical transformation happens
|
|
|
|
self.record_event(ThermodynamicEvent {
|
|
event_type: EventType::Computation,
|
|
entropy_change: 0.0, // Reversible = no entropy change
|
|
energy_change: 0.0,
|
|
timestamp: self.current_time(),
|
|
});
|
|
|
|
forward(input)
|
|
}
|
|
|
|
/// Perform measurement (gains information, increases entropy elsewhere)
|
|
pub fn measure(&mut self, precision_bits: usize) -> MeasurementResult {
|
|
// Measurement is fundamentally irreversible
|
|
// Gains information but produces entropy
|
|
|
|
let information_gained = precision_bits as f64;
|
|
let entropy_cost = precision_bits as f64 * std::f64::consts::LN_2;
|
|
let energy_cost = self.landauer_cost(precision_bits);
|
|
|
|
self.entropy.current += entropy_cost;
|
|
self.energy.available -= energy_cost;
|
|
self.energy.consumed += energy_cost;
|
|
|
|
self.record_event(ThermodynamicEvent {
|
|
event_type: EventType::Measurement,
|
|
entropy_change: entropy_cost,
|
|
energy_change: -energy_cost,
|
|
timestamp: self.current_time(),
|
|
});
|
|
|
|
MeasurementResult {
|
|
information_gained,
|
|
entropy_cost,
|
|
energy_cost,
|
|
}
|
|
}
|
|
|
|
/// Run Maxwell's demon to extract work
|
|
pub fn run_demon(&mut self, operations: usize) -> DemonResult {
|
|
if !self.demon.active {
|
|
return DemonResult {
|
|
work_extracted: 0.0,
|
|
memory_used: 0,
|
|
erasure_cost: 0.0,
|
|
net_work: 0.0,
|
|
};
|
|
}
|
|
|
|
let ops = operations.min(self.demon.capacity - self.demon.memory.len());
|
|
if ops == 0 {
|
|
// Demon must erase memory first
|
|
let erase_cost = self.landauer_cost(self.demon.memory.len());
|
|
self.demon.memory.clear();
|
|
self.demon.information_cost += erase_cost;
|
|
self.energy.available -= erase_cost;
|
|
|
|
return DemonResult {
|
|
work_extracted: 0.0,
|
|
memory_used: 0,
|
|
erasure_cost: erase_cost,
|
|
net_work: -erase_cost,
|
|
};
|
|
}
|
|
|
|
// Each operation records 1 bit and extracts k_B * T * ln(2) work
|
|
let work_per_op = self.k_b * self.temperature * std::f64::consts::LN_2;
|
|
let total_work = ops as f64 * work_per_op;
|
|
|
|
for _ in 0..ops {
|
|
self.demon.memory.push(true);
|
|
}
|
|
self.demon.work_extracted += total_work;
|
|
|
|
self.record_event(ThermodynamicEvent {
|
|
event_type: EventType::DemonOperation,
|
|
entropy_change: -(ops as f64) * std::f64::consts::LN_2, // Local decrease
|
|
energy_change: total_work,
|
|
timestamp: self.current_time(),
|
|
});
|
|
|
|
DemonResult {
|
|
work_extracted: total_work,
|
|
memory_used: ops,
|
|
erasure_cost: 0.0,
|
|
net_work: total_work,
|
|
}
|
|
}
|
|
|
|
/// Get current phase
|
|
pub fn phase(&self) -> &CognitivePhase {
|
|
&self.phase
|
|
}
|
|
|
|
/// Get entropy
|
|
pub fn entropy(&self) -> &ThoughtEntropy {
|
|
&self.entropy
|
|
}
|
|
|
|
/// Get energy budget
|
|
pub fn energy(&self) -> &EnergyBudget {
|
|
&self.energy
|
|
}
|
|
|
|
/// Add energy to the system
|
|
pub fn add_energy(&mut self, amount: f64) {
|
|
self.energy.available += amount;
|
|
}
|
|
|
|
/// Calculate free energy (available for work)
|
|
pub fn free_energy(&self) -> f64 {
|
|
// F = E - T*S
|
|
self.energy.available - self.temperature * self.entropy.current
|
|
}
|
|
|
|
/// Calculate efficiency
|
|
pub fn efficiency(&self) -> f64 {
|
|
if self.energy.consumed == 0.0 {
|
|
return 1.0;
|
|
}
|
|
self.energy.recovered / self.energy.consumed
|
|
}
|
|
|
|
/// Get Carnot efficiency limit
|
|
pub fn carnot_limit(&self, cold_temp: f64) -> f64 {
|
|
if self.temperature <= cold_temp {
|
|
return 0.0;
|
|
}
|
|
1.0 - cold_temp / self.temperature
|
|
}
|
|
|
|
fn record_event(&mut self, event: ThermodynamicEvent) {
|
|
self.history.push_back(event);
|
|
if self.history.len() > 1000 {
|
|
self.history.pop_front();
|
|
}
|
|
}
|
|
|
|
fn current_time(&self) -> u64 {
|
|
std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.map(|d| d.as_secs())
|
|
.unwrap_or(0)
|
|
}
|
|
|
|
/// Get thermodynamic statistics
|
|
pub fn statistics(&self) -> ThermodynamicStatistics {
|
|
ThermodynamicStatistics {
|
|
temperature: self.temperature,
|
|
entropy: self.entropy.current,
|
|
free_energy: self.free_energy(),
|
|
energy_available: self.energy.available,
|
|
efficiency: self.efficiency(),
|
|
phase: self.phase.clone(),
|
|
demon_work: self.demon.work_extracted,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ThoughtEntropy {
|
|
/// Create new entropy tracker
|
|
pub fn new(capacity: f64) -> Self {
|
|
Self {
|
|
current: 0.0,
|
|
production_rate: 0.0,
|
|
capacity,
|
|
components: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
/// Get current entropy
|
|
pub fn current(&self) -> f64 {
|
|
self.current
|
|
}
|
|
|
|
/// Set entropy for a component
|
|
pub fn set_component(&mut self, name: &str, entropy: f64) {
|
|
self.components.insert(name.to_string(), entropy);
|
|
self.current = self.components.values().sum();
|
|
}
|
|
|
|
/// Get entropy headroom
|
|
pub fn headroom(&self) -> f64 {
|
|
(self.capacity - self.current).max(0.0)
|
|
}
|
|
|
|
/// Is at maximum entropy?
|
|
pub fn is_maximum(&self) -> bool {
|
|
self.current >= self.capacity * 0.99
|
|
}
|
|
}
|
|
|
|
impl EnergyBudget {
|
|
/// Create new energy budget
|
|
pub fn new(initial: f64) -> Self {
|
|
Self {
|
|
available: initial,
|
|
consumed: 0.0,
|
|
erasure_cost: 0.0,
|
|
recovered: 0.0,
|
|
}
|
|
}
|
|
|
|
/// Get available energy
|
|
pub fn available(&self) -> f64 {
|
|
self.available
|
|
}
|
|
|
|
/// Get total consumed
|
|
pub fn consumed(&self) -> f64 {
|
|
self.consumed
|
|
}
|
|
}
|
|
|
|
impl MaxwellDemon {
|
|
/// Create new Maxwell's demon
|
|
pub fn new(capacity: usize) -> Self {
|
|
Self {
|
|
memory: Vec::with_capacity(capacity),
|
|
capacity,
|
|
work_extracted: 0.0,
|
|
information_cost: 0.0,
|
|
active: true,
|
|
}
|
|
}
|
|
|
|
/// Activate demon
|
|
pub fn activate(&mut self) {
|
|
self.active = true;
|
|
}
|
|
|
|
/// Deactivate demon
|
|
pub fn deactivate(&mut self) {
|
|
self.active = false;
|
|
}
|
|
|
|
/// Get work extracted
|
|
pub fn work_extracted(&self) -> f64 {
|
|
self.work_extracted
|
|
}
|
|
|
|
/// Get net work (accounting for erasure)
|
|
pub fn net_work(&self) -> f64 {
|
|
self.work_extracted - self.information_cost
|
|
}
|
|
|
|
/// Memory usage fraction
|
|
pub fn memory_usage(&self) -> f64 {
|
|
self.memory.len() as f64 / self.capacity as f64
|
|
}
|
|
}
|
|
|
|
/// Result of erasure operation
|
|
#[derive(Debug, Clone)]
|
|
pub struct ErasureResult {
|
|
pub success: bool,
|
|
pub bits_erased: usize,
|
|
pub energy_cost: f64,
|
|
pub entropy_increase: f64,
|
|
}
|
|
|
|
/// Result of measurement
|
|
#[derive(Debug, Clone)]
|
|
pub struct MeasurementResult {
|
|
pub information_gained: f64,
|
|
pub entropy_cost: f64,
|
|
pub energy_cost: f64,
|
|
}
|
|
|
|
/// Result of demon operation
|
|
#[derive(Debug, Clone)]
|
|
pub struct DemonResult {
|
|
pub work_extracted: f64,
|
|
pub memory_used: usize,
|
|
pub erasure_cost: f64,
|
|
pub net_work: f64,
|
|
}
|
|
|
|
/// Thermodynamic statistics
|
|
#[derive(Debug, Clone)]
|
|
pub struct ThermodynamicStatistics {
|
|
pub temperature: f64,
|
|
pub entropy: f64,
|
|
pub free_energy: f64,
|
|
pub energy_available: f64,
|
|
pub efficiency: f64,
|
|
pub phase: CognitivePhase,
|
|
pub demon_work: f64,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_thermodynamics_creation() {
|
|
let thermo = CognitiveThermodynamics::new(300.0);
|
|
assert_eq!(thermo.measure_temperature(), 300.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_landauer_cost() {
|
|
let thermo = CognitiveThermodynamics::new(300.0);
|
|
|
|
let cost_1bit = thermo.landauer_cost(1);
|
|
let cost_2bits = thermo.landauer_cost(2);
|
|
|
|
// Cost should scale linearly
|
|
assert!((cost_2bits - 2.0 * cost_1bit).abs() < 0.001);
|
|
}
|
|
|
|
#[test]
|
|
fn test_erasure() {
|
|
let mut thermo = CognitiveThermodynamics::new(300.0);
|
|
// Add enough energy for the erasure to succeed
|
|
thermo.add_energy(10000.0);
|
|
let initial_energy = thermo.energy().available();
|
|
|
|
let result = thermo.erase(10);
|
|
|
|
assert!(result.success);
|
|
assert_eq!(result.bits_erased, 10);
|
|
assert!(thermo.energy().available() < initial_energy);
|
|
assert!(thermo.entropy().current() > 0.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_reversible_computation() {
|
|
let mut thermo = CognitiveThermodynamics::new(300.0);
|
|
|
|
let input = 5;
|
|
let output = thermo.reversible_compute(
|
|
input,
|
|
|x| x * 2, // forward
|
|
|x| x / 2, // backward
|
|
);
|
|
|
|
assert_eq!(output, 10);
|
|
// Reversible computation shouldn't increase entropy significantly
|
|
}
|
|
|
|
#[test]
|
|
fn test_phase_transitions() {
|
|
let mut thermo = CognitiveThermodynamics::new(300.0);
|
|
|
|
// Start in Fluid phase
|
|
assert_eq!(*thermo.phase(), CognitivePhase::Fluid);
|
|
|
|
// Cool down
|
|
thermo.set_temperature(50.0);
|
|
assert_eq!(*thermo.phase(), CognitivePhase::Crystalline);
|
|
|
|
// Heat up
|
|
thermo.set_temperature(600.0);
|
|
assert_eq!(*thermo.phase(), CognitivePhase::Gaseous);
|
|
|
|
// Extreme cooling
|
|
thermo.set_temperature(5.0);
|
|
assert_eq!(*thermo.phase(), CognitivePhase::Condensate);
|
|
}
|
|
|
|
#[test]
|
|
fn test_maxwell_demon() {
|
|
let mut thermo = CognitiveThermodynamics::new(300.0);
|
|
|
|
let result = thermo.run_demon(10);
|
|
|
|
assert!(result.work_extracted > 0.0);
|
|
assert_eq!(result.memory_used, 10);
|
|
}
|
|
|
|
#[test]
|
|
fn test_free_energy() {
|
|
let thermo = CognitiveThermodynamics::new(300.0);
|
|
let free = thermo.free_energy();
|
|
|
|
// Free energy should be positive initially
|
|
assert!(free > 0.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_entropy_components() {
|
|
let mut entropy = ThoughtEntropy::new(100.0);
|
|
|
|
entropy.set_component("perception", 10.0);
|
|
entropy.set_component("memory", 15.0);
|
|
|
|
assert_eq!(entropy.current(), 25.0);
|
|
assert!(!entropy.is_maximum());
|
|
}
|
|
|
|
#[test]
|
|
fn test_demon_memory_limit() {
|
|
let mut thermo = CognitiveThermodynamics::new(300.0);
|
|
|
|
// Fill demon memory
|
|
for _ in 0..10 {
|
|
thermo.run_demon(10);
|
|
}
|
|
|
|
// Demon should need to erase memory eventually
|
|
let usage = thermo.demon.memory_usage();
|
|
assert!(usage > 0.0);
|
|
}
|
|
}
|