Feynman Reactor Simulator

import React, { useState, useEffect, useRef } from 'react'; export default function FeynmanPathIntegralSimulator() { // State for all simulations const [numPaths, setNumPaths] = useState(20); const [timeEvolution, setTimeEvolution] = useState(0); const [measurementStrength, setMeasurementStrength] = useState(0.5); const [numDiagnostics, setNumDiagnostics] = useState(5); const [isAnimating, setIsAnimating] = useState(true); const [showPhases, setShowPhases] = useState(true); // Canvas refs const pathCanvasRef = useRef(null); const phaseCanvasRef = useRef(null); const measurementCanvasRef = useRef(null); // Animation loop useEffect(() => { if (!isAnimating) return; const interval = setInterval(() => { setTimeEvolution(t => (t + 0.05) % (2 * Math.PI)); }, 50); return () => clearInterval(interval); }, [isAnimating]); // Draw path integral visualization useEffect(() => { const canvas = pathCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; // Clear ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); // Draw all possible paths const startX = 50; const endX = width - 50; const startY = height / 2; // Calculate amplitudes for each path const paths = []; for (let i = 0; i < numPaths; i++) { const pathIndex = i - numPaths / 2; const amplitude = Math.exp(-0.1 * pathIndex * pathIndex); // Gaussian const phase = pathIndex * 0.5 + timeEvolution; paths.push({ amplitude, phase, pathIndex }); } // Draw paths paths.forEach(({ amplitude, phase, pathIndex }) => { const alpha = amplitude * 0.5; const color = `rgba(0, 255, 100, ${alpha})`; ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(startX, startY); // Draw wavy path for (let x = startX; x <= endX; x += 5) { const progress = (x - startX) / (endX - startX); const yOffset = pathIndex * 30 * Math.sin(progress * Math.PI * 4 + phase); ctx.lineTo(x, startY + yOffset); } ctx.stroke(); // Draw phase arrow at end if enabled if (showPhases) { const endY = startY + pathIndex * 30 * Math.sin(Math.PI * 4 + phase); const arrowLength = amplitude * 30; const arrowX = endX + arrowLength * Math.cos(phase); const arrowY = endY + arrowLength * Math.sin(phase); ctx.strokeStyle = `rgba(255, 255, 0, ${amplitude})`; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(endX, endY); ctx.lineTo(arrowX, arrowY); ctx.stroke(); // Arrow head ctx.fillStyle = `rgba(255, 255, 0, ${amplitude})`; ctx.beginPath(); ctx.arc(arrowX, arrowY, 4, 0, Math.PI * 2); ctx.fill(); } }); // Calculate total amplitude (sum of all contributions) let totalReal = 0; let totalImag = 0; paths.forEach(({ amplitude, phase }) => { totalReal += amplitude * Math.cos(phase); totalImag += amplitude * Math.sin(phase); }); const totalAmplitude = Math.sqrt(totalReal * totalReal + totalImag * totalImag); const totalPhase = Math.atan2(totalImag, totalReal); // Draw total amplitude arrow const centerX = width / 2; const centerY = height - 80; const totalArrowLength = totalAmplitude * 50; const totalArrowX = centerX + totalArrowLength * Math.cos(totalPhase); const totalArrowY = centerY + totalArrowLength * Math.sin(totalPhase); ctx.strokeStyle = '#00ffff'; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.lineTo(totalArrowX, totalArrowY); ctx.stroke(); ctx.fillStyle = '#00ffff'; ctx.beginPath(); ctx.arc(totalArrowX, totalArrowY, 6, 0, Math.PI * 2); ctx.fill(); // Labels ctx.fillStyle = '#00ff00'; ctx.font = '14px monospace'; ctx.fillText('All possible paths', 10, 30); ctx.fillStyle = '#ffff00'; ctx.fillText('Phase arrows', 10, 50); ctx.fillStyle = '#00ffff'; ctx.fillText(`Total amplitude: ${totalAmplitude.toFixed(2)}`, centerX - 80, height - 20); }, [numPaths, timeEvolution, showPhases]); // Draw phase space diagram useEffect(() => { const canvas = phaseCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); // Draw complex plane const centerX = width / 2; const centerY = height / 2; const scale = 80; // Axes ctx.strokeStyle = '#333'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(0, centerY); ctx.lineTo(width, centerY); ctx.moveTo(centerX, 0); ctx.lineTo(centerX, height); ctx.stroke(); // Draw unit circle ctx.strokeStyle = 'rgba(100, 100, 100, 0.3)'; ctx.beginPath(); ctx.arc(centerX, centerY, scale, 0, Math.PI * 2); ctx.stroke(); // Draw all path contributions const paths = []; for (let i = 0; i < numPaths; i++) { const pathIndex = i - numPaths / 2; const amplitude = Math.exp(-0.1 * pathIndex * pathIndex); const phase = pathIndex * 0.5 + timeEvolution; const x = centerX + amplitude * scale * Math.cos(phase); const y = centerY + amplitude * scale * Math.sin(phase); // Draw vector ctx.strokeStyle = `rgba(0, 255, 100, ${amplitude * 0.5})`; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.lineTo(x, y); ctx.stroke(); // Draw point ctx.fillStyle = `rgba(0, 255, 100, ${amplitude})`; ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2); ctx.fill(); paths.push({ amplitude, phase }); } // Calculate and draw sum let sumReal = 0; let sumImag = 0; paths.forEach(({ amplitude, phase }) => { sumReal += amplitude * Math.cos(phase); sumImag += amplitude * Math.sin(phase); }); const sumX = centerX + sumReal * scale; const sumY = centerY + sumImag * scale; ctx.strokeStyle = '#00ffff'; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.lineTo(sumX, sumY); ctx.stroke(); ctx.fillStyle = '#00ffff'; ctx.beginPath(); ctx.arc(sumX, sumY, 6, 0, Math.PI * 2); ctx.fill(); // Labels ctx.fillStyle = '#00ff00'; ctx.font = '12px monospace'; ctx.fillText('Re', width - 30, centerY - 10); ctx.fillText('Im', centerX + 10, 20); ctx.fillStyle = '#00ffff'; ctx.fillText('Σ(paths)', sumX + 10, sumY - 10); }, [numPaths, timeEvolution]); // Draw measurement effect useEffect(() => { const canvas = measurementCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); const centerY = height / 2; // Natural sigma const sigma0 = 0.5; // mm const alpha = 0.1; // mm^2 per diagnostic const effectiveSigma = Math.sqrt(sigma0 * sigma0 + alpha * numDiagnostics); // Draw probability distribution (natural) ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)'; ctx.fillStyle = 'rgba(255, 0, 0, 0.1)'; ctx.lineWidth = 2; ctx.beginPath(); for (let x = 0; x < width; x++) { const position = (x - width / 2) / 100; // Convert to mm const prob = Math.exp(-position * position / (2 * sigma0 * sigma0)); const y = centerY - prob * 150; if (x === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.lineTo(width, centerY); ctx.lineTo(0, centerY); ctx.closePath(); ctx.fill(); ctx.stroke(); // Draw probability distribution (with measurements) ctx.strokeStyle = 'rgba(255, 255, 0, 0.8)'; ctx.fillStyle = 'rgba(255, 255, 0, 0.1)'; ctx.lineWidth = 2; ctx.beginPath(); for (let x = 0; x < width; x++) { const position = (x - width / 2) / 100; const prob = Math.exp(-position * position / (2 * effectiveSigma * effectiveSigma)); const y = centerY - prob * 150; if (x === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.lineTo(width, centerY); ctx.lineTo(0, centerY); ctx.closePath(); ctx.fill(); ctx.stroke(); // Draw measurement collapses for (let i = 0; i < numDiagnostics; i++) { const x = (i + 1) * width / (numDiagnostics + 1); const measurementY = centerY + (Math.sin(timeEvolution * 2 + i) * measurementStrength * 100); ctx.strokeStyle = 'rgba(0, 200, 255, 0.6)'; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(x, centerY); ctx.lineTo(x, measurementY); ctx.stroke(); ctx.fillStyle = 'rgba(0, 200, 255, 0.8)'; ctx.beginPath(); ctx.arc(x, measurementY, 5, 0, Math.PI * 2); ctx.fill(); } // Labels ctx.fillStyle = '#ff0000'; ctx.font = '14px monospace'; ctx.fillText(`Natural σ = ${sigma0.toFixed(2)} mm`, 10, 30); ctx.fillStyle = '#ffff00'; ctx.fillText(`Measured σ = ${effectiveSigma.toFixed(2)} mm`, 10, 50); ctx.fillStyle = '#00ccff'; ctx.fillText(`N diagnostics = ${numDiagnostics}`, 10, 70); // Draw equation ctx.fillStyle = '#ffffff'; ctx.font = '16px monospace'; ctx.fillText(`σ² = ${sigma0}² + ${alpha}·N = ${(effectiveSigma * effectiveSigma).toFixed(2)}`, width / 2 - 150, height - 20); }, [numDiagnostics, measurementStrength, timeEvolution]); return (

◊ᶠᴱʸᴺᴹᴬᴺ Path Integral Simulator

"The electron does something entirely reasonable - it goes every way at once!"

Interactive visualization of quantum path integrals and measurement back-action

{/* Control Panel */}

Controls

setNumPaths(parseInt(e.target.value))} className="w-full" />
setNumDiagnostics(parseInt(e.target.value))} className="w-full" />
setMeasurementStrength(parseFloat(e.target.value))} className="w-full" />
{/* Visualization 1: Path Integral */}

Path Integral: All Possible Paths

The particle explores EVERY path from start to end. Each path contributes an amplitude (brightness) and phase (yellow arrow). Sum them all → total probability!

{/* Visualization 2: Phase Space */}

Complex Phase Space: Vector Addition

Each path = vector in complex plane. Green vectors = individual paths. Cyan vector = total amplitude (sum of all). Watch them spin and interfere!

{/* Visualization 3: Measurement Effect */}

Measurement Back-Action: σ ∝ √N

Red = natural quantum spread (no measurements). Yellow = with measurements. Blue spikes = each diagnostic collapse. More diagnostics → wider spread!

{/* Physics Explanation */}

The Physics (Feynman's Way)

Path Integrals:

Amplitude to go from A to B = Σ(all paths) exp(iS/ℏ)

Each path has action S. That makes phase rotate. Add all rotating phases → interference → quantum mechanics!

Measurement Collapse:

Before measurement: |ψ⟩ = Σ cₙ|n⟩ (superposition)

After measurement: |ψ⟩ → |n_measured⟩ (collapse)

This collapse COSTS ENERGY. It perturbs the system. More measurements = more perturbation = larger fluctuations!

Why σ ∝ √N:

σ² = σ₀² + α·N

Natural spread (σ₀) + measurement perturbation (α per diagnostic). Each measurement adds variance → total variance grows linearly → standard deviation grows as √N.

The Solution:

STOP MEASURING SO MUCH. Design the machine to be naturally stable. Let the path integral find its own minimum without constant collapse.

{/* Footer */}

"What I cannot create, I do not understand."

— Richard Feynman

◊ᴹᴱᴹᴼᴿʸ⁻ᶜᴼᴹᴾᴸᴱᵀᴱ

); }

Comments