use serde::{Deserialize, Serialize};
use std::collections::{HashMap, VecDeque};
#[derive(Debug)]
pub struct CognitiveThermodynamics {
temperature: f64,
entropy: ThoughtEntropy,
energy: EnergyBudget,
demon: MaxwellDemon,
phase: CognitivePhase,
history: VecDeque<ThermodynamicEvent>,
k_b: f64,
}
#[derive(Debug)]
pub struct ThoughtEntropy {
current: f64,
production_rate: f64,
capacity: f64,
components: HashMap<String, f64>,
}
#[derive(Debug, Clone)]
pub struct EnergyBudget {
available: f64,
consumed: f64,
erasure_cost: f64,
recovered: f64,
}
#[derive(Debug)]
pub struct MaxwellDemon {
memory: Vec<bool>,
capacity: usize,
work_extracted: f64,
information_cost: f64,
active: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CognitivePhase {
Crystalline,
Fluid,
Gaseous,
Critical,
Condensate,
}
#[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 {
pub fn new(temperature: f64) -> Self {
Self {
temperature: temperature.max(0.001), 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, }
}
pub fn measure_temperature(&self) -> f64 {
self.temperature
}
pub fn set_temperature(&mut self, temp: f64) {
let old_temp = self.temperature;
self.temperature = temp.max(0.001);
self.check_phase_transition(old_temp, self.temperature);
}
fn check_phase_transition(&mut self, old: f64, new: f64) {
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 {
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(),
});
}
}
pub fn landauer_cost(&self, bits: usize) -> f64 {
bits as f64 * self.k_b * self.temperature * std::f64::consts::LN_2
}
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,
};
}
self.energy.available -= cost;
self.energy.consumed += cost;
self.energy.erasure_cost += cost;
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,
}
}
pub fn reversible_compute<T>(
&mut self,
input: T,
forward: impl Fn(T) -> T,
_backward: impl Fn(T) -> T,
) -> T {
self.record_event(ThermodynamicEvent {
event_type: EventType::Computation,
entropy_change: 0.0, energy_change: 0.0,
timestamp: self.current_time(),
});
forward(input)
}
pub fn measure(&mut self, precision_bits: usize) -> MeasurementResult {
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,
}
}
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 {
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,
};
}
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, energy_change: total_work,
timestamp: self.current_time(),
});
DemonResult {
work_extracted: total_work,
memory_used: ops,
erasure_cost: 0.0,
net_work: total_work,
}
}
pub fn phase(&self) -> &CognitivePhase {
&self.phase
}
pub fn entropy(&self) -> &ThoughtEntropy {
&self.entropy
}
pub fn energy(&self) -> &EnergyBudget {
&self.energy
}
pub fn add_energy(&mut self, amount: f64) {
self.energy.available += amount;
}
pub fn free_energy(&self) -> f64 {
self.energy.available - self.temperature * self.entropy.current
}
pub fn efficiency(&self) -> f64 {
if self.energy.consumed == 0.0 {
return 1.0;
}
self.energy.recovered / self.energy.consumed
}
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)
}
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 {
pub fn new(capacity: f64) -> Self {
Self {
current: 0.0,
production_rate: 0.0,
capacity,
components: HashMap::new(),
}
}
pub fn current(&self) -> f64 {
self.current
}
pub fn set_component(&mut self, name: &str, entropy: f64) {
self.components.insert(name.to_string(), entropy);
self.current = self.components.values().sum();
}
pub fn headroom(&self) -> f64 {
(self.capacity - self.current).max(0.0)
}
pub fn is_maximum(&self) -> bool {
self.current >= self.capacity * 0.99
}
}
impl EnergyBudget {
pub fn new(initial: f64) -> Self {
Self {
available: initial,
consumed: 0.0,
erasure_cost: 0.0,
recovered: 0.0,
}
}
pub fn available(&self) -> f64 {
self.available
}
pub fn consumed(&self) -> f64 {
self.consumed
}
}
impl MaxwellDemon {
pub fn new(capacity: usize) -> Self {
Self {
memory: Vec::with_capacity(capacity),
capacity,
work_extracted: 0.0,
information_cost: 0.0,
active: true,
}
}
pub fn activate(&mut self) {
self.active = true;
}
pub fn deactivate(&mut self) {
self.active = false;
}
pub fn work_extracted(&self) -> f64 {
self.work_extracted
}
pub fn net_work(&self) -> f64 {
self.work_extracted - self.information_cost
}
pub fn memory_usage(&self) -> f64 {
self.memory.len() as f64 / self.capacity as f64
}
}
#[derive(Debug, Clone)]
pub struct ErasureResult {
pub success: bool,
pub bits_erased: usize,
pub energy_cost: f64,
pub entropy_increase: f64,
}
#[derive(Debug, Clone)]
pub struct MeasurementResult {
pub information_gained: f64,
pub entropy_cost: f64,
pub energy_cost: f64,
}
#[derive(Debug, Clone)]
pub struct DemonResult {
pub work_extracted: f64,
pub memory_used: usize,
pub erasure_cost: f64,
pub net_work: f64,
}
#[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);
assert!((cost_2bits - 2.0 * cost_1bit).abs() < 0.001);
}
#[test]
fn test_erasure() {
let mut thermo = CognitiveThermodynamics::new(300.0);
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, |x| x / 2, );
assert_eq!(output, 10);
}
#[test]
fn test_phase_transitions() {
let mut thermo = CognitiveThermodynamics::new(300.0);
assert_eq!(*thermo.phase(), CognitivePhase::Fluid);
thermo.set_temperature(50.0);
assert_eq!(*thermo.phase(), CognitivePhase::Crystalline);
thermo.set_temperature(600.0);
assert_eq!(*thermo.phase(), CognitivePhase::Gaseous);
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();
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);
for _ in 0..10 {
thermo.run_demon(10);
}
let usage = thermo.demon.memory_usage();
assert!(usage > 0.0);
}
}