nanye commited on
Commit
647cf08
·
1 Parent(s): 40aa7d5

display mode bar for 2D plot

Browse files
dist/assets/{index-Mctteb_d.js → index-DxXDp_Rq.js} RENAMED
The diff for this file is too large to render. See raw diff
 
dist/assets/{pyodide.worker-CGobkf40.js → pyodide.worker-CMc9uFEp.js} RENAMED
@@ -354,6 +354,209 @@ class OptimizationManager:
354
  )
355
  else:
356
  raise ValueError("Unsupported algorithm for bivariate mode")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  `,l=`import numpy as np
358
  from sympy import lambdify, Expr
359
 
@@ -1017,4 +1220,4 @@ def adam_bivariate(
1017
  "gradient": gradient_values,
1018
  "hessian": hessian_values,
1019
  }
1020
- `;const f="https://cdn.jsdelivr.net/pyodide/v0.26.1/full/pyodide.mjs";let e=null,a=null;async function r(){const{loadPyodide:n}=await import(f);e=await n({indexURL:"https://cdn.jsdelivr.net/pyodide/v0.26.1/full/"}),await e.loadPackage(["numpy","sympy"]),e.FS.writeFile("optimization_logic.py",l),e.FS.writeFile("optimization_manager.py",s),e.runPython("from optimization_manager import OptimizationManager; manager = OptimizationManager();"),a=e.globals.get("manager"),a||console.error("Failed to initialize optimization manager"),self.postMessage({type:"READY"})}function i(n){if(!n)return null;try{const t=n.toJs({dict_converter:Object.fromEntries});n.destroy&&n.destroy(),self.postMessage({type:"RESULT",data:t})}catch(t){console.error("Error handling Python result:",t)}}self.onmessage=async n=>{const t=n.data;if(!a){console.warn("Pyodide is not ready yet");return}switch(t.type){case"INIT":const o=e.toPy(t.settings);i(a.handle_update_settings(o));break;case"NEXT_STEP":i(a.handle_next_step());break;case"PREV_STEP":i(a.handle_prev_step());break;case"RESET":i(a.handle_reset());break;default:console.error("Unknown message type:",t);break}},r()})();
 
354
  )
355
  else:
356
  raise ValueError("Unsupported algorithm for bivariate mode")
357
+
358
+ def handle_compute_trajectory(self, settings: dict) -> dict[str, dict]:
359
+ """
360
+ Compute function values and a full trajectory for the given settings
361
+ without modifying the manager's current state.
362
+ """
363
+ try:
364
+ mode = settings.get("mode", "").lower().strip()
365
+ function = settings.get("functionExpr", "").strip()
366
+ xlim = settings.get("xlim", [])
367
+ ylim = settings.get("ylim", [])
368
+
369
+ if not self._is_valid_function(function, mode, xlim, ylim):
370
+ return {
371
+ "trajectoryValues": {"x": [], "y": []},
372
+ "functionValues": {"x": [], "y": []},
373
+ }
374
+
375
+ # compute function values (local)
376
+ if mode == "univariate":
377
+ x = np.linspace(xlim[0], xlim[1], 101)
378
+ f = lambdify('x', self._parse_function(function), modules=['numpy'])
379
+ y = f(x)
380
+ if not isinstance(y, np.ndarray):
381
+ y = np.full_like(x, y)
382
+ function_values = {"x": x.tolist(), "y": y.tolist()}
383
+
384
+ elif mode == "bivariate":
385
+ x = np.linspace(xlim[0], xlim[1], 101)
386
+ y = np.linspace(ylim[0], ylim[1], 101)
387
+ X, Y = np.meshgrid(x, y)
388
+ expr = self._parse_function(function)
389
+ f = lambdify(('x', 'y'), expr, modules=['numpy'])
390
+ gradient_x = lambdify(('x', 'y'), expr.diff('x'), modules=['numpy'])
391
+ gradient_y = lambdify(('x', 'y'), expr.diff('y'), modules=['numpy'])
392
+ Z = f(X, Y)
393
+ gradient_x_values = gradient_x(X, Y)
394
+ gradient_y_values = gradient_y(X, Y)
395
+ if not isinstance(Z, np.ndarray):
396
+ Z = np.full_like(X, Z)
397
+ if not isinstance(gradient_x_values, np.ndarray):
398
+ gradient_x_values = np.full_like(X, gradient_x_values)
399
+ if not isinstance(gradient_y_values, np.ndarray):
400
+ gradient_y_values = np.full_like(Y, gradient_y_values)
401
+ function_values = {
402
+ "x": x.tolist(),
403
+ "y": y.tolist(),
404
+ "z": Z.tolist(),
405
+ "gradientX": gradient_x_values.tolist(),
406
+ "gradientY": gradient_y_values.tolist(),
407
+ }
408
+ else:
409
+ raise ValueError("Unsupported mode")
410
+
411
+ # compute trajectory values using existing helper logic
412
+ # choose a reasonably large number of steps for comparison
413
+ steps = 100
414
+ # reuse _compute_trajectory_values logic by calling the same functions
415
+ # but capture result into a local variable
416
+ mode_key = mode
417
+ algorithm = settings.get("algorithm", "").lower().strip().replace(" ", "_")
418
+
419
+ if mode_key == "univariate":
420
+ if algorithm == "gradient_descent":
421
+ traj = gd_univariate(
422
+ self._parse_function(function),
423
+ float(settings["x0"]),
424
+ float(settings.get("learningRate", 0.1)),
425
+ float(settings.get("momentum", 0.0)),
426
+ steps,
427
+ )
428
+ elif algorithm == "nesterov":
429
+ traj = nesterov_univariate(
430
+ self._parse_function(function),
431
+ float(settings["x0"]),
432
+ float(settings.get("learningRate", 0.1)),
433
+ float(settings.get("momentum", 0.0)),
434
+ steps,
435
+ )
436
+ elif algorithm == "adam":
437
+ traj = adam_univariate(
438
+ self._parse_function(function),
439
+ float(settings["x0"]),
440
+ float(settings.get("learningRate", 0.1)),
441
+ float(settings.get("beta1", 0.9)),
442
+ float(settings.get("beta2", 0.999)),
443
+ float(settings.get("epsilon", 1e-8)),
444
+ steps,
445
+ )
446
+ elif algorithm == "adagrad":
447
+ traj = adagrad_univariate(
448
+ self._parse_function(function),
449
+ float(settings["x0"]),
450
+ float(settings.get("learningRate", 0.1)),
451
+ float(settings.get("epsilon", 1e-8)),
452
+ steps,
453
+ )
454
+ elif algorithm == "rmsprop":
455
+ traj = rmsprop_univariate(
456
+ self._parse_function(function),
457
+ float(settings["x0"]),
458
+ float(settings.get("learningRate", 0.1)),
459
+ float(settings.get("beta", 0.9)),
460
+ float(settings.get("epsilon", 1e-8)),
461
+ steps,
462
+ )
463
+ elif algorithm == "adadelta":
464
+ traj = adadelta_univariate(
465
+ self._parse_function(function),
466
+ float(settings["x0"]),
467
+ float(settings.get("beta", 0.9)),
468
+ float(settings.get("epsilon", 1e-3)),
469
+ steps,
470
+ )
471
+ elif algorithm == "newton":
472
+ traj = newton_univariate(
473
+ self._parse_function(function),
474
+ float(settings["x0"]),
475
+ steps,
476
+ )
477
+ else:
478
+ raise ValueError("Unsupported algorithm for univariate mode")
479
+
480
+ elif mode_key == "bivariate":
481
+ if algorithm == "gradient_descent":
482
+ traj = gd_bivariate(
483
+ self._parse_function(function),
484
+ float(settings["x0"]),
485
+ float(settings["y0"]),
486
+ float(settings.get("learningRate", 0.1)),
487
+ float(settings.get("momentum", 0.0)),
488
+ steps,
489
+ )
490
+ elif algorithm == "nesterov":
491
+ traj = nesterov_bivariate(
492
+ self._parse_function(function),
493
+ float(settings["x0"]),
494
+ float(settings["y0"]),
495
+ float(settings.get("learningRate", 0.1)),
496
+ float(settings.get("momentum", 0.0)),
497
+ steps,
498
+ )
499
+ elif algorithm == "adam":
500
+ traj = adam_bivariate(
501
+ self._parse_function(function),
502
+ float(settings["x0"]),
503
+ float(settings["y0"]),
504
+ float(settings.get("learningRate", 0.1)),
505
+ float(settings.get("beta1", 0.9)),
506
+ float(settings.get("beta2", 0.999)),
507
+ float(settings.get("epsilon", 1e-8)),
508
+ steps,
509
+ )
510
+ elif algorithm == "adagrad":
511
+ traj = adagrad_bivariate(
512
+ self._parse_function(function),
513
+ float(settings["x0"]),
514
+ float(settings["y0"]),
515
+ float(settings.get("learningRate", 0.1)),
516
+ float(settings.get("epsilon", 1e-8)),
517
+ steps,
518
+ )
519
+ elif algorithm == "rmsprop":
520
+ traj = rmsprop_bivariate(
521
+ self._parse_function(function),
522
+ float(settings["x0"]),
523
+ float(settings["y0"]),
524
+ float(settings.get("learningRate", 0.1)),
525
+ float(settings.get("beta", 0.9)),
526
+ float(settings.get("epsilon", 1e-8)),
527
+ steps,
528
+ )
529
+ elif algorithm == "adadelta":
530
+ traj = adadelta_bivariate(
531
+ self._parse_function(function),
532
+ float(settings["x0"]),
533
+ float(settings["y0"]),
534
+ float(settings.get("beta", 0.9)),
535
+ float(settings.get("epsilon", 1e-3)),
536
+ steps,
537
+ )
538
+ elif algorithm == "newton":
539
+ traj = newton_bivariate(
540
+ self._parse_function(function),
541
+ float(settings["x0"]),
542
+ float(settings["y0"]),
543
+ steps,
544
+ )
545
+ else:
546
+ raise ValueError("Unsupported algorithm for bivariate mode")
547
+
548
+ else:
549
+ raise ValueError("Unsupported mode")
550
+
551
+ return {
552
+ "functionValues": function_values,
553
+ "trajectoryValues": traj,
554
+ }
555
+ except Exception as e:
556
+ return {
557
+ "trajectoryValues": {"x": [], "y": []},
558
+ "functionValues": {"x": [], "y": []},
559
+ }
560
  `,l=`import numpy as np
561
  from sympy import lambdify, Expr
562
 
 
1220
  "gradient": gradient_values,
1221
  "hessian": hessian_values,
1222
  }
1223
+ `;const f="https://cdn.jsdelivr.net/pyodide/v0.26.1/full/pyodide.mjs";let e=null,t=null;async function r(){const{loadPyodide:n}=await import(f);e=await n({indexURL:"https://cdn.jsdelivr.net/pyodide/v0.26.1/full/"}),await e.loadPackage(["numpy","sympy"]),e.FS.writeFile("optimization_logic.py",l),e.FS.writeFile("optimization_manager.py",s),e.runPython("from optimization_manager import OptimizationManager; manager = OptimizationManager();"),t=e.globals.get("manager"),t||console.error("Failed to initialize optimization manager"),self.postMessage({type:"READY"})}function i(n){if(!n)return null;try{const a=n.toJs({dict_converter:Object.fromEntries});n.destroy&&n.destroy(),self.postMessage({type:"RESULT",data:a})}catch(a){console.error("Error handling Python result:",a)}}self.onmessage=async n=>{const a=n.data;if(!t){console.warn("Pyodide is not ready yet");return}switch(a.type){case"INIT":const o=e.toPy(a.settings);i(t.handle_update_settings(o));break;case"NEXT_STEP":i(t.handle_next_step());break;case"PREV_STEP":i(t.handle_prev_step());break;case"RESET":i(t.handle_reset());break;default:console.error("Unknown message type:",a);break}},r()})();
dist/index.html CHANGED
@@ -5,7 +5,7 @@
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>Optimization</title>
8
- <script type="module" crossorigin src="/assets/index-Mctteb_d.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-Bs9s2ktO.css">
10
  </head>
11
  <body>
 
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>Optimization</title>
8
+ <script type="module" crossorigin src="/assets/index-DxXDp_Rq.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-Bs9s2ktO.css">
10
  </head>
11
  <body>
frontends/react/src/OptimizationPlot.tsx CHANGED
@@ -297,7 +297,7 @@ export default function OptimizationPlot({ data, isLoading, xlim, ylim, setAxisL
297
  style={{ width: '100%', height: '100%' }}
298
  config={{
299
  responsive: true,
300
- displayModeBar: false,
301
  scrollZoom: true,
302
  }}
303
  />
 
297
  style={{ width: '100%', height: '100%' }}
298
  config={{
299
  responsive: true,
300
+ displayModeBar: true,
301
  scrollZoom: true,
302
  }}
303
  />