|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<title>Gradient-Free BOED via Interacting Particle Systems</title> |
|
<style> |
|
body { margin: 0; overflow: hidden; } |
|
#info { |
|
position: absolute; |
|
top: 10px; |
|
left: 10px; |
|
background: rgba(0,0,0,0.6); |
|
color: #fff; |
|
font-family: sans-serif; |
|
padding: 10px; |
|
border-radius: 4px; |
|
max-width: 300px; |
|
line-height: 1.4; |
|
} |
|
#info h1 { |
|
margin: 0 0 6px; |
|
font-size: 16px; |
|
} |
|
#info p { margin: 4px 0; font-size: 13px; } |
|
#info a { color: #66ccff; text-decoration: none; } |
|
#info a:hover { text-decoration: underline; } |
|
</style> |
|
</head> |
|
<body> |
|
<div id="info"> |
|
<h1>Gradient-Free Sequential BOED</h1> |
|
<p><strong>Gruhlke et al.</strong></p> |
|
<p> |
|
<a href="https://arxiv.org/abs/2504.13320" target="_blank">arXiv Abstract</a> | |
|
<a href="https://arxiv.org/pdf/2504.13320" target="_blank">PDF</a> |
|
</p> |
|
<p style="font-size:12px;"> |
|
Uses Ensemble Kalman Inversion + Affine-Invariant Langevin sampling<br/> |
|
for gradient-free sequential experimental design. |
|
</p> |
|
</div> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script> |
|
<script> |
|
|
|
const scene = new THREE.Scene(); |
|
const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 1000); |
|
camera.position.set(0, 0, 50); |
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true }); |
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
document.body.appendChild(renderer.domElement); |
|
|
|
const controls = new THREE.OrbitControls(camera, renderer.domElement); |
|
window.addEventListener('resize', () => { |
|
camera.aspect = window.innerWidth/window.innerHeight; |
|
camera.updateProjectionMatrix(); |
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
}); |
|
|
|
|
|
const N = 100; |
|
const particles = []; |
|
const sphereGeo = new THREE.SphereGeometry(0.5, 8, 8); |
|
for(let i=0; i<N; i++){ |
|
const mat = new THREE.MeshBasicMaterial({ color: new THREE.Color(Math.random(),Math.random(),Math.random()) }); |
|
const m = new THREE.Mesh(sphereGeo, mat); |
|
m.position.set((Math.random()-0.5)*40, (Math.random()-0.5)*40, (Math.random()-0.5)*40); |
|
particles.push(m); |
|
scene.add(m); |
|
} |
|
|
|
function step(){ |
|
|
|
const mean = new THREE.Vector3(); |
|
particles.forEach(p=>mean.add(p.position)); |
|
mean.divideScalar(N); |
|
|
|
let cov=0; |
|
particles.forEach(p=>cov+=p.position.distanceToSquared(mean)); |
|
cov/=N; |
|
const alpha=0.01, noiseAmp=0.1*Math.sqrt(cov); |
|
particles.forEach(p=>{ |
|
|
|
const toMean = mean.clone().sub(p.position).multiplyScalar(alpha); |
|
|
|
const noise = new THREE.Vector3( |
|
(Math.random()-0.5), |
|
(Math.random()-0.5), |
|
(Math.random()-0.5) |
|
).multiplyScalar(noiseAmp); |
|
p.position.add(toMean).add(noise); |
|
}); |
|
} |
|
|
|
function animate(){ |
|
requestAnimationFrame(animate); |
|
step(); |
|
controls.update(); |
|
renderer.render(scene, camera); |
|
} |
|
animate(); |
|
</script> |
|
</body> |
|
</html> |
|
|