hwr-notes/Komplexitätstheorie/vortrag/Learnings.html
2026-04-09 11:24:56 +02:00

493 lines
No EOL
39 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVP Lernzusammenfassung</title>
<style>
:root {
--bg: #fafaf8;
--bg2: #f1efe8;
--text: #2c2c2a;
--text2: #5f5e5a;
--text3: #888780;
--border: rgba(0,0,0,0.1);
--blue: #378ADD;
--purple: #7F77DD;
--teal: #1D9E75;
--red: #E24B4A;
--amber: #EF9F27;
--coral: #D85A30;
--green: #97C459;
--font: -apple-system, 'Segoe UI', sans-serif;
--mono: 'SF Mono', 'Fira Code', monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--bg2: #2a2a28;
--text: #e0dfd8;
--text2: #a0a098;
--text3: #707068;
--border: rgba(255,255,255,0.1);
}
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: var(--font); font-size: 16px; line-height: 1.75; color: var(--text); background: var(--bg); max-width: 780px; margin: 0 auto; padding: 40px 24px 80px; }
h1 { font-size: 28px; font-weight: 600; margin: 0 0 8px; }
h2 { font-size: 20px; font-weight: 600; margin: 48px 0 16px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
h3 { font-size: 17px; font-weight: 600; margin: 32px 0 12px; }
p { margin: 0 0 16px; }
strong { font-weight: 600; }
em { font-style: italic; }
code { font-family: var(--mono); font-size: 14px; background: var(--bg2); padding: 2px 6px; border-radius: 4px; }
.subtitle { color: var(--text2); font-size: 15px; margin-bottom: 32px; }
.viz-container { margin: 24px 0 32px; padding: 20px; background: var(--bg2); border-radius: 12px; border: 0.5px solid var(--border); }
.viz-container svg { display: block; margin: 0 auto; }
.step-nav { display: flex; gap: 8px; margin: 0 0 12px; flex-wrap: wrap; }
.step-btn { font-size: 13px; padding: 5px 12px; border-radius: 6px; border: 0.5px solid var(--border); background: transparent; color: var(--text2); cursor: pointer; font-family: var(--font); transition: all .15s; }
.step-btn.active { background: #E6F1FB; color: #185FA5; border-color: #85B7EB; font-weight: 500; }
@media (prefers-color-scheme: dark) {
.step-btn.active { background: #0C447C; color: #B5D4F4; border-color: #185FA5; }
}
.step-btn:hover:not(.active) { background: var(--bg); }
.viz-caption { font-size: 14px; line-height: 1.6; color: var(--text); margin: 10px 0 0; }
.viz-caption strong { font-weight: 600; }
.key-item { display: inline-flex; align-items: center; gap: 6px; margin-right: 12px; font-size: 12px; color: var(--text2); }
.key-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.merkbox { margin: 20px 0; padding: 16px 20px; border-radius: 10px; border-left: 4px solid var(--teal); background: var(--bg2); }
.merkbox-title { font-size: 14px; font-weight: 600; color: var(--teal); margin-bottom: 6px; }
.prof-box { margin: 20px 0; padding: 16px 20px; border-radius: 10px; border-left: 4px solid var(--amber); background: var(--bg2); }
.prof-box-title { font-size: 14px; font-weight: 600; color: var(--amber); margin-bottom: 6px; }
.proof-check { display: flex; align-items: baseline; gap: 8px; font-size: 14px; color: var(--text2); margin: 4px 0; }
.proof-check .mark { color: var(--teal); font-weight: 600; }
hr { border: none; border-top: 1px solid var(--border); margin: 40px 0; }
.chain-step { display: flex; align-items: center; gap: 12px; margin: 8px 0; }
.chain-arrow { color: var(--text3); font-size: 18px; margin: 4px 0 4px 20px; }
.chain-box { padding: 8px 14px; border-radius: 8px; font-size: 14px; }
</style>
</head>
<body>
<h1>SVP — Lernzusammenfassung</h1>
<p class="subtitle">Alle Erklärungen und Visualisierungen aus der Tutoring-Session. Zum Wiederholen vor dem Vortrag.</p>
<!-- ═══════════════════════════════════════ -->
<h2>1. Was ist ein Gitter?</h2>
<p>Ein Gitter ist die Menge aller ganzzahligen Kombinationen von Basisvektoren. Stell dir schiefes Karopapier vor — die Ecken der Parallelogramme sind die Gitterpunkte, und die Seitenvektoren bilden die Basis.</p>
<p>Formal: <code>L = { z₁b₁ + z₂b₂ + ... + zₙbₙ | zᵢ ∈ }</code></p>
<p>Der entscheidende Unterschied zur linearen Algebra: Bei Vektorräumen darfst du <em>reelle</em> Zahlen verwenden und erreichst jeden Punkt. Bei Gittern nur <em>ganze</em> Zahlen → du bekommst diskrete Punkte.</p>
<div class="merkbox">
<div class="merkbox-title">Merkregel</div>
Mit einer Kombination aus den Basisvektoren (nur ganzzahlige Koeffizienten!) kann man das gesamte Gitter abbilden. Kein Punkt fehlt, keiner kommt dazu. Die Basis <em>definiert</em> das Gitter.
</div>
<p><strong>Basen sind nicht eindeutig:</strong> Dasselbe Gitter kann durch komplett unterschiedliche Basisvektoren beschrieben werden. Manche Basen sind „gut" (kurze, fast senkrechte Vektoren → SVP leicht lösbar), manche „schlecht" (lange, fast parallele Vektoren → SVP schwer). Man kann nicht einfach orthonormalisieren, weil das reelle Koeffizienten bräuchte — erlaubt sind nur ganzzahlige unimodulare Transformationen (det = ±1).</p>
<p><strong>Grundidee der Gitter-Krypto:</strong> Öffentlicher Schlüssel = schlechte Basis, privater Schlüssel = gute Basis desselben Gitters.</p>
<!-- Viz 1: Lattice + SVP + CVP -->
<div class="viz-container" id="viz1-wrap">
<div class="step-nav" id="v1nav"></div>
<div id="v1legend" style="margin-bottom:6px"></div>
<svg id="v1svg" width="100%" viewBox="0 0 640 380"></svg>
<div class="viz-caption" id="v1cap"></div>
</div>
<script>
(function(){
const b1=[80,20], b2=[30,70];
const b1p=[110,90], b2p=[190,110];
const ox=320, oy=220;
function gp(i,j){return [ox+i*b1[0]+j*b2[0], oy-(i*b1[1]+j*b2[1])];}
function allPts(){
const pts=[];
for(let i=-4;i<=4;i++) for(let j=-4;j<=4;j++){
const [x,y]=gp(i,j);
if(x>10&&x<630&&y>10&&y<370) pts.push({x,y,i,j});
}
return pts;
}
function dist(i,j){return Math.sqrt((i*b1[0]+j*b2[0])**2+(i*b1[1]+j*b2[1])**2);}
function findShortest(){
let best=Infinity,bi=0,bj=0;
for(let i=-4;i<=4;i++) for(let j=-4;j<=4;j++){
if(i===0&&j===0) continue;
const d=dist(i,j); if(d<best){best=d;bi=i;bj=j;}
}
return {i:bi,j:bj,d:best};
}
const steps=[
{label:"1. Gitter",legend:[{c:"#5DCAA5",t:"Gitterpunkte"},{c:"#378ADD",t:"Basis b₁, b₂"}]},
{label:"2. Schlechte Basis",legend:[{c:"#5DCAA5",t:"Gleiche Punkte"},{c:"#378ADD",t:"Gute Basis (kurz, fast orthogonal)"},{c:"#D85A30",t:"Schlechte Basis b₁', b₂' (lang, fast parallel)"}]},
{label:"3. SVP",legend:[{c:"#5DCAA5",t:"Gitterpunkte"},{c:"#E24B4A",t:"λ₁ = kürzester Vektor"}]},
{label:"4. γ-SVP",legend:[{c:"#E24B4A",t:"λ₁ (exakt)"},{c:"#EF9F27",t:"γ·λ₁ (Approximation ok)"}]},
{label:"5. CVP",legend:[{c:"#7F77DD",t:"Zielpunkt t"},{c:"#1D9E75",t:"Nächster Gitterpunkt"}]},
];
const captions=[
`<strong>Ein Gitter</strong> entsteht durch alle ganzzahligen Kombinationen der Basisvektoren b₁ und b₂.`,
`<strong>Dasselbe Gitter, schlechte Basis.</strong> b₁' = b₁+b₂ und b₂' = 2b₁+b₂ — beide lang, nur ~8° auseinander (fast parallel). Die Vektoren erzeugen exakt die gleichen Punkte. Grundidee der Krypto: öffentlicher Schlüssel = schlechte Basis, privater Schlüssel = gute.`,
`<strong>SVP: Finde den kürzesten Nicht-Null-Vektor.</strong> In 2D trivial — in Dimension 500+ exponentiell schwer.`,
`<strong>γ-SVP:</strong> Statt exakt λ₁ zu finden, reicht ein Vektor im orangenen Kreis. Je größer γ, desto leichter.`,
`<strong>CVP:</strong> Finde den nächsten Gitterpunkt zu einem externen Punkt t. Mindestens so schwer wie SVP.`,
];
function draw(step){
const svg=document.getElementById('v1svg');
const pts=allPts(), sh=findShortest(), [sx,sy]=gp(sh.i,sh.j);
let h=`<defs><marker id="a1" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker></defs>`;
for(let i=-4;i<=4;i++){const[x1,y1]=gp(i,-4),[x2,y2]=gp(i,4);h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${getComputedStyle(document.body).getPropertyValue('color').includes('255')?'rgba(255,255,255,0.06)':'rgba(0,0,0,0.06)'}" stroke-width="0.3"/>`;}
for(let j=-4;j<=4;j++){const[x1,y1]=gp(-4,j),[x2,y2]=gp(4,j);h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${getComputedStyle(document.body).getPropertyValue('color').includes('255')?'rgba(255,255,255,0.06)':'rgba(0,0,0,0.06)'}" stroke-width="0.3"/>`;}
const dots=(hl)=>{let g='';pts.forEach(p=>{const isO=p.i===0&&p.j===0,isS=p.i===sh.i&&p.j===sh.j;let fill="#5DCAA5",r=isO?5:3.5,op=isO?1:0.7;if(hl==='svp'&&isS){fill="#E24B4A";r=5;op=1;}if(hl==='cvp'&&p.i===1&&p.j===0){fill="#1D9E75";r=5;op=1;}g+=`<circle cx="${p.x}" cy="${p.y}" r="${r}" fill="${fill}" opacity="${op}"/>`;if(isO)g+=`<text x="${p.x+8}" y="${p.y-8}" fill="var(--text3)" font-size="12" font-family="var(--font)">0</text>`;});return g;};
const arrow=(x1,y1,x2,y2,color,w=2)=>`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${color}" stroke-width="${w}" stroke-linecap="round" marker-end="url(#a1)"/>`;
if(step===0){h+=dots('');h+=arrow(ox,oy,ox+b1[0],oy-b1[1],"#378ADD",2.5);h+=arrow(ox,oy,ox+b2[0],oy-b2[1],"#378ADD",2.5);h+=`<text x="${ox+b1[0]+8}" y="${oy-b1[1]-6}" fill="#378ADD" font-size="14" font-weight="500" font-family="var(--font)">b₁</text>`;h+=`<text x="${ox+b2[0]+8}" y="${oy-b2[1]-6}" fill="#378ADD" font-size="14" font-weight="500" font-family="var(--font)">b₂</text>`;}
if(step===1){h+=dots('');h+=arrow(ox,oy,ox+b1[0],oy-b1[1],"#378ADD",1.5);h+=arrow(ox,oy,ox+b2[0],oy-b2[1],"#378ADD",1.5);h+=`<text x="${ox+b1[0]+8}" y="${oy-b1[1]-6}" fill="#378ADD" font-size="13" font-family="var(--font)" opacity="0.5">b₁</text>`;h+=`<text x="${ox+b2[0]+8}" y="${oy-b2[1]-6}" fill="#378ADD" font-size="13" font-family="var(--font)" opacity="0.5">b₂</text>`;h+=arrow(ox,oy,ox+b1p[0],oy-b1p[1],"#D85A30",2.5);h+=arrow(ox,oy,ox+b2p[0],oy-b2p[1],"#D85A30",2.5);h+=`<text x="${ox+b1p[0]+8}" y="${oy-b1p[1]-6}" fill="#D85A30" font-size="14" font-weight="500" font-family="var(--font)">b₁'</text>`;h+=`<text x="${ox+b2p[0]-24}" y="${oy-b2p[1]-6}" fill="#D85A30" font-size="14" font-weight="500" font-family="var(--font)">b₂'</text>`;}
if(step===2){h+=dots('svp');h+=arrow(ox,oy,sx,sy,"#E24B4A",2.5);h+=`<text x="${(ox+sx)/2+10}" y="${(oy+sy)/2-10}" fill="#E24B4A" font-size="14" font-weight="500" font-family="var(--font)">λ₁</text>`;}
if(step===3){const r1=sh.d,r2=r1*2;h+=`<circle cx="${ox}" cy="${oy}" r="${r1}" fill="none" stroke="#E24B4A" stroke-width="1" stroke-dasharray="4 3" opacity="0.7"/>`;h+=`<circle cx="${ox}" cy="${oy}" r="${r2}" fill="#EF9F27" fill-opacity="0.08" stroke="#EF9F27" stroke-width="1.5" stroke-dasharray="5 3"/>`;h+=dots('svp');h+=arrow(ox,oy,sx,sy,"#E24B4A",2);h+=`<text x="${ox+8}" y="${oy-r1-6}" fill="#E24B4A" font-size="12" font-family="var(--font)">λ₁</text>`;h+=`<text x="${ox+8}" y="${oy-r2-6}" fill="#EF9F27" font-size="12" font-family="var(--font)">γ·λ₁</text>`;pts.filter(p=>{if(p.i===0&&p.j===0)return false;const d=dist(p.i,p.j);return d<=r2&&d>r1;}).forEach(p=>{h+=`<circle cx="${p.x}" cy="${p.y}" r="6" fill="none" stroke="#EF9F27" stroke-width="1.5"/>`;});}
if(step===4){const tx=ox+55,ty=oy-52,[cx,cy]=gp(1,0);h+=dots('cvp');h+=`<circle cx="${tx}" cy="${ty}" r="6" fill="#7F77DD"/>`;h+=`<text x="${tx+10}" y="${ty-8}" fill="#7F77DD" font-size="14" font-weight="500" font-family="var(--font)">t</text>`;h+=`<line x1="${tx}" y1="${ty}" x2="${cx}" y2="${cy}" stroke="#1D9E75" stroke-width="1.5" stroke-dasharray="5 3"/>`;h+=`<text x="${(tx+cx)/2+10}" y="${(ty+cy)/2-8}" fill="#1D9E75" font-size="12" font-family="var(--font)">Distanz</text>`;}
svg.innerHTML=h;
document.querySelectorAll('#v1nav .step-btn').forEach((b,i)=>b.classList.toggle('active',i===step));
document.getElementById('v1legend').innerHTML=steps[step].legend.map(l=>`<span class="key-item"><span class="key-dot" style="background:${l.c}"></span>${l.t}</span>`).join('');
document.getElementById('v1cap').innerHTML=captions[step];
}
const nav=document.getElementById('v1nav');
steps.forEach((s,i)=>{const b=document.createElement('button');b.className='step-btn';b.textContent=s.label;b.onclick=()=>draw(i);nav.appendChild(b);});
draw(0);
})();
</script>
<!-- ═══════════════════════════════════════ -->
<h2>2. SVP, γ-SVP und CVP</h2>
<h3>Exaktes SVP</h3>
<p>Gegeben eine Basis B, finde den kürzesten Nicht-Null-Vektor. Die Länge dieses Vektors heißt λ₁(L). Minkowski hat 1889 bewiesen, dass so ein Vektor immer existiert — aber ihn <em>finden</em> ist das Problem.</p>
<h3>γ-SVP (Approximation)</h3>
<p>Statt den exakt kürzesten Vektor zu finden, reicht einer, der höchstens γ-mal so lang ist. Drei Varianten:</p>
<p><strong>Suchversion (SVP_γ):</strong> Finde einen Vektor v mit ‖v‖ ≤ γ · λ₁.</p>
<p><strong>Schätzversion (EstSVP_γ):</strong> Gib die Länge λ₁ bis auf Faktor γ genau an.</p>
<p><strong>Entscheidungsversion (GapSVP_γ):</strong> Gegeben Basis B und Wert d, unterscheide: Ist λ₁ ≤ d (YES) oder λ₁ > γ·d (NO)? Alles dazwischen ist Grauzone (Promise-Problem) — dort darf die Antwort beliebig sein. In der Visualisierung: blauer Kreis = YES-Grenze (d), oranger Kreis = NO-Grenze (γ·d), gelbe Zone dazwischen = der „verbotene" Bereich, den das Problem ignoriert.</p>
<div class="merkbox">
<div class="merkbox-title">Die Komplexitätslandschaft von γ</div>
<code>γ = 1</code> → NP-hart (Ajtai 1998)<br>
<code>γ = Konstante</code> → NP-hart (Micciancio 2001)<br>
<code>γ ≈ √n</code> → NP ∩ coNP (Aharonov & Regev 2005)<br>
<code>γ = 2^O(n)</code> → in P (LLL löst das)<br>
Dazwischen: <em>Terra incognita</em> — niemand weiß wo es kippt.
</div>
<h3>CVP (Closest Vector Problem)</h3>
<p>Gegeben ein Gitter und einen externen Punkt t (nicht im Gitter), finde den nächstgelegenen Gitterpunkt. In der Visualisierung: roter Punkt mit Kreuz = Zielpunkt t, grün umringter Punkt = nächster Gitterpunkt, gestrichelte Linie = minimale Distanz.</p>
<p><strong>Verhältnis zu SVP:</strong> SVP ≤<sub>p</sub> CVP (Polynomialzeit-Reduktion: Man kann SVP auf CVP reduzieren, indem man Basis verdoppelt und t geschickt wählt). Die Umkehrung ist unbekannt — CVP gilt als das natürlich schwerere Problem. Typische Anwendung in der Kryptografie: t ist ein verrauschter Geheimtext, der nächste Gitterpunkt ist die eigentliche Nachricht.</p>
<!-- ═══════════════════════════════════════ -->
<h2>3. Komplexitätstheoretische Einordnung</h2>
<h3>Schnell-Glossar</h3>
<p><strong>P</strong> = effizient lösbar. <strong>NP</strong> = Lösung schnell überprüfbar. <strong>NP-hart</strong> = mindestens so schwer wie alles in NP. <strong>coNP</strong> = Ablehnung schnell verifizierbar. <strong>NP ∩ coNP</strong> = beides verifizierbar → vermutlich nicht NP-hart.</p>
<h3>NP-Härte (Ajtai 1998)</h3>
<p>Ajtai hat SAT auf SVP reduziert: Aus jeder SAT-Formel baut er ein Gitter, bei dem der kürzeste Vektor verrät, ob die Formel erfüllbar ist. <strong>Aber:</strong> Die Reduktion braucht Zufall (randomisiert). Ob es deterministisch geht, ist seit 26 Jahren offen.</p>
<p>Micciancio (2001) verschärft: Selbst Approximation bis auf <em>jeden</em> konstanten Faktor γ bleibt NP-hart.</p>
<h3>GapSVP in NP ∩ coNP (Aharonov & Regev 2005)</h3>
<p>Ab γ ≈ √n liegt GapSVP in NP ∩ coNP. Die NP-Seite ist trivial (kurzen Vektor vorzeigen). Die coNP-Seite ist der Durchbruch:</p>
<!-- Viz 2: Dual Lattice / coNP -->
<div class="viz-container" id="viz2-wrap">
<div class="step-nav" id="v2nav"></div>
<svg id="v2svg" width="100%" viewBox="0 0 640 320"></svg>
<div class="viz-caption" id="v2cap"></div>
</div>
<script>
(function(){
const ox1=160,oy=160,ox2=480;
const steps=[
{label:"1. Wippe",desc:`<strong>Transference-Theorem:</strong> Wenn λ₁(L) groß ist (Gitter hat keinen kurzen Vektor), dann muss λ₁(L*) klein sein (Dual hat kurze Vektoren). Wie eine Wippe.`},
{label:"2. Umgekehrt",desc:`<strong>Andersrum:</strong> Kurze Vektoren im Gitter → lange Vektoren im Dual. Die Wippe kippt. Banaszczyk: λ₁(L) · λ₁(L*) ≥ 1.`},
{label:"3. Der Beweis",desc:`<strong>coNP-Beweis:</strong> Um zu zeigen "L hat keinen kurzen Vektor", zeige stattdessen kurze Vektoren im Dual. Abwesenheit beweisen durch Anwesenheit von etwas anderem.`},
];
function draw(s){
const svg=document.getElementById('v2svg');
let h=`<defs><marker id="a2" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker></defs>`;
h+=`<line x1="320" y1="15" x2="320" y2="305" stroke="var(--border)" stroke-width="0.5" stroke-dasharray="6 4"/>`;
h+=`<text x="160" y="18" text-anchor="middle" fill="var(--text2)" font-size="13" font-weight="500" font-family="var(--font)">Gitter L</text>`;
h+=`<text x="480" y="18" text-anchor="middle" fill="var(--text2)" font-size="13" font-weight="500" font-family="var(--font)">Duales Gitter L*</text>`;
function lattice(cx,cy,b1,b2,color,r,range,showR,rc,rv){
let g='';
for(let i=-range;i<=range;i++){const x1=cx+i*b1[0]-range*b2[0],y1=cy-(i*b1[1]-range*b2[1]),x2=cx+i*b1[0]+range*b2[0],y2=cy-(i*b1[1]+range*b2[1]);g+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="var(--border)" stroke-width="0.2"/>`;}
for(let j=-range;j<=range;j++){const x1=cx-range*b1[0]+j*b2[0],y1=cy-(-range*b1[1]+j*b2[1]),x2=cx+range*b1[0]+j*b2[0],y2=cy-(range*b1[1]+j*b2[1]);g+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="var(--border)" stroke-width="0.2"/>`;}
if(showR) g+=`<circle cx="${cx}" cy="${cy}" r="${rv}" fill="${rc}" fill-opacity="0.08" stroke="${rc}" stroke-width="1" stroke-dasharray="4 3"/>`;
for(let i=-range;i<=range;i++) for(let j=-range;j<=range;j++){const x=cx+i*b1[0]+j*b2[0],y=cy-(i*b1[1]+j*b2[1]);if(x>5&&x<635&&y>20&&y<310){const isO=i===0&&j===0;g+=`<circle cx="${x}" cy="${y}" r="${isO?4:r}" fill="${color}" opacity="${isO?1:0.7}"/>`;}}
return g;
}
if(s===0){
h+=lattice(ox1,oy,[55,18],[15,50],"#378ADD",3.5,4,true,"#378ADD",55);
h+=lattice(ox2,oy,[14,5],[4,15],"#D85A30",3,10,true,"#D85A30",14);
h+=`<text x="${ox1}" y="${oy+75}" text-anchor="middle" fill="#378ADD" font-size="12" font-family="var(--font)">λ₁ groß ↑</text>`;
h+=`<text x="${ox2}" y="${oy+75}" text-anchor="middle" fill="#D85A30" font-size="12" font-family="var(--font)">λ₁* klein ↓</text>`;
h+=`<text x="320" y="${oy+75}" text-anchor="middle" fill="var(--text3)" font-size="20">⇆</text>`;
}
if(s===1){
h+=lattice(ox1,oy,[22,7],[6,20],"#378ADD",2.5,8,true,"#378ADD",22);
h+=lattice(ox2,oy,[48,16],[12,45],"#D85A30",3.5,3,true,"#D85A30",48);
h+=`<text x="${ox1}" y="${oy+75}" text-anchor="middle" fill="#378ADD" font-size="12" font-family="var(--font)">λ₁ klein ↓</text>`;
h+=`<text x="${ox2}" y="${oy+75}" text-anchor="middle" fill="#D85A30" font-size="12" font-family="var(--font)">λ₁* groß ↑</text>`;
h+=`<text x="320" y="${oy+75}" text-anchor="middle" fill="var(--text3)" font-size="20">⇆</text>`;
}
if(s===2){
const b1D=[14,5],b2D=[4,15];
h+=lattice(ox1,oy,[55,18],[15,50],"#378ADD",3.5,4,true,"#E24B4A",40);
h+=`<text x="${ox1}" y="${oy+80}" text-anchor="middle" fill="#1D9E75" font-size="12" font-weight="500" font-family="var(--font)">Kein Punkt im Kreis!</text>`;
for(let i=-10;i<=10;i++){const x1=ox2+i*b1D[0]-10*b2D[0],y1=oy-(i*b1D[1]-10*b2D[1]),x2=ox2+i*b1D[0]+10*b2D[0],y2=oy-(i*b1D[1]+10*b2D[1]);h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="var(--border)" stroke-width="0.2"/>`;}
for(let j=-10;j<=10;j++){const x1=ox2-10*b1D[0]+j*b2D[0],y1=oy-(-10*b1D[1]+j*b2D[1]),x2=ox2+10*b1D[0]+j*b2D[0],y2=oy-(10*b1D[1]+j*b2D[1]);h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="var(--border)" stroke-width="0.2"/>`;}
for(let i=-10;i<=10;i++) for(let j=-10;j<=10;j++){const x=ox2+i*b1D[0]+j*b2D[0],y=oy-(i*b1D[1]+j*b2D[1]);if(x>325&&x<635&&y>20&&y<310){const isO=i===0&&j===0;const d=Math.sqrt((i*b1D[0]+j*b2D[0])**2+(i*b1D[1]+j*b2D[1])**2);if(!isO&&d<=22){h+=`<circle cx="${x}" cy="${y}" r="6" fill="none" stroke="#EF9F27" stroke-width="1.5"/>`;h+=`<circle cx="${x}" cy="${y}" r="3" fill="#EF9F27"/>`;}else{h+=`<circle cx="${x}" cy="${y}" r="${isO?4:2.5}" fill="#D85A30" opacity="${isO?1:0.5}"/>`;}}}
h+=`<text x="${ox2}" y="${oy+80}" text-anchor="middle" fill="#EF9F27" font-size="12" font-weight="500" font-family="var(--font)">Kurze duale Vektoren = Beweis</text>`;
h+=`<path d="M320 ${oy+55} C 360 ${oy+35}, 400 ${oy+35}, 440 ${oy+55}" fill="none" stroke="var(--text3)" stroke-width="0.8" stroke-dasharray="3 3" marker-end="url(#a2)"/>`;
h+=`<text x="380" y="${oy+43}" text-anchor="middle" fill="var(--text3)" font-size="10" font-family="var(--font)">beweist</text>`;
}
svg.innerHTML=h;
document.querySelectorAll('#v2nav .step-btn').forEach((b,i)=>b.classList.toggle('active',i===s));
document.getElementById('v2cap').innerHTML=steps[s].desc;
}
const nav=document.getElementById('v2nav');
steps.forEach((s,i)=>{const b=document.createElement('button');b.className='step-btn';b.textContent=s.label;b.onclick=()=>draw(i);nav.appendChild(b);});
draw(0);
})();
</script>
<div class="merkbox">
<div class="merkbox-title">Der coNP-Beweis in einem Satz</div>
Du beweist Abwesenheit (kein kurzer Vektor im Gitter) durch Anwesenheit (kurze Vektoren im dualen Gitter). Wegen der Wippe (Transference-Theorem) schließt das eine das andere aus.
</div>
<p>Fun Fact: Aharonov & Regev haben das zuerst quantenmechanisch bewiesen (QMA) und dann "dequantisiert" — den Quantenbeweis in einen klassischen umgewandelt.</p>
<!-- ═══════════════════════════════════════ -->
<h2>4. Worst-Case-to-Average-Case-Reduktion</h2>
<h3>Das Problem mit RSA</h3>
<p>RSA sagt: "Faktorisieren zufälliger Zahlen ist hoffentlich schwer." Aber es gibt keinen Beweis dafür. Vielleicht sind 99% der zufälligen Instanzen leicht — dann wäre RSA unsicher. Bogdanov & Trevisan haben gezeigt, dass so eine Worst-Case-to-Average-Case-Verbindung für allgemeine NP-Probleme vermutlich unmöglich ist.</p>
<h3>Ajtais Durchbruch (1996)</h3>
<p>Für Gitter ist es anders: Wenn du <em>zufällige</em> SIS-Instanzen lösen kannst, kannst du <em>jede beliebige</em> Worst-Case-SVP-Instanz lösen. Die Reduktion baut aus der schwierigsten SVP-Instanz zufällige SIS-Instanzen. Löst jemand die, kannst du die Lösung zurückübersetzen.</p>
<p><strong>SIS (Short Integer Solution):</strong> Gegeben eine zufällige Matrix A, finde einen kurzen Vektor z mit Az = 0 mod q.</p>
<div class="merkbox">
<div class="merkbox-title">Warum das einzigartig ist</div>
Bei Gittern gibt es keine "leichten zufälligen Instanzen". Entweder ALLE sind schwer, oder ALLE sind leicht. Es gibt kein Dazwischen. Das ist bei keinem anderen kryptografisch relevanten Problem der Fall.
</div>
<!-- Viz 3: Reduction chain -->
<div class="viz-container" id="viz3-wrap">
<div class="step-nav" id="v3nav"></div>
<svg id="v3svg" width="100%" viewBox="0 0 640 420"></svg>
<div class="viz-caption" id="v3cap"></div>
</div>
<script>
(function(){
const steps=[
{label:"1. RSA vs Gitter",desc:`<strong>Links RSA:</strong> Mischung aus leichten und schweren Instanzen, keine Verbindung zum Worst-Case. <strong>Rechts Gitter:</strong> Alle gleich schwer, durch Reduktion bewiesen.`},
{label:"2. Die volle Kette",desc:`<strong>Die komplette Sicherheitsargumentation:</strong> Jeder Pfeil ist eine bewiesene Reduktion. Kyber brechen = SVP im Worst-Case lösen. Kein bekannter klassischer oder Quantenalgorithmus kann das.`},
];
function draw(s){
const svg=document.getElementById('v3svg');
let h=`<defs><marker id="a3" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker></defs>`;
const cx=320;
if(s===0){
h+=`<text x="160" y="32" text-anchor="middle" fill="var(--text2)" font-size="14" font-weight="500" font-family="var(--font)">RSA / Faktorisierung</text>`;
h+=`<text x="480" y="32" text-anchor="middle" fill="var(--text2)" font-size="14" font-weight="500" font-family="var(--font)">Gitter / SVP</text>`;
h+=`<line x1="320" y1="16" x2="320" y2="400" stroke="var(--border)" stroke-width="0.5" stroke-dasharray="6 4"/>`;
h+=`<text x="160" y="62" text-anchor="middle" fill="var(--text3)" font-size="12" font-family="var(--font)">Zufällige Instanzen</text>`;
const rsaX=[50,92,134,176,218];
rsaX.forEach((x,i)=>{const c=i===3?"#F09595":"#97C459";h+=`<rect x="${x}" y="74" width="36" height="36" rx="6" fill="${c}" fill-opacity="0.25" stroke="${c}" stroke-width="0.5"/>`;});
h+=`<text x="86" y="98" text-anchor="middle" fill="#639922" font-size="10" font-family="var(--font)">leicht</text>`;
h+=`<text x="194" y="98" text-anchor="middle" fill="#E24B4A" font-size="10" font-family="var(--font)">schwer</text>`;
h+=`<text x="160" y="136" text-anchor="middle" fill="var(--text3)" font-size="12" font-family="var(--font)">Worst-Case</text>`;
h+=`<rect x="110" y="146" width="100" height="36" rx="6" fill="#F09595" fill-opacity="0.25" stroke="#E24B4A" stroke-width="0.5"/>`;
h+=`<text x="160" y="170" text-anchor="middle" fill="#E24B4A" font-size="11" font-family="var(--font)">sehr schwer</text>`;
h+=`<text x="160" y="212" text-anchor="middle" fill="#E24B4A" font-size="12" font-family="var(--font)">Keine Verbindung!</text>`;
h+=`<text x="480" y="62" text-anchor="middle" fill="var(--text3)" font-size="12" font-family="var(--font)">Zufällige Instanzen</text>`;
for(let i=0;i<5;i++){h+=`<rect x="${370+i*42}" y="74" width="36" height="36" rx="6" fill="#F09595" fill-opacity="0.25" stroke="#E24B4A" stroke-width="0.5"/>`;h+=`<text x="${388+i*42}" y="98" text-anchor="middle" fill="#E24B4A" font-size="10" font-family="var(--font)">schwer</text>`;}
h+=`<text x="480" y="136" text-anchor="middle" fill="var(--text3)" font-size="12" font-family="var(--font)">Worst-Case</text>`;
h+=`<rect x="430" y="146" width="100" height="36" rx="6" fill="#F09595" fill-opacity="0.25" stroke="#E24B4A" stroke-width="0.5"/>`;
h+=`<text x="480" y="170" text-anchor="middle" fill="#E24B4A" font-size="11" font-family="var(--font)">sehr schwer</text>`;
h+=`<line x1="480" y1="114" x2="480" y2="142" stroke="#1D9E75" stroke-width="1.5" marker-end="url(#a3)"/>`;
h+=`<line x1="480" y1="184" x2="480" y2="114" stroke="#1D9E75" stroke-width="1.5" marker-start="url(#a3)"/>`;
h+=`<text x="512" y="134" fill="#1D9E75" font-size="11" font-weight="500" font-family="var(--font)">= gleich schwer!</text>`;
h+=`<rect x="40" y="270" width="230" height="56" rx="8" fill="#F09595" fill-opacity="0.12" stroke="#E24B4A" stroke-width="0.5"/>`;
h+=`<text x="155" y="294" text-anchor="middle" fill="#E24B4A" font-size="13" font-weight="500" font-family="var(--font)">Sicherheit = Hoffnung</text>`;
h+=`<text x="155" y="312" text-anchor="middle" fill="#E24B4A" font-size="11" font-family="var(--font)">"Hoffentlich schwer"</text>`;
h+=`<rect x="370" y="270" width="230" height="56" rx="8" fill="#5DCAA5" fill-opacity="0.12" stroke="#1D9E75" stroke-width="0.5"/>`;
h+=`<text x="485" y="294" text-anchor="middle" fill="#1D9E75" font-size="13" font-weight="500" font-family="var(--font)">Sicherheit = Beweis</text>`;
h+=`<text x="485" y="312" text-anchor="middle" fill="#1D9E75" font-size="11" font-family="var(--font)">"Beweisbar schwer"</text>`;
}
if(s===1){
const levels=[
{y:30,label:"Worst-Case GapSVP/SIVP",sub:"Faktor Õ(n)",color:"#E24B4A",bg:"#F09595"},
{y:110,label:"Average-Case SIS",sub:"Ajtai 1996, Micciancio-Regev 2007",color:"#BA7517",bg:"#EF9F27"},
{y:190,label:"Average-Case LWE",sub:"Regev 2005, Peikert 2009",color:"#534AB7",bg:"#AFA9EC"},
{y:270,label:"ML-KEM / ML-DSA",sub:"NIST FIPS 203 & 204, August 2024",color:"#0F6E56",bg:"#5DCAA5"},
];
levels.forEach((lv,i)=>{
h+=`<rect x="120" y="${lv.y}" width="400" height="56" rx="8" fill="${lv.bg}" fill-opacity="0.15" stroke="${lv.color}" stroke-width="0.5"/>`;
h+=`<text x="${cx}" y="${lv.y+24}" text-anchor="middle" fill="${lv.color}" font-size="14" font-weight="500" font-family="var(--font)">${lv.label}</text>`;
h+=`<text x="${cx}" y="${lv.y+42}" text-anchor="middle" fill="${lv.color}" font-size="11" font-family="var(--font)" opacity="0.8">${lv.sub}</text>`;
if(i<levels.length-1){h+=`<line x1="${cx}" y1="${lv.y+60}" x2="${cx}" y2="${levels[i+1].y-4}" stroke="var(--text3)" stroke-width="1.5" marker-end="url(#a3)"/>`;}
});
h+=`<rect x="120" y="360" width="400" height="44" rx="8" fill="var(--bg2)" stroke="var(--border)" stroke-width="0.5"/>`;
h+=`<text x="${cx}" y="386" text-anchor="middle" fill="var(--text2)" font-size="12" font-weight="500" font-family="var(--font)">Kyber brechen = SVP im Worst-Case lösen</text>`;
}
svg.innerHTML=h;
document.querySelectorAll('#v3nav .step-btn').forEach((b,i)=>b.classList.toggle('active',i===s));
document.getElementById('v3cap').innerHTML=steps[s].desc;
}
const nav=document.getElementById('v3nav');
steps.forEach((s,i)=>{const b=document.createElement('button');b.className='step-btn';b.textContent=s.label;b.onclick=()=>draw(i);nav.appendChild(b);});
draw(0);
})();
</script>
<!-- ═══════════════════════════════════════ -->
<h2>5. Algorithmen</h2>
<h3>LLL (Lenstra-Lenstra-Lovász, 1982)</h3>
<p>Nimmt eine "schlechte" Basis und macht sie "besser". Zwei Bedingungen:</p>
<p><strong>Größenreduktion:</strong> Gram-Schmidt-Koeffizienten |μ| ≤ ½ — jeder Vektor zeigt so wenig wie möglich in Richtung der vorherigen.</p>
<p><strong>Lovász-Bedingung:</strong> Die Gram-Schmidt-Vektoren dürfen nicht zu schnell kürzer werden.</p>
<p>Funktioniert wie Bubble Sort — vergleiche Nachbarn, tausche wenn nötig. Polynomielle Laufzeit, aber exponentieller Approximationsfaktor 2^{(n-1)/2}.</p>
<!-- Viz 4: LLL -->
<div class="viz-container" id="viz4-wrap">
<div class="step-nav" id="v4nav"></div>
<svg id="v4svg" width="100%" viewBox="0 0 640 340"></svg>
<div class="viz-caption" id="v4cap"></div>
</div>
<script>
(function(){
const ox=320,oy=190;
const badB1=[140,10],badB2=[130,50];
const goodB1=[50,40],goodB2=[-30,50];
function len(v){return Math.sqrt(v[0]*v[0]+v[1]*v[1]);}
function dot(a,b){return a[0]*b[0]+a[1]*b[1];}
function angle(a,b){return Math.acos(dot(a,b)/(len(a)*len(b)))*180/Math.PI;}
const steps=[
{label:"Schlechte Basis",b1:badB1,b2:badB2,desc:`<strong>Schlechte Basis:</strong> Fast parallele Vektoren (${Math.round(angle(badB1,badB2))}°). Der kürzeste Vektor λ₁ ist viel kürzer als beide Basisvektoren.`},
{label:"LLL-reduziert",b1:goodB1,b2:goodB2,desc:`<strong>Nach LLL:</strong> Fast senkrechte Vektoren (${Math.round(angle(goodB1,goodB2))}°). b₁ ist jetzt nah an λ₁. In 2D fast perfekt, in hoher Dimension wird der Faktor exponentiell.`},
];
function draw(s){
const st=steps[s],b1=st.b1,b2=st.b2;
let h=`<defs><marker id="a4" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker></defs>`;
for(let i=-6;i<=6;i++) for(let j=-6;j<=6;j++){const x=ox+i*b1[0]+j*b2[0],y=oy-(i*b1[1]+j*b2[1]);if(x>10&&x<630&&y>10&&y<330){const isO=i===0&&j===0;h+=`<circle cx="${x}" cy="${y}" r="${isO?4:2.5}" fill="#5DCAA5" opacity="${isO?1:0.5}"/>`;}}
let minD=Infinity,sv=[0,0];
for(let i=-3;i<=3;i++) for(let j=-3;j<=3;j++){if(i===0&&j===0)continue;const vx=i*b1[0]+j*b2[0],vy=i*b1[1]+j*b2[1],d=Math.sqrt(vx*vx+vy*vy);if(d<minD){minD=d;sv=[vx,vy];}}
h+=`<line x1="${ox}" y1="${oy}" x2="${ox+sv[0]}" y2="${oy-sv[1]}" stroke="#E24B4A" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.6"/>`;
h+=`<text x="${ox+sv[0]+(sv[0]>0?8:-30)}" y="${oy-sv[1]-6}" fill="#E24B4A" font-size="11" font-family="var(--font)" opacity="0.7">λ₁</text>`;
h+=`<line x1="${ox}" y1="${oy}" x2="${ox+b1[0]}" y2="${oy-b1[1]}" stroke="#378ADD" stroke-width="2.5" marker-end="url(#a4)"/>`;
h+=`<line x1="${ox}" y1="${oy}" x2="${ox+b2[0]}" y2="${oy-b2[1]}" stroke="#7F77DD" stroke-width="2.5" marker-end="url(#a4)"/>`;
h+=`<text x="${ox+b1[0]+8}" y="${oy-b1[1]-6}" fill="#378ADD" font-size="14" font-weight="500" font-family="var(--font)">b₁</text>`;
h+=`<text x="${ox+b2[0]+8}" y="${oy-b2[1]-6}" fill="#7F77DD" font-size="14" font-weight="500" font-family="var(--font)">b₂</text>`;
h+=`<text x="40" y="330" fill="var(--text2)" font-size="11" font-family="var(--mono)">‖b₁‖=${Math.round(len(b1))} ‖b₂‖=${Math.round(len(b2))} λ₁=${Math.round(minD)} Faktor=‖b₁‖/λ₁=${(len(b1)/minD).toFixed(2)}</text>`;
document.getElementById('v4svg').innerHTML=h;
document.querySelectorAll('#v4nav .step-btn').forEach((b,i)=>b.classList.toggle('active',i===s));
document.getElementById('v4cap').innerHTML=st.desc;
}
const nav=document.getElementById('v4nav');
steps.forEach((s,i)=>{const b=document.createElement('button');b.className='step-btn';b.textContent=s.label;b.onclick=()=>draw(i);nav.appendChild(b);});
draw(0);
})();
</script>
<h3>Exakte Algorithmen</h3>
<p><strong>Enumeration (Kannan 1983):</strong> Erst Basis reduzieren, dann systematisch alle Vektoren durchprobieren. Wie Baumsuche mit Pruning. Laufzeit n^{O(n)} (superexponentiell), aber nur poly(n) Speicher. Praxistauglich bis Dimension ~60-80.</p>
<p><strong>Sieving (AKS 2001):</strong> Starte mit vielen zufälligen Gittervektoren, finde nahe Paare, ersetze durch ihre Differenz. Wie ein Sieb, das immer kürzere Vektoren erzeugt. Laufzeit 2^{n+o(n)} (besser), aber auch 2^{n+o(n)} Speicher (schlechter).</p>
<h3>Übersichtstabelle</h3>
<table style="width:100%;border-collapse:collapse;font-size:14px;margin:16px 0;">
<tr style="border-bottom:2px solid var(--border);">
<th style="text-align:left;padding:8px;color:var(--text2);">Algorithmus</th>
<th style="text-align:left;padding:8px;color:var(--text2);">Faktor γ</th>
<th style="text-align:left;padding:8px;color:var(--text2);">Laufzeit</th>
<th style="text-align:left;padding:8px;color:var(--text2);">Speicher</th>
</tr>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;">LLL (1982)</td><td style="padding:8px;font-family:var(--mono);font-size:13px;">2^{(n-1)/2}</td><td style="padding:8px;color:var(--teal);">poly(n)</td><td style="padding:8px;color:var(--teal);">poly(n)</td>
</tr>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;">BKZ-k</td><td style="padding:8px;font-family:var(--mono);font-size:13px;">2^{O(n/k)}</td><td style="padding:8px;">2^{O(k)}</td><td style="padding:8px;color:var(--teal);">poly(n)</td>
</tr>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;">Enumeration (1983)</td><td style="padding:8px;font-family:var(--mono);font-size:13px;">1 (exakt)</td><td style="padding:8px;">n^{O(n)}</td><td style="padding:8px;color:var(--teal);">poly(n)</td>
</tr>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;">Sieving (2001)</td><td style="padding:8px;font-family:var(--mono);font-size:13px;">1 (exakt)</td><td style="padding:8px;">2^{n+o(n)}</td><td style="padding:8px;color:var(--amber);">2^{n+o(n)}</td>
</tr>
<tr>
<td style="padding:8px;">Voronoi (2010)</td><td style="padding:8px;font-family:var(--mono);font-size:13px;">1 (exakt)</td><td style="padding:8px;">Õ(4^n)</td><td style="padding:8px;color:var(--amber);">Õ(2^n)</td>
</tr>
</table>
<div class="prof-box">
<div class="prof-box-title">Offene Frage (kann der Prof fragen)</div>
Kann SVP in 2^{O(n)} Zeit mit 2^{o(n)} Speicher gelöst werden? Also das Beste aus Enumeration (wenig Speicher) und Sieving (wenig Zeit)?
</div>
<!-- ═══════════════════════════════════════ -->
<h2>6. Post-Quantum-Krypto (Kurzfassung für den Vortrag)</h2>
<p>RSA und ECC werden durch Shors Algorithmus gebrochen. Die NIST-Standards seit August 2024 basieren auf Gitterproblemen:</p>
<p><strong>ML-KEM (Kyber):</strong> Schlüsselaustausch, basiert auf Module-LWE.</p>
<p><strong>ML-DSA (Dilithium):</strong> Digitale Signaturen, basiert auf Module-LWE + Module-SIS.</p>
<p><strong>SLH-DSA (SPHINCS+):</strong> Hashbasiertes Backup, falls Gitter gebrochen werden.</p>
<div class="merkbox">
<div class="merkbox-title">Der Schlüsselsatz für deinen Vortrag</div>
"Die Sicherheit von Kyber und Dilithium basiert nicht auf der Hoffnung, dass zufällige Instanzen schwer sind — sondern auf der beweisbaren Worst-Case-Härte von SVP. Das ist eine fundamental stärkere Aussage als alles, was RSA bieten kann."
</div>
<!-- ═══════════════════════════════════════ -->
<h2>7. Wahrscheinliche Prof-Fragen</h2>
<div class="prof-box">
<div class="prof-box-title">1. Warum ist SVP für Post-Quantum-Krypto relevant?</div>
Worst-Case-Härte überträgt sich auf Average-Case. Kein bekannter Quantenvorteil. NIST-Standards basieren darauf.
</div>
<div class="prof-box">
<div class="prof-box-title">2. Was leistet LLL, und wo sind seine Grenzen?</div>
Polynomielle Laufzeit, aber Approximationsfaktor 2^{(n-1)/2} — exponentiell in der Dimension. Reicht für kleine Dimensionen, nicht für kryptografische Parameter (n ≈ 1000).
</div>
<div class="prof-box">
<div class="prof-box-title">3. Was ist der Unterschied zwischen SVP und CVP?</div>
SVP: kürzester Nicht-Null-Vektor im Gitter (Länge = λ₁). CVP: nächster Gitterpunkt zu einem externen Punkt t ∉ L. SVP ≤<sub>p</sub> CVP — man kann SVP auf CVP reduzieren (Einbettungstrick: verdopple die Basis und wähle t so, dass der nächste Gitterpunkt dem kürzesten Vektor entspricht). Umkehrung unbekannt. GapCVP ist ebenfalls NP-hart und liegt für große γ in NP ∩ coNP.
</div>
<div class="prof-box">
<div class="prof-box-title">4. Was bedeutet die Worst-Case-to-Average-Case-Reduktion?</div>
Ajtai 1996: Zufällige SIS-Instanzen lösen = Worst-Case-SVP lösen. Einzigartig — bei RSA/SAT gibt es das nicht. Bogdanov & Trevisan zeigten Barrieren für allgemeine NP-Probleme.
</div>
<div class="prof-box">
<div class="prof-box-title">5. Wie ordnet sich SVP in die Komplexitätslandschaft ein?</div>
NP-hart für exakte Lösung (randomisierte Reduktion), für γ ≈ √n in NP ∩ coNP, für γ = 2^{O(n)} in P. Die genaue Grenze ist offen.
</div>
<div class="prof-box">
<div class="prof-box-title">6. Was ist LWE?</div>
Gleichungssystem b = As + e mit kleinem Fehler e. Ohne Fehler trivial (Gauß-Elimination), mit Fehler schwer. Regev 2005: LWE lösen → GapSVP im Worst-Case lösen (braucht Quantenreduktion). Peikert 2009: klassisch, aber nur für große Moduli.
</div>
<hr>
<p style="color:var(--text3);font-size:13px;margin-top:32px;">Zuletzt aktualisiert: April 2026. Alle Visualisierungen sind interaktiv — klick dich durch die Tabs.</p>
</body>
</html>