From 6bec7e3a80a6c07f452265adbdb9dcb6a0de6d6d Mon Sep 17 00:00:00 2001 From: Naoto Mizuno Date: Thu, 2 Nov 2023 16:24:50 +0900 Subject: [PATCH 1/5] Support constrained optimization for timeline plot --- .../ts/components/GraphTimeline.tsx | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphTimeline.tsx b/optuna_dashboard/ts/components/GraphTimeline.tsx index 68afe0fc..40d23662 100644 --- a/optuna_dashboard/ts/components/GraphTimeline.tsx +++ b/optuna_dashboard/ts/components/GraphTimeline.tsx @@ -92,12 +92,7 @@ const plotTimeline = (trials: Trial[], mode: string) => { template: mode === "dark" ? plotlyDarkTemplate : {}, } - const traces: Partial[] = [] - for (const s of Object.keys(cm) as TrialState[]) { - const bars = trials.filter((t) => t.state === s) - if (bars.length === 0) { - continue - } + const makeTrace = (bars: Trial[], name: string, color: string) => { const starts = bars.map((b) => b.datetime_start ?? new Date()) const completes = bars.map((b, i) => b.datetime_complete ?? starts[i]) const trace: Partial = { @@ -106,14 +101,38 @@ const plotTimeline = (trials: Trial[], mode: string) => { y: bars.map((b) => b.number), // @ts-ignore: To suppress ts(2322) base: starts.map((s) => s.toISOString()), - name: s, + name: name, text: bars.map((b) => makeHovertext(b)), - hovertemplate: "%{text}" + s + "", + hovertemplate: "%{text}" + name + "", orientation: "h", - marker: { color: cm[s] }, + marker: { color: color }, textposition: "none", // Avoid drawing hovertext in a bar. } - traces.push(trace) + return trace + } + + const traces: Partial[] = [] + for (const s of Object.keys(cm) as TrialState[]) { + const bars = trials.filter((t) => t.state === s) + if (bars.length === 0) { + continue + } + if (s == "Complete") { + const feasibleTrials = bars.filter((t) => + t.constraints.every((c) => c <= 0) + ) + const infeasibleTrials = bars.filter((t) => + t.constraints.some((c) => c > 0) + ) + if (feasibleTrials.length > 0) { + traces.push(makeTrace(feasibleTrials, "Complete", cm[s])) + } + if (infeasibleTrials.length > 0) { + traces.push(makeTrace(infeasibleTrials, "Infeasible", "#cccccc")) + } + } else { + traces.push(makeTrace(bars, s, cm[s])) + } } plotly.react(plotDomId, traces, layout) } From e0bc52573228e5b7863239915498cb9ecb59bb8c Mon Sep 17 00:00:00 2001 From: Naoto Mizuno Date: Wed, 8 Nov 2023 15:29:13 +0900 Subject: [PATCH 2/5] Update optuna_dashboard/ts/components/GraphTimeline.tsx Co-authored-by: Hideaki Imamura <38826298+HideakiImamura@users.noreply.github.com> --- optuna_dashboard/ts/components/GraphTimeline.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphTimeline.tsx b/optuna_dashboard/ts/components/GraphTimeline.tsx index 40d23662..b2a29888 100644 --- a/optuna_dashboard/ts/components/GraphTimeline.tsx +++ b/optuna_dashboard/ts/components/GraphTimeline.tsx @@ -112,12 +112,12 @@ const plotTimeline = (trials: Trial[], mode: string) => { } const traces: Partial[] = [] - for (const s of Object.keys(cm) as TrialState[]) { - const bars = trials.filter((t) => t.state === s) + for (const [state, color] of Object.entries(cm)) { + const bars = trials.filter((t) => t.state === state) if (bars.length === 0) { continue } - if (s == "Complete") { + if (state == "Complete") { const feasibleTrials = bars.filter((t) => t.constraints.every((c) => c <= 0) ) @@ -125,14 +125,15 @@ const plotTimeline = (trials: Trial[], mode: string) => { t.constraints.some((c) => c > 0) ) if (feasibleTrials.length > 0) { - traces.push(makeTrace(feasibleTrials, "Complete", cm[s])) + traces.push(makeTrace(feasibleTrials, "Complete", color)) } if (infeasibleTrials.length > 0) { traces.push(makeTrace(infeasibleTrials, "Infeasible", "#cccccc")) } } else { - traces.push(makeTrace(bars, s, cm[s])) + traces.push(makeTrace(bars, state, color)) } } + } plotly.react(plotDomId, traces, layout) } From ff6ce9ddc29af8f5878f962828407a5f1b25bd67 Mon Sep 17 00:00:00 2001 From: Naoto Mizuno Date: Wed, 8 Nov 2023 15:37:21 +0900 Subject: [PATCH 3/5] Remove excessive parenthesis --- optuna_dashboard/ts/components/GraphTimeline.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphTimeline.tsx b/optuna_dashboard/ts/components/GraphTimeline.tsx index b2a29888..23c65d51 100644 --- a/optuna_dashboard/ts/components/GraphTimeline.tsx +++ b/optuna_dashboard/ts/components/GraphTimeline.tsx @@ -134,6 +134,5 @@ const plotTimeline = (trials: Trial[], mode: string) => { traces.push(makeTrace(bars, state, color)) } } - } plotly.react(plotDomId, traces, layout) } From cbbe56a2894db374f5f4c981470091996636c705 Mon Sep 17 00:00:00 2001 From: Naoto Mizuno Date: Wed, 8 Nov 2023 15:37:58 +0900 Subject: [PATCH 4/5] Use strict equality operator --- optuna_dashboard/ts/components/GraphTimeline.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphTimeline.tsx b/optuna_dashboard/ts/components/GraphTimeline.tsx index 23c65d51..195eaeed 100644 --- a/optuna_dashboard/ts/components/GraphTimeline.tsx +++ b/optuna_dashboard/ts/components/GraphTimeline.tsx @@ -117,7 +117,7 @@ const plotTimeline = (trials: Trial[], mode: string) => { if (bars.length === 0) { continue } - if (state == "Complete") { + if (state === "Complete") { const feasibleTrials = bars.filter((t) => t.constraints.every((c) => c <= 0) ) From 3628c31c7e66426f201472a26ce4346c80832c0a Mon Sep 17 00:00:00 2001 From: Naoto Mizuno Date: Wed, 8 Nov 2023 15:39:25 +0900 Subject: [PATCH 5/5] Change argument name to state --- optuna_dashboard/ts/components/GraphTimeline.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphTimeline.tsx b/optuna_dashboard/ts/components/GraphTimeline.tsx index 195eaeed..cc0f7f57 100644 --- a/optuna_dashboard/ts/components/GraphTimeline.tsx +++ b/optuna_dashboard/ts/components/GraphTimeline.tsx @@ -92,7 +92,7 @@ const plotTimeline = (trials: Trial[], mode: string) => { template: mode === "dark" ? plotlyDarkTemplate : {}, } - const makeTrace = (bars: Trial[], name: string, color: string) => { + const makeTrace = (bars: Trial[], state: string, color: string) => { const starts = bars.map((b) => b.datetime_start ?? new Date()) const completes = bars.map((b, i) => b.datetime_complete ?? starts[i]) const trace: Partial = { @@ -101,9 +101,9 @@ const plotTimeline = (trials: Trial[], mode: string) => { y: bars.map((b) => b.number), // @ts-ignore: To suppress ts(2322) base: starts.map((s) => s.toISOString()), - name: name, + name: state, text: bars.map((b) => makeHovertext(b)), - hovertemplate: "%{text}" + name + "", + hovertemplate: "%{text}" + state + "", orientation: "h", marker: { color: color }, textposition: "none", // Avoid drawing hovertext in a bar.