611 lines
19 KiB
Rust
611 lines
19 KiB
Rust
//! # Exotic MinCut Examples - Comprehensive Benchmarks
|
|
//!
|
|
//! This benchmark suite measures performance across all exotic use cases:
|
|
//! - Temporal Attractors
|
|
//! - Strange Loop Swarms
|
|
//! - Causal Discovery
|
|
//! - Time Crystal Coordination
|
|
//! - Morphogenetic Networks
|
|
//! - Neural Graph Optimization
|
|
//!
|
|
//! Run with: `cargo run --release -p mincut-benchmarks`
|
|
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::time::{Duration, Instant};
|
|
|
|
// ============================================================================
|
|
// BENCHMARK INFRASTRUCTURE
|
|
// ============================================================================
|
|
|
|
/// Benchmark result with statistics
|
|
#[derive(Debug, Clone)]
|
|
struct BenchResult {
|
|
name: String,
|
|
iterations: usize,
|
|
total_time: Duration,
|
|
min_time: Duration,
|
|
max_time: Duration,
|
|
avg_time: Duration,
|
|
throughput: f64, // operations per second
|
|
}
|
|
|
|
impl BenchResult {
|
|
fn print(&self) {
|
|
println!(" {} ({} iterations)", self.name, self.iterations);
|
|
println!(" Total: {:?}", self.total_time);
|
|
println!(" Average: {:?}", self.avg_time);
|
|
println!(" Min: {:?}", self.min_time);
|
|
println!(" Max: {:?}", self.max_time);
|
|
println!(" Throughput: {:.2} ops/sec", self.throughput);
|
|
println!();
|
|
}
|
|
}
|
|
|
|
/// Run a benchmark with the given closure
|
|
fn bench<F>(name: &str, iterations: usize, mut f: F) -> BenchResult
|
|
where
|
|
F: FnMut() -> (),
|
|
{
|
|
let mut times = Vec::with_capacity(iterations);
|
|
|
|
// Warmup
|
|
for _ in 0..3 {
|
|
f();
|
|
}
|
|
|
|
// Actual benchmark
|
|
for _ in 0..iterations {
|
|
let start = Instant::now();
|
|
f();
|
|
times.push(start.elapsed());
|
|
}
|
|
|
|
let total: Duration = times.iter().sum();
|
|
let min = *times.iter().min().unwrap();
|
|
let max = *times.iter().max().unwrap();
|
|
let avg = total / iterations as u32;
|
|
let throughput = iterations as f64 / total.as_secs_f64();
|
|
|
|
BenchResult {
|
|
name: name.to_string(),
|
|
iterations,
|
|
total_time: total,
|
|
min_time: min,
|
|
max_time: max,
|
|
avg_time: avg,
|
|
throughput,
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// SIMPLE GRAPH IMPLEMENTATION FOR BENCHMARKS
|
|
// ============================================================================
|
|
|
|
/// Lightweight graph for benchmarking
|
|
#[derive(Clone)]
|
|
struct BenchGraph {
|
|
vertices: HashSet<u64>,
|
|
edges: HashMap<(u64, u64), f64>,
|
|
adjacency: HashMap<u64, Vec<u64>>,
|
|
}
|
|
|
|
impl BenchGraph {
|
|
fn new() -> Self {
|
|
Self {
|
|
vertices: HashSet::new(),
|
|
edges: HashMap::new(),
|
|
adjacency: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
fn with_vertices(n: usize) -> Self {
|
|
let mut g = Self::new();
|
|
for i in 0..n as u64 {
|
|
g.vertices.insert(i);
|
|
g.adjacency.insert(i, Vec::new());
|
|
}
|
|
g
|
|
}
|
|
|
|
fn add_edge(&mut self, u: u64, v: u64, weight: f64) {
|
|
if !self.vertices.contains(&u) {
|
|
self.vertices.insert(u);
|
|
self.adjacency.insert(u, Vec::new());
|
|
}
|
|
if !self.vertices.contains(&v) {
|
|
self.vertices.insert(v);
|
|
self.adjacency.insert(v, Vec::new());
|
|
}
|
|
|
|
let key = if u < v { (u, v) } else { (v, u) };
|
|
self.edges.insert(key, weight);
|
|
self.adjacency.get_mut(&u).unwrap().push(v);
|
|
self.adjacency.get_mut(&v).unwrap().push(u);
|
|
}
|
|
|
|
fn remove_edge(&mut self, u: u64, v: u64) {
|
|
let key = if u < v { (u, v) } else { (v, u) };
|
|
self.edges.remove(&key);
|
|
if let Some(adj) = self.adjacency.get_mut(&u) {
|
|
adj.retain(|&x| x != v);
|
|
}
|
|
if let Some(adj) = self.adjacency.get_mut(&v) {
|
|
adj.retain(|&x| x != u);
|
|
}
|
|
}
|
|
|
|
fn vertex_count(&self) -> usize {
|
|
self.vertices.len()
|
|
}
|
|
|
|
fn edge_count(&self) -> usize {
|
|
self.edges.len()
|
|
}
|
|
|
|
fn degree(&self, v: u64) -> usize {
|
|
self.adjacency.get(&v).map(|a| a.len()).unwrap_or(0)
|
|
}
|
|
|
|
/// Simple min-cut approximation using minimum degree
|
|
fn approx_mincut(&self) -> f64 {
|
|
self.vertices
|
|
.iter()
|
|
.map(|&v| self.degree(v) as f64)
|
|
.min_by(|a, b| a.partial_cmp(b).unwrap())
|
|
.unwrap_or(0.0)
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: TEMPORAL ATTRACTORS
|
|
// ============================================================================
|
|
|
|
fn bench_temporal_attractors() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " TEMPORAL ATTRACTORS ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark attractor evolution
|
|
for size in [100, 500, 1000, 5000] {
|
|
let result = bench(&format!("evolve_step (n={})", size), 100, || {
|
|
let mut graph = BenchGraph::with_vertices(size);
|
|
|
|
// Create initial ring
|
|
for i in 0..size as u64 {
|
|
graph.add_edge(i, (i + 1) % size as u64, 1.0);
|
|
}
|
|
|
|
// Evolve toward optimal attractor
|
|
for _ in 0..10 {
|
|
let cut = graph.approx_mincut();
|
|
if cut < 3.0 {
|
|
// Strengthen weak points
|
|
let weak_v = (0..size as u64).min_by_key(|&v| graph.degree(v)).unwrap();
|
|
let target = (weak_v + size as u64 / 2) % size as u64;
|
|
graph.add_edge(weak_v, target, 1.0);
|
|
}
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
// Benchmark convergence detection
|
|
let result = bench("convergence_detection (100 samples)", 1000, || {
|
|
let samples: Vec<f64> = (0..100).map(|i| 5.0 + (i as f64 * 0.01)).collect();
|
|
let _variance: f64 = {
|
|
let mean = samples.iter().sum::<f64>() / samples.len() as f64;
|
|
samples.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / samples.len() as f64
|
|
};
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: STRANGE LOOP SWARMS
|
|
// ============================================================================
|
|
|
|
fn bench_strange_loop() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " STRANGE LOOP SWARMS ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark self-observation
|
|
for size in [100, 500, 1000] {
|
|
let result = bench(&format!("self_observe (n={})", size), 100, || {
|
|
let mut graph = BenchGraph::with_vertices(size);
|
|
|
|
// Create mesh
|
|
for i in 0..size as u64 {
|
|
for j in (i + 1)..std::cmp::min(i + 5, size as u64) {
|
|
graph.add_edge(i, j, 1.0);
|
|
}
|
|
}
|
|
|
|
// Self-observation cycle
|
|
let _mincut = graph.approx_mincut();
|
|
let _weak_vertices: Vec<u64> =
|
|
(0..size as u64).filter(|&v| graph.degree(v) < 3).collect();
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
// Benchmark feedback loop iteration
|
|
let result = bench("feedback_loop_iteration (n=500)", 100, || {
|
|
let mut graph = BenchGraph::with_vertices(500);
|
|
|
|
// Initialize
|
|
for i in 0..500u64 {
|
|
graph.add_edge(i, (i + 1) % 500, 1.0);
|
|
}
|
|
|
|
// 10 feedback iterations
|
|
for _ in 0..10 {
|
|
// Observe
|
|
let cut = graph.approx_mincut();
|
|
|
|
// Decide
|
|
if cut < 3.0 {
|
|
// Strengthen
|
|
let v = (0..500u64).min_by_key(|&v| graph.degree(v)).unwrap();
|
|
graph.add_edge(v, (v + 250) % 500, 1.0);
|
|
}
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: CAUSAL DISCOVERY
|
|
// ============================================================================
|
|
|
|
fn bench_causal_discovery() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " CAUSAL DISCOVERY ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark event tracking
|
|
let result = bench("event_tracking (1000 events)", 100, || {
|
|
let mut events: Vec<(Instant, &str, f64)> = Vec::with_capacity(1000);
|
|
let base = Instant::now();
|
|
|
|
for i in 0..1000 {
|
|
events.push((
|
|
base,
|
|
if i % 3 == 0 {
|
|
"edge_cut"
|
|
} else {
|
|
"mincut_change"
|
|
},
|
|
i as f64,
|
|
));
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
// Benchmark causality detection
|
|
for event_count in [100, 500, 1000] {
|
|
let result = bench(
|
|
&format!("causality_detection (n={})", event_count),
|
|
50,
|
|
|| {
|
|
// Simulate event pairs
|
|
let events: Vec<(u64, u64)> = (0..event_count)
|
|
.map(|i| (i as u64, i as u64 + 50))
|
|
.collect();
|
|
|
|
// Find causal relationships
|
|
let mut causal_pairs: HashMap<(&str, &str), Vec<u64>> = HashMap::new();
|
|
|
|
for (t1, t2) in &events {
|
|
let delay = t2 - t1;
|
|
if delay < 200 {
|
|
causal_pairs
|
|
.entry(("A", "B"))
|
|
.or_insert_with(Vec::new)
|
|
.push(delay);
|
|
}
|
|
}
|
|
|
|
// Calculate statistics
|
|
for (_pair, delays) in &causal_pairs {
|
|
let _avg: f64 = delays.iter().sum::<u64>() as f64 / delays.len() as f64;
|
|
}
|
|
},
|
|
);
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: TIME CRYSTAL COORDINATION
|
|
// ============================================================================
|
|
|
|
fn bench_time_crystal() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " TIME CRYSTAL COORDINATION ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark phase transitions
|
|
for size in [50, 100, 500] {
|
|
let result = bench(&format!("phase_transition (n={})", size), 100, || {
|
|
let mut graph = BenchGraph::with_vertices(size);
|
|
|
|
// Phase 1: Ring
|
|
for i in 0..size as u64 {
|
|
graph.add_edge(i, (i + 1) % size as u64, 1.0);
|
|
}
|
|
let _ring_cut = graph.approx_mincut();
|
|
|
|
// Phase 2: Star (clear and rebuild)
|
|
graph.edges.clear();
|
|
for adj in graph.adjacency.values_mut() {
|
|
adj.clear();
|
|
}
|
|
for i in 1..size as u64 {
|
|
graph.add_edge(0, i, 1.0);
|
|
}
|
|
let _star_cut = graph.approx_mincut();
|
|
|
|
// Phase 3: Mesh
|
|
graph.edges.clear();
|
|
for adj in graph.adjacency.values_mut() {
|
|
adj.clear();
|
|
}
|
|
for i in 0..size as u64 {
|
|
for j in (i + 1)..std::cmp::min(i + 4, size as u64) {
|
|
graph.add_edge(i, j, 1.0);
|
|
}
|
|
}
|
|
let _mesh_cut = graph.approx_mincut();
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
// Benchmark stability verification
|
|
let result = bench("stability_verification (9 phases)", 200, || {
|
|
let expected: Vec<f64> = vec![2.0, 1.0, 6.0, 2.0, 1.0, 6.0, 2.0, 1.0, 6.0];
|
|
let actual: Vec<f64> = vec![2.0, 1.0, 6.0, 2.0, 1.0, 6.0, 2.0, 1.0, 6.0];
|
|
|
|
let _matches: usize = expected
|
|
.iter()
|
|
.zip(&actual)
|
|
.filter(|(e, a)| (*e - *a).abs() < 0.5)
|
|
.count();
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: MORPHOGENETIC NETWORKS
|
|
// ============================================================================
|
|
|
|
fn bench_morphogenetic() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " MORPHOGENETIC NETWORKS ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark growth cycle
|
|
for initial_size in [10, 50, 100] {
|
|
let result = bench(
|
|
&format!("growth_cycle (start={})", initial_size),
|
|
50,
|
|
|| {
|
|
let mut graph = BenchGraph::with_vertices(initial_size);
|
|
let mut signals: HashMap<u64, f64> = HashMap::new();
|
|
|
|
// Initialize signals
|
|
for i in 0..initial_size as u64 {
|
|
signals.insert(i, 1.0);
|
|
}
|
|
|
|
// Create initial connections
|
|
for i in 0..initial_size as u64 {
|
|
graph.add_edge(i, (i + 1) % initial_size as u64, 1.0);
|
|
}
|
|
|
|
// 15 growth cycles
|
|
let mut next_id = initial_size as u64;
|
|
for _ in 0..15 {
|
|
// Diffuse signals
|
|
let mut new_signals = signals.clone();
|
|
for (&v, &sig) in &signals {
|
|
for &neighbor in graph.adjacency.get(&v).unwrap_or(&vec![]) {
|
|
*new_signals.entry(neighbor).or_insert(0.0) += sig * 0.1;
|
|
}
|
|
}
|
|
|
|
// Decay
|
|
for sig in new_signals.values_mut() {
|
|
*sig *= 0.9;
|
|
}
|
|
signals = new_signals;
|
|
|
|
// Growth rules
|
|
for v in 0..next_id {
|
|
if !graph.vertices.contains(&v) {
|
|
continue;
|
|
}
|
|
|
|
let sig = signals.get(&v).copied().unwrap_or(0.0);
|
|
let deg = graph.degree(v);
|
|
|
|
if sig > 0.5 && deg < 2 {
|
|
// Spawn
|
|
graph.add_edge(v, next_id, 1.0);
|
|
signals.insert(next_id, sig * 0.5);
|
|
next_id += 1;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
);
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: NEURAL GRAPH OPTIMIZER
|
|
// ============================================================================
|
|
|
|
fn bench_neural_optimizer() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " NEURAL GRAPH OPTIMIZER ");
|
|
let mut results = Vec::new();
|
|
|
|
// Benchmark feature extraction
|
|
for size in [50, 100, 500] {
|
|
let result = bench(&format!("feature_extraction (n={})", size), 100, || {
|
|
let mut graph = BenchGraph::with_vertices(size);
|
|
for i in 0..size as u64 {
|
|
graph.add_edge(i, (i + 1) % size as u64, 1.0);
|
|
}
|
|
|
|
// Extract features
|
|
let _features: Vec<f64> = vec![
|
|
graph.vertex_count() as f64 / 1000.0,
|
|
graph.edge_count() as f64 / 5000.0,
|
|
graph.approx_mincut() / 10.0,
|
|
graph.edges.values().sum::<f64>() / graph.edge_count() as f64,
|
|
];
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
// Benchmark neural forward pass (simulated)
|
|
let result = bench("neural_forward_pass (4 layers)", 1000, || {
|
|
// Simulate 4-layer network
|
|
let input = vec![0.5, 0.3, 0.2, 0.8];
|
|
let mut activation = input;
|
|
|
|
for layer in 0..4 {
|
|
let mut output = vec![0.0; 4];
|
|
for i in 0..4 {
|
|
for j in 0..4 {
|
|
output[i] += activation[j] * ((layer * 4 + i + j) as f64 * 0.1).sin();
|
|
}
|
|
output[i] = output[i].max(0.0); // ReLU
|
|
}
|
|
activation = output;
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
// Benchmark optimization step
|
|
let result = bench("optimization_step (10 candidates)", 100, || {
|
|
let mut best_score = 0.0f64;
|
|
|
|
for candidate in 0..10 {
|
|
// Simulate action evaluation
|
|
let score = (candidate as f64 * 0.1).sin() + 0.5;
|
|
if score > best_score {
|
|
best_score = score;
|
|
}
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// BENCHMARK: SCALING ANALYSIS
|
|
// ============================================================================
|
|
|
|
fn bench_scaling() -> Vec<BenchResult> {
|
|
println!("\n{:=^60}", " SCALING ANALYSIS ");
|
|
let mut results = Vec::new();
|
|
|
|
// Test how performance scales with graph size
|
|
for size in [100, 500, 1000, 5000, 10000] {
|
|
let result = bench(&format!("full_pipeline (n={})", size), 10, || {
|
|
let mut graph = BenchGraph::with_vertices(size);
|
|
|
|
// Build graph
|
|
for i in 0..size as u64 {
|
|
graph.add_edge(i, (i + 1) % size as u64, 1.0);
|
|
if i % 10 == 0 {
|
|
graph.add_edge(i, (i + size as u64 / 2) % size as u64, 1.0);
|
|
}
|
|
}
|
|
|
|
// Run analysis
|
|
let _cut = graph.approx_mincut();
|
|
|
|
// Simulate evolution
|
|
for _ in 0..5 {
|
|
let cut = graph.approx_mincut();
|
|
if cut < 3.0 {
|
|
let v = (0..size as u64).min_by_key(|&v| graph.degree(v)).unwrap();
|
|
graph.add_edge(v, (v + 1) % size as u64, 1.0);
|
|
}
|
|
}
|
|
});
|
|
result.print();
|
|
results.push(result);
|
|
}
|
|
|
|
results
|
|
}
|
|
|
|
// ============================================================================
|
|
// MAIN
|
|
// ============================================================================
|
|
|
|
fn main() {
|
|
println!("╔════════════════════════════════════════════════════════════╗");
|
|
println!("║ EXOTIC MINCUT EXAMPLES - BENCHMARK SUITE ║");
|
|
println!("║ Measuring Performance Across All Use Cases ║");
|
|
println!("╚════════════════════════════════════════════════════════════╝");
|
|
|
|
let mut all_results = Vec::new();
|
|
|
|
all_results.extend(bench_temporal_attractors());
|
|
all_results.extend(bench_strange_loop());
|
|
all_results.extend(bench_causal_discovery());
|
|
all_results.extend(bench_time_crystal());
|
|
all_results.extend(bench_morphogenetic());
|
|
all_results.extend(bench_neural_optimizer());
|
|
all_results.extend(bench_scaling());
|
|
|
|
// Summary
|
|
println!("\n{:=^60}", " SUMMARY ");
|
|
println!("\nTop 5 Fastest Operations:");
|
|
let mut sorted = all_results.clone();
|
|
sorted.sort_by(|a, b| a.avg_time.cmp(&b.avg_time));
|
|
for result in sorted.iter().take(5) {
|
|
println!(" {:50} {:>10?}", result.name, result.avg_time);
|
|
}
|
|
|
|
println!("\nTop 5 Highest Throughput:");
|
|
sorted.sort_by(|a, b| b.throughput.partial_cmp(&a.throughput).unwrap());
|
|
for result in sorted.iter().take(5) {
|
|
println!(" {:50} {:>12.0} ops/sec", result.name, result.throughput);
|
|
}
|
|
|
|
println!("\nScaling Analysis:");
|
|
for result in all_results
|
|
.iter()
|
|
.filter(|r| r.name.starts_with("full_pipeline"))
|
|
{
|
|
println!(" {:50} {:>10?}", result.name, result.avg_time);
|
|
}
|
|
|
|
println!("\n✅ Benchmark suite complete!");
|
|
}
|