joel-woodfield commited on
Commit
e048104
·
1 Parent(s): 303a85e

Refactor axis ranges to avoid re-rendering

Browse files
dist/assets/{index-BSZlS5Yr.js → index-BePOBmlp.js} RENAMED
The diff for this file is too large to render. See raw diff
 
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-BSZlS5Yr.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-BE9C_h4C.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-BePOBmlp.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-BE9C_h4C.css">
10
  </head>
11
  <body>
frontends/react/src/App.tsx CHANGED
@@ -1,39 +1,41 @@
1
- import { useState } from "react";
2
  import OptimizationPlot from "./OptimizationPlot.tsx";
3
  import Sidebar from "./Sidebar.tsx";
4
- import type { Settings } from "./types.ts";
5
  import usePyodide from "./usePyodide.ts";
6
  import LoadingScreen from "./ui/LoadingScreen.tsx";
7
 
8
- const INITIAL_SETTINGS: Settings = {
9
  mode: "Univariate",
10
  functionExpr: "x^2",
11
  algorithm: "Gradient Descent",
12
- xlim: [-1, 1],
13
- ylim: [-1, 1],
14
  x0: "0.5",
15
  y0: "0.5",
16
  learningRate: "0.1",
17
  momentum: "0.0",
18
  };
19
 
 
 
 
20
  export default function App() {
21
- const api = usePyodide(INITIAL_SETTINGS);
 
 
 
 
22
 
23
- const [settings, setSettings] = useState<Settings>(INITIAL_SETTINGS);
24
 
25
- function handleSettingsChange(newSettings: Settings) {
26
- setSettings(newSettings);
27
- api.sendInit(newSettings);
28
  }
29
 
30
  function setAxisLimits(xlim: [number, number], ylim: [number, number]) {
31
- const newSettings = {
32
- ...settings,
33
- xlim: xlim,
34
- ylim: ylim,
35
- };
36
- handleSettingsChange(newSettings);
37
  }
38
 
39
  if (api.isLoading) {
@@ -45,13 +47,13 @@ export default function App() {
45
  <div className="grid grid-cols-[2fr_1fr] h-dvh">
46
  <OptimizationPlot
47
  data={api.plotData}
48
- xlim={settings.xlim}
49
- ylim={settings.ylim}
50
  setAxisLimits={setAxisLimits}
51
  />
52
  <Sidebar
53
- settings={settings}
54
- setSettings={handleSettingsChange}
55
 
56
  onReset={() => api.sendReset()}
57
  onNextStep={() => api.sendNextStep()}
 
1
+ import { useState, useRef } from "react";
2
  import OptimizationPlot from "./OptimizationPlot.tsx";
3
  import Sidebar from "./Sidebar.tsx";
4
+ import type { SettingsUi } from "./types.ts";
5
  import usePyodide from "./usePyodide.ts";
6
  import LoadingScreen from "./ui/LoadingScreen.tsx";
7
 
8
+ const INITIAL_SETTINGS_UI: SettingsUi = {
9
  mode: "Univariate",
10
  functionExpr: "x^2",
11
  algorithm: "Gradient Descent",
 
 
12
  x0: "0.5",
13
  y0: "0.5",
14
  learningRate: "0.1",
15
  momentum: "0.0",
16
  };
17
 
18
+ const INITIAL_XLIM: [number, number] = [-1, 1];
19
+ const INITIAL_YLIM: [number, number] = [-1, 1];
20
+
21
  export default function App() {
22
+ const [settingsUi, setSettingsUi] = useState<SettingsUi>(INITIAL_SETTINGS_UI);
23
+ const xlimRef = useRef<[number, number]>(INITIAL_XLIM);
24
+ const ylimRef = useRef<[number, number]>(INITIAL_YLIM);
25
+
26
+ const settings = { ...settingsUi, xlim: xlimRef.current, ylim: ylimRef.current };
27
 
28
+ const api = usePyodide(settings);
29
 
30
+ function handleSettingsUiChange(newSettings: SettingsUi) {
31
+ setSettingsUi(newSettings);
32
+ api.sendInit({ ...newSettings, xlim: xlimRef.current, ylim: ylimRef.current });
33
  }
34
 
35
  function setAxisLimits(xlim: [number, number], ylim: [number, number]) {
36
+ xlimRef.current = xlim;
37
+ ylimRef.current = ylim;
38
+ api.sendInit({ ...settingsUi, xlim, ylim });
 
 
 
39
  }
40
 
41
  if (api.isLoading) {
 
47
  <div className="grid grid-cols-[2fr_1fr] h-dvh">
48
  <OptimizationPlot
49
  data={api.plotData}
50
+ xlim={xlimRef.current}
51
+ ylim={ylimRef.current}
52
  setAxisLimits={setAxisLimits}
53
  />
54
  <Sidebar
55
+ settings={settingsUi}
56
+ setSettings={handleSettingsUiChange}
57
 
58
  onReset={() => api.sendReset()}
59
  onNextStep={() => api.sendNextStep()}
frontends/react/src/Sidebar.tsx CHANGED
@@ -4,7 +4,7 @@ import Tabs from "./ui/Tabs.tsx";
4
  import Dropdown from "./ui/Dropdown.tsx";
5
  import Button from "./ui/Button.tsx";
6
  import Radio from "./ui/Radio.tsx";
7
- import { SUPPORTED_MODES, SUPPORTED_ALGORITHMS, type Settings } from "./types.ts";
8
 
9
 
10
  const DEFAULT_HYPERPARAMETERS = {
@@ -37,8 +37,8 @@ const BIVARIATE_FUNCTION_OPTIONS = {
37
 
38
 
39
  interface SidebarProps {
40
- settings: Settings,
41
- setSettings: (settings: Settings) => void,
42
 
43
  onReset?: () => void,
44
  onNextStep?: () => void,
@@ -59,10 +59,10 @@ export default function Sidebar({
59
  const tabs = ["Settings", "Optimize"] as const;
60
  const [activeTab, setActiveTab] = useState<(typeof tabs)[number]>("Settings");
61
 
62
- function updateSettings(key: keyof Settings, value: string) {
63
  if (key === "algorithm") {
64
  const defaults = DEFAULT_HYPERPARAMETERS[value as keyof typeof DEFAULT_HYPERPARAMETERS];
65
- setSettings({ ...settings, algorithm: value as Settings["algorithm"], ...defaults });
66
  } else {
67
  setSettings({ ...settings, [key]: value });
68
  }
@@ -76,7 +76,7 @@ export default function Sidebar({
76
  updateSettings("functionExpr", expr);
77
  }
78
 
79
- function handleModeChange(mode: Settings["mode"]) {
80
  // When changing modes, reset function to Quadratic as some options are mode-specific
81
  const newFunctionOption = "Quadratic";
82
 
@@ -127,7 +127,7 @@ export default function Sidebar({
127
  label="Algorithm"
128
  options={SUPPORTED_ALGORITHMS}
129
  activeOption={settings.algorithm}
130
- onChange={(value: Settings["algorithm"]) => updateSettings("algorithm", value)}
131
  />
132
  <div className={`${settings.mode === "Bivariate" ? "grid grid-cols-2 gap-2" : ""}`}>
133
  <InputField
 
4
  import Dropdown from "./ui/Dropdown.tsx";
5
  import Button from "./ui/Button.tsx";
6
  import Radio from "./ui/Radio.tsx";
7
+ import { SUPPORTED_MODES, SUPPORTED_ALGORITHMS, type SettingsUi } from "./types.ts";
8
 
9
 
10
  const DEFAULT_HYPERPARAMETERS = {
 
37
 
38
 
39
  interface SidebarProps {
40
+ settings: SettingsUi,
41
+ setSettings: (settings: SettingsUi) => void,
42
 
43
  onReset?: () => void,
44
  onNextStep?: () => void,
 
59
  const tabs = ["Settings", "Optimize"] as const;
60
  const [activeTab, setActiveTab] = useState<(typeof tabs)[number]>("Settings");
61
 
62
+ function updateSettings(key: keyof SettingsUi, value: string) {
63
  if (key === "algorithm") {
64
  const defaults = DEFAULT_HYPERPARAMETERS[value as keyof typeof DEFAULT_HYPERPARAMETERS];
65
+ setSettings({ ...settings, algorithm: value as SettingsUi["algorithm"], ...defaults });
66
  } else {
67
  setSettings({ ...settings, [key]: value });
68
  }
 
76
  updateSettings("functionExpr", expr);
77
  }
78
 
79
+ function handleModeChange(mode: SettingsUi["mode"]) {
80
  // When changing modes, reset function to Quadratic as some options are mode-specific
81
  const newFunctionOption = "Quadratic";
82
 
 
127
  label="Algorithm"
128
  options={SUPPORTED_ALGORITHMS}
129
  activeOption={settings.algorithm}
130
+ onChange={(value: SettingsUi["algorithm"]) => updateSettings("algorithm", value)}
131
  />
132
  <div className={`${settings.mode === "Bivariate" ? "grid grid-cols-2 gap-2" : ""}`}>
133
  <InputField
frontends/react/src/types.ts CHANGED
@@ -23,6 +23,8 @@ export interface Settings {
23
  epsilon?: string;
24
  }
25
 
 
 
26
  export type PlotValues = {
27
  x: number[];
28
  y: number[];
 
23
  epsilon?: string;
24
  }
25
 
26
+ export type SettingsUi = Omit<Settings, "xlim" | "ylim">;
27
+
28
  export type PlotValues = {
29
  x: number[];
30
  y: number[];