Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions src/components/AssumptionsTab.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo, useState, useRef, useCallback, useEffect } from 'react';
import { ASSUMPTION_SEGMENTS, GLOBAL_PARAMS, TRANSLATION_INTENSITIES } from '../data/assumptions.js';
import { formatNumber } from '../engine/calculations.js';
import { formatNumber, softEfficiencyCap } from '../engine/calculations.js';

/* ── Brain equivalency constants ── */
const BRAIN = GLOBAL_PARAMS.brainEquivalency;
Expand Down Expand Up @@ -73,7 +73,7 @@ const BRAIN_COLUMNS = [
{ valueKey: 'cumulativeGain', label: 'Cumulative Eff. (x)', format: v => v < 1000 ? v.toFixed(1) + 'x' : (v / 1000).toFixed(1) + 'Kx' },
{ valueKey: 'wattsPerBrainEquiv', label: 'W per Brain-Equiv', format: v => v >= 1000 ? (v / 1000).toFixed(1) + ' kW' : v.toFixed(0) + ' W' },
{ valueKey: 'brainEfficiencyPct', label: '% of Brain Eff.', format: v => v < 1 ? v.toFixed(2) + '%' : v < 100 ? v.toFixed(1) + '%' : v.toFixed(0) + '%', help: `Human brain = ${GLOBAL_PARAMS.brainEquivalency.humanBrainWatts}W` },
{ valueKey: 'atAsymptote', label: 'Limit?', format: v => v ? 'AT LIMIT' : '\u2014' }
{ valueKey: 'atAsymptote', label: 'Returns', format: v => v ? 'DIMINISHING' : 'linear' }
];

function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSimulating, results }) {
Expand Down Expand Up @@ -377,48 +377,48 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
const startingWatts = BRAIN.startingWattsPerBrainEquiv;
const brainWatts = BRAIN.humanBrainWatts;

// Cap: AI can be at most 5× more efficient than the human brain (30W).
// At 5× efficiency → 6W per brain-equiv. maxCumulativeGain = 10000 / 6 ≈ 1667×.
// Knee: gains above this level see logarithmic diminishing returns.
// maxCumulativeGain = 10000 / 3 ≈ 3333×. Beyond the knee, improvements
// continue but much slower — reflecting practical engineering limits.
const minWatts = BRAIN.minWattsPerBrainEquiv;
const maxCumulativeGain = startingWatts / minWatts;

let cumulativeGain = 1.0;
let asymptoteReached = false;
let firstAsymptoteIdx = -1;
let rawCumulativeGain = 1.0;
let pastKnee = false;
let firstKneeIdx = -1;

const results = {};

timeBlocks.forEach((block, idx) => {
const years = BLOCK_YEARS[idx] || 1;
const annualGain = efficiencySummary[block.key]?.totalGain || 1;

if (!asymptoteReached) {
// Compound the annual gain over the block's duration
const blockGain = Math.pow(annualGain, years);
cumulativeGain *= blockGain;
// Always compound — gains never stop, just slow down past the knee
const blockGain = Math.pow(annualGain, years);
rawCumulativeGain *= blockGain;

// Check if we hit the asymptote
if (cumulativeGain >= maxCumulativeGain) {
cumulativeGain = maxCumulativeGain;
asymptoteReached = true;
firstAsymptoteIdx = idx;
}
// Soft cap: below the knee linear, above logarithmic diminishing returns
const effectiveGain = softEfficiencyCap(rawCumulativeGain, maxCumulativeGain);

if (!pastKnee && rawCumulativeGain >= maxCumulativeGain) {
pastKnee = true;
firstKneeIdx = idx;
}

const wattsPerBrainEquiv = Math.max(startingWatts / cumulativeGain, minWatts);
const wattsPerBrainEquiv = Math.max(startingWatts / effectiveGain, minWatts);
const brainEfficiencyPct = (brainWatts / wattsPerBrainEquiv) * 100;

results[block.key] = {
cumulativeGain,
cumulativeGain: effectiveGain,
wattsPerBrainEquiv,
brainEfficiencyPct,
atAsymptote: asymptoteReached
atAsymptote: pastKnee
};
});

return {
perBlock: results,
firstAsymptoteIdx
firstAsymptoteIdx: firstKneeIdx
};
}, [efficiencySummary, timeBlocks]);

Expand Down Expand Up @@ -500,14 +500,13 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
});
}, [impliedAIs, results]);

/* ── Check if a row is past the asymptote (for greying out efficiency cells) ── */
/* ── Check if a row is past the efficiency knee (diminishing returns) ── */

const isRowPastAsymptote = useCallback((rowIdx) => {
const { firstAsymptoteIdx } = brainEquivalency;
if (firstAsymptoteIdx === -1) return false;
// Grey out the row that hit the asymptote and all rows after it
return rowIdx >= firstAsymptoteIdx;
}, [brainEquivalency]);
// With the soft cap, cells are never fully disabled — gains continue,
// just slower. Return false so all rows stay editable.
return false;
}, []);

/* ── Render: table header row ── */

Expand Down Expand Up @@ -746,7 +745,7 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
</th>
<th className="assumptions-header-cell">
<div className="assumptions-col-title">W/Brain-Equiv</div>
<div className="assumptions-col-years">floor {BRAIN.minWattsPerBrainEquiv}W</div>
<div className="assumptions-col-years">knee {BRAIN.minWattsPerBrainEquiv}W</div>
</th>
<th className="assumptions-header-cell">
<div className="assumptions-col-title">Brain Equivalents</div>
Expand All @@ -771,11 +770,12 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
<span className="assumptions-metric">{row.totalPowerGW.toFixed(1)}</span>
</td>
<td className="assumptions-input-cell">
<span className={`assumptions-metric${row.atEfficiencyLimit ? ' asymptote-label' : ''}`}>
<span className="assumptions-metric">
{row.wattsPerBrainEquiv >= 1000
? (row.wattsPerBrainEquiv / 1000).toFixed(1) + ' kW'
: row.wattsPerBrainEquiv.toFixed(0) + ' W'}
{row.atEfficiencyLimit ? ' (LIMIT)' : ''}
: row.wattsPerBrainEquiv < 10
? row.wattsPerBrainEquiv.toFixed(1) + ' W'
: row.wattsPerBrainEquiv.toFixed(0) + ' W'}
</span>
</td>
<td className="assumptions-input-cell">
Expand Down Expand Up @@ -918,9 +918,9 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
Compares AI compute efficiency to the human brain ({BRAIN.humanBrainWatts}W).
Starting at {(BRAIN.startingWattsPerBrainEquiv / 1000).toFixed(0)}kW per brain-equivalent
of cognitive work, efficiency improvements compound over time.
Asymptotes at {BRAIN.maxEfficiencyVsBrain}× brain efficiency
({BRAIN.minWattsPerBrainEquiv}W per brain-equiv). Once the
asymptote is reached, further efficiency cells are locked.
Soft knee at {BRAIN.maxEfficiencyVsBrain}× brain efficiency
({BRAIN.minWattsPerBrainEquiv}W per brain-equiv) — beyond this,
gains continue but with logarithmic diminishing returns.
</p>
{renderBrainEquivalencyTable()}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/data/assumptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ export const GLOBAL_PARAMS = {
brainEquivalency: {
humanBrainWatts: 30, // Human brain power consumption in watts
startingWattsPerBrainEquiv: 10000, // Starting AI watts per brain-equivalent of cognitive work
maxEfficiencyVsBrain: 5, // Asymptote: AI can be at most 5x more efficient than the brain
// At 5x efficiency, AI does brain-equivalent work at 30W / 5 = 6W
minWattsPerBrainEquiv: 6 // = humanBrainWatts / maxEfficiencyVsBrain
maxEfficiencyVsBrain: 10, // Asymptote: AI can be at most 10x more efficient than the brain
// At 10x efficiency, AI does brain-equivalent work at 30W / 10 = 3W
minWattsPerBrainEquiv: 3 // = humanBrainWatts / maxEfficiencyVsBrain
}
};

Expand Down
43 changes: 27 additions & 16 deletions src/engine/calculations.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,25 @@ function getNodeType(nodeId) {

const EPSILON = 1e-10;

// Thermodynamic efficiency ceiling: shared across simulation engine and brain equivalency.
// No matter how clever the algorithm or optimized the silicon, inference cannot go below
// ~6W per operation (5× more efficient than the human brain at ~30W). Current GPU-class
// accelerators draw ~700W, so max compound efficiency gain is bounded by 700W / 6W ≈ 117×.
// Efficiency ceiling (soft knee): gains below the knee are linear; above, logarithmic
// diminishing returns. The knee is set by the ratio of current GPU power to a practical
// floor (~3W = 10× more efficient than the human brain at 30W). Beyond the knee,
// improvements continue but at a dramatically slower pace — reflecting engineering
// diminishing returns rather than a hard thermodynamic wall.
export const CURRENT_GPU_WATTS = 700;
export const THERMODYNAMIC_FLOOR_WATTS = 6;
export const MAX_EFFICIENCY_GAIN = CURRENT_GPU_WATTS / THERMODYNAMIC_FLOOR_WATTS;
export const THERMODYNAMIC_FLOOR_WATTS = 3;
export const MAX_EFFICIENCY_GAIN = CURRENT_GPU_WATTS / THERMODYNAMIC_FLOOR_WATTS; // ~233×

/**
* Soft asymptotic efficiency cap with diminishing returns above the knee.
* Below the knee: gain = raw (linear, unchanged).
* Above the knee: gain = knee × (1 + ln(raw / knee)) — logarithmic.
* Continuous at the knee. Always increasing, but dramatically slower above it.
*/
export function softEfficiencyCap(raw, knee) {
if (raw <= knee) return raw;
return knee * (1 + Math.log(raw / knee));
}

// Planning knobs
const CATCHUP_MONTHS = 6;
Expand Down Expand Up @@ -501,12 +513,11 @@ function computeRequiredGpus(month, trajectories, demandAssumptions, efficiencyA
// Efficiency gain: M decays (models get cheaper → more tok/s), S and H grow throughput.
// H_memory: inference is memory-bandwidth-bound (not compute-bound), so HBM generational
// improvements (H_memory) directly increase inference tok/s alongside general H gains.
// Thermodynamic floor: no matter how clever the algorithm or how optimized the silicon,
// inference cannot go below ~6W per operation (5× more efficient than the human brain
// at ~30W). Current GPU-class accelerators draw ~700W, so the maximum compound
// efficiency gain across all axes is bounded by 700W / 6W ≈ 117×.
// Soft efficiency ceiling: below ~233× (700W / 3W), gains are linear. Above the knee,
// diminishing returns kick in — improvements continue but at logarithmic pace,
// reflecting practical engineering limits rather than a hard thermodynamic wall.
const rawEfficiencyGain = (1 / Math.max(eff.M_inference, EPSILON)) * eff.S_inference * eff.H * eff.H_memory;
const efficiencyGain = Math.min(rawEfficiencyGain, MAX_EFFICIENCY_GAIN);
const efficiencyGain = softEfficiencyCap(rawEfficiencyGain, MAX_EFFICIENCY_GAIN);

// Per-segment GPU demand (with demandScale applied to token volumes)
const consumerTokens = (inferenceDemand.consumer || 0) * demandScale;
Expand All @@ -533,11 +544,11 @@ function computeRequiredGpus(month, trajectories, demandAssumptions, efficiencyA

const totalTrainingHours = (frontierRuns * hoursFrontier) + (midtierRuns * hoursMidtier);
const denomTraining = hoursPerMonth * utilTrn * eff.S_training * eff.H;
// Cap training efficiency the same way: M_training decays (numerator) while S*H grows
// (denominator), so the effective reduction factor = M / (S*H). Floor it at 1/MAX.
const rawTrainingFactor = eff.M_training / Math.max(denomTraining, EPSILON);
const minTrainingFactor = 1 / (hoursPerMonth * utilTrn * MAX_EFFICIENCY_GAIN);
const requiredTraining = totalTrainingHours * Math.max(rawTrainingFactor, minTrainingFactor);
// Soft cap training efficiency: compute raw gain = (S*H) / M, apply soft knee,
// then convert back to a cost factor. Gains continue past the knee but slow dramatically.
const rawTrainingGain = eff.S_training * eff.H / Math.max(eff.M_training, EPSILON);
const cappedTrainingGain = softEfficiencyCap(rawTrainingGain, MAX_EFFICIENCY_GAIN);
const requiredTraining = totalTrainingHours / (hoursPerMonth * utilTrn * cappedTrainingGain);

return {
requiredTotal: requiredInference + requiredTraining,
Expand Down