Mehdi BEN BARKA
Initial deploy: pass@k MSE widget SWE-bench Lite
2a548b3
Raw
History Blame Contribute Delete
22.9 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>pass@k — Homogène vs Dynamique sur SWE-bench Lite</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/dist/tabler-icons.min.css">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--color-background-primary: #ffffff;
--color-background-secondary: #f5f5f4;
--color-background-tertiary: #f0efed;
--color-text-primary: #1a1a1a;
--color-text-secondary: #6b7280;
--color-text-tertiary: #9ca3af;
--color-border-tertiary: rgba(0,0,0,0.08);
--color-border-secondary: rgba(0,0,0,0.15);
--border-radius-md: 8px;
--border-radius-lg: 12px;
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background-primary: #1a1a1a;
--color-background-secondary: #262626;
--color-background-tertiary: #2a2a2a;
--color-text-primary: #f5f5f4;
--color-text-secondary: #a1a1aa;
--color-text-tertiary: #71717a;
--color-border-tertiary: rgba(255,255,255,0.08);
--color-border-secondary: rgba(255,255,255,0.15);
}
}
body {
font-family: var(--font-sans);
background: var(--color-background-tertiary);
color: var(--color-text-primary);
padding: 2rem;
min-height: 100vh;
}
.container {
max-width: 720px;
margin: 0 auto;
background: var(--color-background-primary);
border-radius: var(--border-radius-lg);
padding: 1.5rem;
border: 0.5px solid var(--color-border-tertiary);
}
h1 {
font-size: 16px;
font-weight: 500;
margin-bottom: 4px;
color: var(--color-text-primary);
}
.subtitle {
font-size: 12px;
color: var(--color-text-secondary);
margin-bottom: 1.5rem;
line-height: 1.5;
}
/* Form elements */
input[type=range] {
accent-color: #378add;
}
button {
color: var(--color-text-primary);
background: var(--color-background-secondary);
border: 0.5px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
cursor: pointer;
font-family: var(--font-sans);
}
button:hover { background: var(--color-background-tertiary); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
</style>
</head>
<body>
<div class="container">
<h1>pass@k — Homogène vs Dynamique (Algo 2)</h1>
<p class="subtitle">
Simulation Monte Carlo sur SWE-bench Lite (300 tâches, n=250 runs/tâche oracle) ·
Plan factoriel seeds monde × seeds ordre · MSE, biais² et variance en pp²<br>
Données : Jimenez et al. 2024 · Méthode dynamique : Kazdan et al. 2025 (arXiv 2510.05197)
</p>
<h2 class="sr-only">Comparaison biais, variance et MSE entre allocation homogène et dynamique sur SWE-bench Lite</h2>
<div style="padding:1rem 0 0;">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;">
<label style="font-size:13px;color:var(--color-text-secondary);min-width:96px;">n (runs/tâche)</label>
<input type="range" min="2" max="60" step="1" value="10" id="sl-n" style="flex:1;">
<span style="font-size:13px;font-weight:500;min-width:32px;text-align:right;" id="vn">10</span>
</div>
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;">
<label style="font-size:13px;color:var(--color-text-secondary);min-width:96px;">T (nb tâches)</label>
<input type="range" min="10" max="300" step="10" value="100" id="sl-T" style="flex:1;">
<span style="font-size:13px;font-weight:500;min-width:32px;text-align:right;" id="vT">100</span>
</div>
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;">
<label style="font-size:13px;color:var(--color-text-secondary);min-width:96px;">k (pass@k)</label>
<input type="range" min="1" max="20" step="1" value="5" id="sl-k" style="flex:1;">
<span style="font-size:13px;font-weight:500;min-width:32px;text-align:right;" id="vk">5</span>
</div>
<div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;">
<label style="font-size:13px;color:var(--color-text-secondary);min-width:96px;">seeds monde</label>
<input type="range" min="1" max="10" step="1" value="5" id="sl-sw" style="flex:1;">
<span style="font-size:13px;font-weight:500;min-width:32px;text-align:right;" id="vsw">5</span>
<label style="font-size:13px;color:var(--color-text-secondary);min-width:76px;text-align:right;">seeds ordre</label>
<input type="range" min="1" max="10" step="1" value="5" id="sl-so" style="flex:1;">
<span style="font-size:13px;font-weight:500;min-width:32px;text-align:right;" id="vso">5</span>
</div>
<button id="runbtn" onclick="runAll()" style="width:100%;padding:9px;font-size:13px;font-weight:500;background:var(--color-background-secondary);border:0.5px solid var(--color-border-secondary);border-radius:8px;cursor:pointer;margin-bottom:16px;color:var(--color-text-primary);">
<i class="ti ti-player-play" style="vertical-align:-2px;margin-right:4px;" aria-hidden="true"></i>Lancer la simulation
</button>
<div style="background:var(--color-background-secondary);border-radius:10px;padding:12px 14px;margin-bottom:16px;">
<div style="display:grid;grid-template-columns:auto 1fr 1fr;gap:8px 16px;align-items:center;font-size:13px;">
<div></div>
<div style="text-align:center;font-weight:500;color:#378add;">Homogène</div>
<div style="text-align:center;font-weight:500;color:#e2855a;">Dynamique</div>
<div style="color:var(--color-text-secondary);">Biais (pp)</div>
<div style="text-align:center;" id="t-hbias"></div>
<div style="text-align:center;" id="t-dbias"></div>
<div style="color:var(--color-text-secondary);">Variance (pp²)</div>
<div style="text-align:center;" id="t-hvar"></div>
<div style="text-align:center;" id="t-dvar"></div>
<div style="color:var(--color-text-secondary);font-weight:500;border-top:0.5px solid var(--color-border-tertiary);padding-top:8px;">MSE (pp²)</div>
<div style="text-align:center;font-weight:500;border-top:0.5px solid var(--color-border-tertiary);padding-top:8px;" id="t-hmse"></div>
<div style="text-align:center;font-weight:500;border-top:0.5px solid var(--color-border-tertiary);padding-top:8px;" id="t-dmse"></div>
</div>
<div style="text-align:center;margin-top:12px;padding-top:10px;border-top:0.5px solid var(--color-border-tertiary);font-size:13px;">
<span style="color:var(--color-text-secondary);">Méthode la plus précise (MSE min) : </span>
<span style="font-weight:500;" id="t-winner"></span>
</div>
</div>
<div style="display:flex;gap:0;margin-bottom:14px;border-bottom:1px solid var(--color-border-tertiary);">
<button id="tab-mse" onclick="switchTab('mse')" style="padding:7px 12px;font-size:13px;background:none;border:none;border-bottom:2px solid #378add;color:var(--color-text-primary);font-weight:500;cursor:pointer;margin-bottom:-1px;">MSE vs k</button>
<button id="tab-msen" onclick="switchTab('msen')" style="padding:7px 12px;font-size:13px;background:none;border:none;border-bottom:2px solid transparent;color:var(--color-text-secondary);cursor:pointer;margin-bottom:-1px;">MSE vs n</button>
<button id="tab-mseT" onclick="switchTab('mseT')" style="padding:7px 12px;font-size:13px;background:none;border:none;border-bottom:2px solid transparent;color:var(--color-text-secondary);cursor:pointer;margin-bottom:-1px;">MSE vs T</button>
<button id="tab-decomp" onclick="switchTab('decomp')" style="padding:7px 12px;font-size:13px;background:none;border:none;border-bottom:2px solid transparent;color:var(--color-text-secondary);cursor:pointer;margin-bottom:-1px;">Biais²/Var</button>
</div>
<div id="legend-line" style="display:flex;gap:18px;margin-bottom:10px;font-size:12px;color:var(--color-text-secondary);">
<span style="display:flex;align-items:center;gap:6px;"><span style="width:20px;height:2px;background:#378add;display:inline-block;"></span>Homogène</span>
<span style="display:flex;align-items:center;gap:6px;"><span style="width:20px;height:2px;background:#e2855a;display:inline-block;"></span>Dynamique</span>
</div>
<div style="position:relative;width:100%;height:290px;">
<canvas id="myChart" role="img" aria-label="MSE des deux méthodes">Comparaison de l'erreur quadratique moyenne des deux méthodes.</canvas>
</div>
<p id="status" style="font-size:12px;color:var(--color-text-tertiary);margin-top:10px;text-align:center;">Règle les paramètres puis lance la simulation.</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>
<script>
const RAW=[{"n":250,"c":18},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":193},{"n":250,"c":7},{"n":250,"c":0},{"n":250,"c":181},{"n":250,"c":2},{"n":250,"c":1},{"n":250,"c":0},{"n":250,"c":235},{"n":250,"c":113},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":91},{"n":250,"c":0},{"n":250,"c":236},{"n":250,"c":28},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":235},{"n":250,"c":196},{"n":250,"c":1},{"n":250,"c":220},{"n":250,"c":99},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":57},{"n":250,"c":220},{"n":250,"c":19},{"n":250,"c":196},{"n":250,"c":220},{"n":250,"c":228},{"n":250,"c":220},{"n":250,"c":113},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":220},{"n":250,"c":196},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":220},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":0},{"n":250,"c":241},{"n":250,"c":0}];
function mb32(s){return function(){let t=s+=0x6D2B79F5;t=Math.imul(t^t>>>15,t|1);t^=t+Math.imul(t^t>>>7,t|61);return((t^t>>>14)>>>0)/4294967296;};}
function lgamma(x){const g=7,c=[0.99999999999980993,676.5203681218851,-1259.1392167224028,771.32342877765313,-176.61502916214059,12.507343278686905,-0.13857109526572012,9.9843695780195716e-6,1.5056327351493116e-7];if(x<0.5)return Math.log(Math.PI/Math.sin(Math.PI*x))-lgamma(1-x);x-=1;let a=c[0];const t=x+g+0.5;for(let i=1;i<g+2;i++)a+=c[i]/(x+i);return 0.5*Math.log(2*Math.PI)+(x+0.5)*Math.log(t)-t+Math.log(a);}
function logB(n,k){if(k<0||k>n)return -Infinity;return lgamma(n+1)-lgamma(k+1)-lgamma(n-k+1);}
function betaln(a,b){return lgamma(a)+lgamma(b)-lgamma(a+b);}
function sampleTasks(T,rng){const idx=Array.from({length:RAW.length},(_,i)=>i);for(let i=idx.length-1;i>0;i--){const j=Math.floor(rng()*(i+1));[idx[i],idx[j]]=[idx[j],idx[i]];}return idx.slice(0,T).map(i=>RAW[i]);}
function oracle(tasks,k){let s=0;for(const t of tasks){const v=logB(t.n-t.c,k)-logB(t.n,k);s+=v===-Infinity?1:1-Math.exp(v);}return s/tasks.length;}
function buildPools(tasks,rng){return tasks.map(t=>{const arr=new Int8Array(t.n);for(let i=0;i<t.c;i++)arr[i]=1;for(let i=arr.length-1;i>0;i--){const j=Math.floor(rng()*(i+1));const tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}return arr;});}
function homogEst(tasks,n,k,rng){
const pools=buildPools(tasks,rng);let s=0;
for(let i=0;i<tasks.length;i++){let c=0;const p=pools[i];for(let r=0;r<n;r++)c+=p[r]||0;const v=logB(n-c,k)-logB(n,k);s+=v===-Infinity?1:1-Math.exp(v);}
return s/tasks.length;
}
function nelderMead(f,x0){let sim=[x0.slice(),[x0[0]+0.5,x0[1]],[x0[0],x0[1]+0.5]];let fv=sim.map(p=>f(p[0],p[1]));for(let it=0;it<300;it++){const ord=[0,1,2].sort((a,b)=>fv[a]-fv[b]);sim=ord.map(i=>sim[i]);fv=ord.map(i=>fv[i]);if(Math.abs(fv[2]-fv[0])<1e-6)break;const cx=(sim[0][0]+sim[1][0])/2,cy=(sim[0][1]+sim[1][1])/2;const rx=cx+(cx-sim[2][0]),ry=cy+(cy-sim[2][1]);const fr=f(rx,ry);if(fr<fv[0]){const ex=cx+2*(rx-cx),ey=cy+2*(ry-cy);const fe=f(ex,ey);if(fe<fr){sim[2]=[ex,ey];fv[2]=fe;}else{sim[2]=[rx,ry];fv[2]=fr;}}else if(fr<fv[1]){sim[2]=[rx,ry];fv[2]=fr;}else{const cx2=cx+0.5*(sim[2][0]-cx),cy2=cy+0.5*(sim[2][1]-cy);const fc=f(cx2,cy2);if(fc<fv[2]){sim[2]=[cx2,cy2];fv[2]=fc;}else{for(let i=1;i<3;i++){sim[i]=[sim[0][0]+0.5*(sim[i][0]-sim[0][0]),sim[0][1]+0.5*(sim[i][1]-sim[0][1])];fv[i]=f(sim[i][0],sim[i][1]);}}}}return sim[0];}
function dynEst(tasks,budget,k,rng){
const pools=buildPools(tasks,rng);const ptr=new Int32Array(tasks.length);const m=tasks.length;
const succ=new Int32Array(m),att=new Int32Array(m);
for(let t=0;t<budget;t++){
let sMin=Infinity;for(let i=0;i<m;i++)if(succ[i]<sMin)sMin=succ[i];
let aMin=Infinity;for(let i=0;i<m;i++)if(succ[i]===sMin&&att[i]<aMin)aMin=att[i];
const H=[];for(let i=0;i<m;i++)if(succ[i]===sMin&&att[i]===aMin)H.push(i);
const it=H[Math.floor(rng()*H.length)];att[it]++;
const p=pools[it];succ[it]+=(ptr[it]<p.length?p[ptr[it]++]:(rng()<tasks[it].c/tasks[it].n?1:0));
}
const fit=nelderMead((a,b)=>{if(a<=0||b<=0)return 1e10;const lab=betaln(a,b);let ll=0;for(let i=0;i<m;i++){if(att[i]===0)continue;ll+=logB(att[i],succ[i])+betaln(succ[i]+a,att[i]-succ[i]+b)-lab;}return-ll;},[1,1]);
const a=Math.max(1e-4,fit[0]),b=Math.max(1e-4,fit[1]);
return 1-Math.exp(betaln(a,b+k)-betaln(a,b));
}
function meanArr(a){return a.reduce((x,y)=>x+y,0)/a.length;}
function varArr(a){const m=meanArr(a);return meanArr(a.map(x=>(x-m)**2));}
function metrics(T,n,k,nw,no){
const hE=[],dE=[];
for(let w=0;w<nw;w++){
const tasks=sampleTasks(T,mb32(1000+w*37));
const truth=oracle(tasks,k);
for(let o=0;o<no;o++){
hE.push(homogEst(tasks,n,k,mb32(9000+w*100+o*7))-truth);
dE.push(dynEst(tasks,T*n,k,mb32(5000+w*100+o*13))-truth);
}
}
return{
hBias:meanArr(hE)*100, hVar:varArr(hE)*1e4, hMse:meanArr(hE.map(x=>x*x))*1e4,
dBias:meanArr(dE)*100, dVar:varArr(dE)*1e4, dMse:meanArr(dE.map(x=>x*x))*1e4
};
}
let tab='mse',ch=null;
function setTabStyle(a){['mse','msen','mseT','decomp'].forEach(t=>{const b=document.getElementById('tab-'+t);b.style.borderBottomColor=t===a?'#378add':'transparent';b.style.color=t===a?'var(--color-text-primary)':'var(--color-text-secondary)';b.style.fontWeight=t===a?'500':'400';});}
function updateTable(m){
document.getElementById('t-hbias').textContent=(m.hBias>=0?'+':'')+m.hBias.toFixed(3);
document.getElementById('t-dbias').textContent=(m.dBias>=0?'+':'')+m.dBias.toFixed(3);
document.getElementById('t-hvar').textContent=m.hVar.toFixed(3);
document.getElementById('t-dvar').textContent=m.dVar.toFixed(3);
document.getElementById('t-hmse').textContent=m.hMse.toFixed(3);
document.getElementById('t-dmse').textContent=m.dMse.toFixed(3);
document.getElementById('t-hmse').style.color=m.hMse<m.dMse?'#1D9E75':'var(--color-text-primary)';
document.getElementById('t-dmse').style.color=m.dMse<m.hMse?'#1D9E75':'var(--color-text-primary)';
const wEl=document.getElementById('t-winner');
wEl.textContent=(m.hMse<m.dMse?'Homogène':'Dynamique')+' (MSE '+Math.min(m.hMse,m.dMse).toFixed(3)+' vs '+Math.max(m.hMse,m.dMse).toFixed(3)+')';
wEl.style.color=m.hMse<m.dMse?'#378add':'#e2855a';
}
function renderLine(labels,h,d,xl){
document.getElementById('legend-line').style.display='flex';
if(ch)ch.destroy();
ch=new Chart(document.getElementById('myChart').getContext('2d'),{
type:'line',
data:{labels,datasets:[
{label:'Homogène',data:h,borderColor:'#378add',backgroundColor:'transparent',borderWidth:2,pointRadius:2,tension:0.25},
{label:'Dynamique',data:d,borderColor:'#e2855a',backgroundColor:'transparent',borderWidth:2,pointRadius:2,tension:0.25}
]},
options:{responsive:true,maintainAspectRatio:false,
plugins:{legend:{display:false},tooltip:{callbacks:{label:c=>c.dataset.label+': '+c.parsed.y.toFixed(3)+' pp²'}}},
scales:{
x:{title:{display:true,text:xl,color:'#888',font:{size:11}},ticks:{color:'#888',font:{size:10},maxTicksLimit:12},grid:{color:'rgba(128,128,128,0.1)'}},
y:{title:{display:true,text:'MSE (pp²)',color:'#888',font:{size:11}},ticks:{color:'#888',font:{size:10}},grid:{color:'rgba(128,128,128,0.1)'},min:0}
}
}
});
}
function renderBar(labels,datasets,xl){
document.getElementById('legend-line').style.display='none';
if(ch)ch.destroy();
ch=new Chart(document.getElementById('myChart').getContext('2d'),{
type:'bar',data:{labels,datasets},
options:{responsive:true,maintainAspectRatio:false,
plugins:{legend:{display:true,position:'top',labels:{font:{size:11},boxWidth:12,boxHeight:12,color:'#888'}},tooltip:{callbacks:{label:c=>c.dataset.label+': '+c.parsed.y.toFixed(3)+' pp²'}}},
scales:{
x:{stacked:true,title:{display:true,text:xl,color:'#888',font:{size:11}},ticks:{color:'#888',font:{size:10},maxTicksLimit:12},grid:{display:false}},
y:{stacked:true,title:{display:true,text:'pp²',color:'#888',font:{size:11}},ticks:{color:'#888',font:{size:10}},grid:{color:'rgba(128,128,128,0.1)'},min:0}
}
}
});
}
function runAll(){
const n=+document.getElementById('sl-n').value,T=+document.getElementById('sl-T').value,k=+document.getElementById('sl-k').value;
const nw=+document.getElementById('sl-sw').value,no=+document.getElementById('sl-so').value;
const btn=document.getElementById('runbtn'),status=document.getElementById('status');
btn.disabled=true; status.textContent='Simulation en cours…';
setTimeout(()=>{
updateTable(metrics(T,n,k,nw,no));
const sw=Math.min(nw,3),so=Math.min(no,3);
let labels=[],h=[],d=[];
if(tab==='mse'){
const kmax=Math.min(n,20);
for(let ki=1;ki<=kmax;ki++){const m=metrics(T,n,ki,sw,so);labels.push(ki);h.push(+m.hMse.toFixed(4));d.push(+m.dMse.toFixed(4));}
renderLine(labels,h,d,'k');
} else if(tab==='msen'){
const nmax=Math.min(60,250);const step=Math.max(1,Math.floor(nmax/16));
for(let ni=Math.max(k,2);ni<=nmax;ni+=step){const m=metrics(T,ni,k,sw,so);labels.push(ni);h.push(+m.hMse.toFixed(4));d.push(+m.dMse.toFixed(4));}
renderLine(labels,h,d,'n (runs/tâche)');
} else if(tab==='mseT'){
const tmax=Math.min(300,RAW.length);const step=Math.max(10,Math.floor(tmax/15));
for(let Ti=step;Ti<=tmax;Ti+=step){const m=metrics(Ti,n,k,sw,so);labels.push(Ti);h.push(+m.hMse.toFixed(4));d.push(+m.dMse.toFixed(4));}
renderLine(labels,h,d,'T (nb tâches)');
} else {
const kmax=Math.min(n,20);let hb=[],hv=[],db=[],dv=[];
for(let ki=1;ki<=kmax;ki++){const m=metrics(T,n,ki,sw,so);labels.push(ki);hb.push(+(m.hBias*m.hBias).toFixed(4));hv.push(+m.hVar.toFixed(4));db.push(+(m.dBias*m.dBias).toFixed(4));dv.push(+m.dVar.toFixed(4));}
renderBar(labels,[
{label:'Homog biais²',data:hb,backgroundColor:'#185fa5',stack:'H'},
{label:'Homog var',data:hv,backgroundColor:'#85b7eb',stack:'H'},
{label:'Dyn biais²',data:db,backgroundColor:'#993c1d',stack:'D'},
{label:'Dyn var',data:dv,backgroundColor:'#f0997b',stack:'D'}
],'k');
}
btn.disabled=false;
status.textContent=`Terminé — ${nw}×${no} seeds (table), ${sw}×${so} seeds (courbe).`;
},50);
}
function switchTab(t){tab=t;setTabStyle(t);runAll();}
['sl-n','sl-T','sl-k','sl-sw','sl-so'].forEach(id=>{
const key='v'+id.replace('sl-','');
document.getElementById(id).addEventListener('input',()=>document.getElementById(key).textContent=document.getElementById(id).value);
});
runAll();
</script>
</div>
</body>
</html>