The demo below shows the core idea of diagonalization in action. There is a finite list of small algorithms (each one returns 0 or 1 for a given input). A diagonal machine reads each algorithm as input and deliberately returns the opposite answer — ensuring it disagrees with every listed algorithm on at least one input.
<!-- Diagonalization demo for the Time Hierarchy Theorem -->
<p class="hint">Each row is a small algorithm that outputs 0 or 1 for inputs 0–4. The <b>diagonal machine D</b> looks at what algorithm Aᵢ returns on input <i>i</i> (the shaded diagonal cell) and flips it. D therefore disagrees with <i>every</i> listed algorithm on at least one input — so no listed algorithm can equal D. That is the problem D solves that sits outside the smaller time class.</p>
<div id="matrix-wrap">
<table id="matrix" aria-label="Diagonalization matrix">
<thead>
<tr>
<th>Algorithm</th>
<th title="Input value">Input 0</th>
<th title="Input value">Input 1</th>
<th title="Input value">Input 2</th>
<th title="Input value">Input 3</th>
<th title="Input value">Input 4</th>
<th class="diag-col" title="Diagonal machine output for this row index">D(i)</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
<div class="status" id="status">Click "Run diagonal" to see the disagreements.</div>
<div class="btns">
<button id="btn-run" type="button">Run diagonal</button>
<button id="btn-reset" type="button" class="ghost">Reset</button>
</div>
/* Styles for the diagonalization matrix */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .7rem; line-height: 1.5; }
#matrix-wrap { overflow-x: auto; }
table { border-collapse: collapse; font-size: .9rem; margin-bottom: .7rem; }
th, td { padding: .35rem .55rem; border: 1px solid #cdd9e3; text-align: center; }
th { background: #e8eef3; font-weight: 700; color: #1d3557; }
td.algo-name { text-align: left; font-style: italic; white-space: nowrap; }
td.cell-0 { background: #f0f4f8; color: #555; }
td.cell-1 { background: #d4edda; color: #155724; font-weight: 600; }
td.diag-col { background: #fff3cd; font-weight: 700; }
td.diag-col.flip { background: #e63946; color: #fff; }
td.diag-agree { background: #c3e6cb; }
td.diag-disagree { background: #f5c6cb; }
tr.diag-row td { background: #fffbe6; font-weight: 700; }
tr.diag-row td.diag-col { background: #ffc107; color: #222; }
.status { font-size: .95rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.info { color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem;
border: 1px solid #1d3557; background: #1d3557; color: #fff;
border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
const i18nFmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Small algorithms A1..A5, each mapping an input number to 0 or 1.
// In a real proof these would be Turing machines enumerated by index.
const ALGOS = [
{ name: 'A₁', fn: n => (n % 2 === 0 ? 1 : 0) },
{ name: 'A₂', fn: n => (n < 3 ? 1 : 0) },
{ name: 'A₃', fn: n => 1 },
{ name: 'A₄', fn: n => (n === 2 || n === 4 ? 1 : 0) },
{ name: 'A₅', fn: n => 0 }
];
const INPUTS = [0, 1, 2, 3, 4];
// The diagonal machine flips the output of algorithm i on input i.
function diagonal(i) {
return ALGOS[i].fn(i) === 1 ? 0 : 1;
}
let ran = false;
function buildTable(showDiag) {
const tbody = document.getElementById('tbody');
tbody.innerHTML = '';
// Build one table row per algorithm
for (let i = 0; i < ALGOS.length; i++) {
const tr = document.createElement('tr');
const nameCell = document.createElement('td');
nameCell.className = 'algo-name';
nameCell.textContent = ALGOS[i].name;
tr.appendChild(nameCell);
for (let j = 0; j < INPUTS.length; j++) {
const td = document.createElement('td');
const val = ALGOS[i].fn(INPUTS[j]);
td.textContent = val;
td.className = 'cell-' + val;
// Highlight the diagonal cell (row i, input i) that D reads and flips
if (j === i && showDiag) {
td.className += (val === 1 ? ' diag-disagree' : ' diag-agree');
}
tr.appendChild(td);
}
// Last column shows what D returns for this row index
const diagTd = document.createElement('td');
diagTd.className = 'diag-col';
if (showDiag) {
const d = diagonal(i);
diagTd.textContent = d;
diagTd.classList.add('flip');
} else {
diagTd.textContent = '?';
}
tr.appendChild(diagTd);
tbody.appendChild(tr);
}
// Extra row shows D's full output across all inputs
const diagRow = document.createElement('tr');
diagRow.className = 'diag-row';
const dLabel = document.createElement('td');
dLabel.className = 'algo-name';
dLabel.textContent = 'D (diagonal)';
diagRow.appendChild(dLabel);
for (let j = 0; j < INPUTS.length; j++) {
const td = document.createElement('td');
td.className = 'diag-col';
if (showDiag) {
td.textContent = diagonal(j);
} else {
td.textContent = '?';
}
diagRow.appendChild(td);
}
const cornerTd = document.createElement('td');
cornerTd.className = 'diag-col';
cornerTd.textContent = '';
diagRow.appendChild(cornerTd);
tbody.appendChild(diagRow);
}
function run() {
ran = true;
buildTable(true);
const disagreeCount = ALGOS.length;
document.getElementById('status').textContent = i18nFmt('Diagonal machine found — disagrees with all %n% algorithms on their diagonal cell.', { n: disagreeCount });
document.getElementById('status').className = 'status ok';
}
function reset() {
ran = false;
buildTable(false);
document.getElementById('status').textContent = 'Click "Run diagonal" to see the disagreements.';
document.getElementById('status').className = 'status info';
}
document.getElementById('btn-run').addEventListener('click', run);
document.getElementById('btn-reset').addEventListener('click', reset);
buildTable(false);
document.getElementById('status').className = 'status info';
<!-- Diagonalization demo for the Time Hierarchy Theorem -->
<p class="hint">Each row is a small algorithm that outputs 0 or 1 for inputs 0–4. The <b>diagonal machine D</b> looks at what algorithm Aᵢ returns on input <i>i</i> (the shaded diagonal cell) and flips it. D therefore disagrees with <i>every</i> listed algorithm on at least one input — so no listed algorithm can equal D. That is the problem D solves that sits outside the smaller time class.</p>
<div id="matrix-wrap">
<table id="matrix" aria-label="Diagonalization matrix">
<thead>
<tr>
<th>Algorithm</th>
<th title="Input value">Input 0</th>
<th title="Input value">Input 1</th>
<th title="Input value">Input 2</th>
<th title="Input value">Input 3</th>
<th title="Input value">Input 4</th>
<th class="diag-col" title="Diagonal machine output for this row index">D(i)</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
<div class="status" id="status">Click "Run diagonal" to see the disagreements.</div>
<div class="btns">
<button id="btn-run" type="button">Run diagonal</button>
<button id="btn-reset" type="button" class="ghost">Reset</button>
</div>
/* Styles for the diagonalization matrix */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .7rem; line-height: 1.5; }
#matrix-wrap { overflow-x: auto; }
table { border-collapse: collapse; font-size: .9rem; margin-bottom: .7rem; }
th, td { padding: .35rem .55rem; border: 1px solid #cdd9e3; text-align: center; }
th { background: #e8eef3; font-weight: 700; color: #1d3557; }
td.algo-name { text-align: left; font-style: italic; white-space: nowrap; }
td.cell-0 { background: #f0f4f8; color: #555; }
td.cell-1 { background: #d4edda; color: #155724; font-weight: 600; }
td.diag-col { background: #fff3cd; font-weight: 700; }
td.diag-col.flip { background: #e63946; color: #fff; }
td.diag-agree { background: #c3e6cb; }
td.diag-disagree { background: #f5c6cb; }
tr.diag-row td { background: #fffbe6; font-weight: 700; }
tr.diag-row td.diag-col { background: #ffc107; color: #222; }
.status { font-size: .95rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.info { color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem;
border: 1px solid #1d3557; background: #1d3557; color: #fff;
border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
const i18nFmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Small algorithms A1..A5, each mapping an input number to 0 or 1.
// In a real proof these would be Turing machines enumerated by index.
const ALGOS = [
{ name: 'A₁', fn: n => (n % 2 === 0 ? 1 : 0) },
{ name: 'A₂', fn: n => (n < 3 ? 1 : 0) },
{ name: 'A₃', fn: n => 1 },
{ name: 'A₄', fn: n => (n === 2 || n === 4 ? 1 : 0) },
{ name: 'A₅', fn: n => 0 }
];
const INPUTS = [0, 1, 2, 3, 4];
// The diagonal machine flips the output of algorithm i on input i.
function diagonal(i) {
return ALGOS[i].fn(i) === 1 ? 0 : 1;
}
let ran = false;
function buildTable(showDiag) {
const tbody = document.getElementById('tbody');
tbody.innerHTML = '';
// Build one table row per algorithm
for (let i = 0; i < ALGOS.length; i++) {
const tr = document.createElement('tr');
const nameCell = document.createElement('td');
nameCell.className = 'algo-name';
nameCell.textContent = ALGOS[i].name;
tr.appendChild(nameCell);
for (let j = 0; j < INPUTS.length; j++) {
const td = document.createElement('td');
const val = ALGOS[i].fn(INPUTS[j]);
td.textContent = val;
td.className = 'cell-' + val;
// Highlight the diagonal cell (row i, input i) that D reads and flips
if (j === i && showDiag) {
td.className += (val === 1 ? ' diag-disagree' : ' diag-agree');
}
tr.appendChild(td);
}
// Last column shows what D returns for this row index
const diagTd = document.createElement('td');
diagTd.className = 'diag-col';
if (showDiag) {
const d = diagonal(i);
diagTd.textContent = d;
diagTd.classList.add('flip');
} else {
diagTd.textContent = '?';
}
tr.appendChild(diagTd);
tbody.appendChild(tr);
}
// Extra row shows D's full output across all inputs
const diagRow = document.createElement('tr');
diagRow.className = 'diag-row';
const dLabel = document.createElement('td');
dLabel.className = 'algo-name';
dLabel.textContent = 'D (diagonal)';
diagRow.appendChild(dLabel);
for (let j = 0; j < INPUTS.length; j++) {
const td = document.createElement('td');
td.className = 'diag-col';
if (showDiag) {
td.textContent = diagonal(j);
} else {
td.textContent = '?';
}
diagRow.appendChild(td);
}
const cornerTd = document.createElement('td');
cornerTd.className = 'diag-col';
cornerTd.textContent = '';
diagRow.appendChild(cornerTd);
tbody.appendChild(diagRow);
}
function run() {
ran = true;
buildTable(true);
const disagreeCount = ALGOS.length;
document.getElementById('status').textContent = i18nFmt('Diagonal machine found — disagrees with all %n% algorithms on their diagonal cell.', { n: disagreeCount });
document.getElementById('status').className = 'status ok';
}
function reset() {
ran = false;
buildTable(false);
document.getElementById('status').textContent = 'Click "Run diagonal" to see the disagreements.';
document.getElementById('status').className = 'status info';
}
document.getElementById('btn-run').addEventListener('click', run);
document.getElementById('btn-reset').addEventListener('click', reset);
buildTable(false);
document.getElementById('status').className = 'status info';
The diagonal machine uses its extra simulation budget to stay one step ahead. No algorithm in the list can match it on every input — that is precisely the problem that sits outside the smaller time class. Click Run diagonal to see the disagreements light up.
Comments
Loading comments...