From bd6923237c08fdd710c608091167a056a7a05961 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Wed, 8 Nov 2023 14:36:04 +0900 Subject: [PATCH 01/14] Fast pareto-front calculation for 2D --- .../ts/components/GraphParetoFront.tsx | 67 +++++++++++++++---- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index abcf667d..32146280 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -165,6 +165,60 @@ const makeMarker = ( } } +const getIsDominatedTrialND = (normalizedValues: number[][]) => { + // Fallback for straight-forward pareto front algorithm (O(N^2) complexity). + const dominatedTrials: boolean[] = [] + normalizedValues.forEach((values0: number[], i: number) => { + const dominated = normalizedValues.some((values1: number[], j: number) => { + if (i === j) { + return false + } + return values0.every((value0: number, k: number) => { + return values1[k] <= value0 + }) + }) + dominatedTrials.push(dominated) + }) + return dominatedTrials +} + +const getIsDominatedTrial2D = (normalizedValues: number[][]) => { + // Fast pareto front algorithm (O(N log N) complexity). + const sorted = normalizedValues + .map((values, i) => [values[0], values[1], i]) + .sort() + let minValue1 = sorted[0][1] + const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( + true + ) + + sorted.forEach((values) => { + if (values[1] <= minValue1) { + dominatedTrials[values[2]] = false + minValue1 = values[1] + } + }) + return dominatedTrials +} + +const getIsDominatedTrial1D = (normalizedValues: number[][]) => { + const best_value = Math.min(...normalizedValues.map((values) => values[0])) + return normalizedValues.map((value) => value[0] !== best_value) +} + +const getIsDominatedTrial = (normalizedValues: number[][]) => { + if (normalizedValues.length == 0) { + return [] + } + if (normalizedValues[0].length == 1) { + return getIsDominatedTrial1D(normalizedValues) + } else if (normalizedValues[0].length == 2) { + return getIsDominatedTrial2D(normalizedValues) + } else { + return getIsDominatedTrialND(normalizedValues) + } +} + const plotParetoFront = ( study: StudyDetail, objectiveXId: number, @@ -218,18 +272,7 @@ const plotParetoFront = ( } }) - const dominatedTrials: boolean[] = [] - normalizedValues.forEach((values0: number[], i: number) => { - const dominated = normalizedValues.some((values1: number[], j: number) => { - if (i === j) { - return false - } - return values0.every((value0: number, k: number) => { - return values1[k] <= value0 - }) - }) - dominatedTrials.push(dominated) - }) + const dominatedTrials: boolean[] = getIsDominatedTrial(normalizedValues) const plotData: Partial[] = [ makeScatterObject( From e3c1d74e81905eb6a95fd34f35eec79c527b3a06 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Fri, 10 Nov 2023 13:56:31 +0900 Subject: [PATCH 02/14] Fix bug in getIsDominatedTrialND --- .../ts/components/GraphParetoFront.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 32146280..e182e9b8 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -168,14 +168,12 @@ const makeMarker = ( const getIsDominatedTrialND = (normalizedValues: number[][]) => { // Fallback for straight-forward pareto front algorithm (O(N^2) complexity). const dominatedTrials: boolean[] = [] - normalizedValues.forEach((values0: number[], i: number) => { - const dominated = normalizedValues.some((values1: number[], j: number) => { - if (i === j) { + normalizedValues.forEach((values0: number[]) => { + const dominated = normalizedValues.some((values1: number[]) => { + if (values0.every((value0: number, k: number) => values1[k] === value0)) { return false } - return values0.every((value0: number, k: number) => { - return values1[k] <= value0 - }) + return values0.every((value0: number, k: number) => values1[k] <= value0) }) dominatedTrials.push(dominated) }) @@ -186,7 +184,9 @@ const getIsDominatedTrial2D = (normalizedValues: number[][]) => { // Fast pareto front algorithm (O(N log N) complexity). const sorted = normalizedValues .map((values, i) => [values[0], values[1], i]) - .sort() + .sort((a, b) => { + return a[0] - b[0] + }) let minValue1 = sorted[0][1] const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( true From aba648eb05b36f1cf7e8d4aa5f9549010dd3ad9e Mon Sep 17 00:00:00 2001 From: Contramundum Date: Fri, 10 Nov 2023 13:58:14 +0900 Subject: [PATCH 03/14] Code fix --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index e182e9b8..2861328c 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -184,9 +184,7 @@ const getIsDominatedTrial2D = (normalizedValues: number[][]) => { // Fast pareto front algorithm (O(N log N) complexity). const sorted = normalizedValues .map((values, i) => [values[0], values[1], i]) - .sort((a, b) => { - return a[0] - b[0] - }) + .sort((a, b) => a[0] - b[0]) let minValue1 = sorted[0][1] const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( true From becaff154c2aa13b7f77dd92df7fdd54a9618043 Mon Sep 17 00:00:00 2001 From: contramundum53 Date: Wed, 29 Nov 2023 13:34:54 +0900 Subject: [PATCH 04/14] Update optuna_dashboard/ts/components/GraphParetoFront.tsx Co-authored-by: Hideaki Imamura <38826298+HideakiImamura@users.noreply.github.com> --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 2861328c..1005bc6d 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -208,7 +208,7 @@ const getIsDominatedTrial = (normalizedValues: number[][]) => { if (normalizedValues.length == 0) { return [] } - if (normalizedValues[0].length == 1) { + if (normalizedValues[0].length === 1) { return getIsDominatedTrial1D(normalizedValues) } else if (normalizedValues[0].length == 2) { return getIsDominatedTrial2D(normalizedValues) From 4ef4aa19f572322aa830b4a214d41c82e34f6a03 Mon Sep 17 00:00:00 2001 From: contramundum53 Date: Wed, 29 Nov 2023 13:35:03 +0900 Subject: [PATCH 05/14] Update optuna_dashboard/ts/components/GraphParetoFront.tsx Co-authored-by: Hideaki Imamura <38826298+HideakiImamura@users.noreply.github.com> --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 1005bc6d..8845ebd9 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -205,7 +205,7 @@ const getIsDominatedTrial1D = (normalizedValues: number[][]) => { } const getIsDominatedTrial = (normalizedValues: number[][]) => { - if (normalizedValues.length == 0) { + if (normalizedValues.length === 0) { return [] } if (normalizedValues[0].length === 1) { From b0f66b3209363e190fe2544e7612acacf499568f Mon Sep 17 00:00:00 2001 From: contramundum53 Date: Wed, 29 Nov 2023 13:35:09 +0900 Subject: [PATCH 06/14] Update optuna_dashboard/ts/components/GraphParetoFront.tsx Co-authored-by: Hideaki Imamura <38826298+HideakiImamura@users.noreply.github.com> --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 8845ebd9..e9a99b45 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -210,7 +210,7 @@ const getIsDominatedTrial = (normalizedValues: number[][]) => { } if (normalizedValues[0].length === 1) { return getIsDominatedTrial1D(normalizedValues) - } else if (normalizedValues[0].length == 2) { + } else if (normalizedValues[0].length === 2) { return getIsDominatedTrial2D(normalizedValues) } else { return getIsDominatedTrialND(normalizedValues) From 5b4f0bb40ecf700f1f37f6d6fef4a82427b903c3 Mon Sep 17 00:00:00 2001 From: contramundum53 Date: Wed, 29 Nov 2023 13:45:17 +0900 Subject: [PATCH 07/14] Update optuna_dashboard/ts/components/GraphParetoFront.tsx --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index e9a99b45..88eea2e7 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -184,7 +184,7 @@ const getIsDominatedTrial2D = (normalizedValues: number[][]) => { // Fast pareto front algorithm (O(N log N) complexity). const sorted = normalizedValues .map((values, i) => [values[0], values[1], i]) - .sort((a, b) => a[0] - b[0]) + .sort() let minValue1 = sorted[0][1] const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( true From 8ebed9b99ce65889bc596ded7c0fed101eeb3732 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Thu, 14 Dec 2023 13:47:03 +0900 Subject: [PATCH 08/14] fix pareto-front --- .../ts/components/GraphParetoFront.tsx | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 88eea2e7..155c03b8 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -181,20 +181,38 @@ const getIsDominatedTrialND = (normalizedValues: number[][]) => { } const getIsDominatedTrial2D = (normalizedValues: number[][]) => { + if (normalizedValues.length === 0) { + return [] + } // Fast pareto front algorithm (O(N log N) complexity). const sorted = normalizedValues .map((values, i) => [values[0], values[1], i]) - .sort() + .sort((a, b) => + a[0] > b[0] + ? 1 + : a[0] < b[0] + ? -1 + : a[1] > b[1] + ? 1 + : a[1] < b[1] + ? -1 + : 0 + ) + let maxValue0 = sorted[0][0] let minValue1 = sorted[0][1] - const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( - true - ) + const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( + false + ) sorted.forEach((values) => { - if (values[1] <= minValue1) { - dominatedTrials[values[2]] = false + if ( + values[1] > minValue1 || + (values[1] >= minValue1 && values[0] > maxValue0) + ) { + dominatedTrials[values[2]] = true minValue1 = values[1] } + maxValue0 = values[0] }) return dominatedTrials } From 422ffd20ba62e90f3b542042cc533f58144512a3 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Thu, 14 Dec 2023 13:49:01 +0900 Subject: [PATCH 09/14] rename variables --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 155c03b8..73e74810 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -219,7 +219,7 @@ const getIsDominatedTrial2D = (normalizedValues: number[][]) => { const getIsDominatedTrial1D = (normalizedValues: number[][]) => { const best_value = Math.min(...normalizedValues.map((values) => values[0])) - return normalizedValues.map((value) => value[0] !== best_value) + return normalizedValues.map((values) => values[0] !== best_value) } const getIsDominatedTrial = (normalizedValues: number[][]) => { From 01ecc5563bd67771aa7aed83b0953f81a0891d27 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Thu, 14 Dec 2023 13:54:25 +0900 Subject: [PATCH 10/14] rename functions --- .../ts/components/GraphParetoFront.tsx | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 73e74810..6aad593e 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -165,9 +165,9 @@ const makeMarker = ( } } -const getIsDominatedTrialND = (normalizedValues: number[][]) => { +const getIsDominatedND = (normalizedValues: number[][]) => { // Fallback for straight-forward pareto front algorithm (O(N^2) complexity). - const dominatedTrials: boolean[] = [] + const isDominated: boolean[] = [] normalizedValues.forEach((values0: number[]) => { const dominated = normalizedValues.some((values1: number[]) => { if (values0.every((value0: number, k: number) => values1[k] === value0)) { @@ -175,12 +175,12 @@ const getIsDominatedTrialND = (normalizedValues: number[][]) => { } return values0.every((value0: number, k: number) => values1[k] <= value0) }) - dominatedTrials.push(dominated) + isDominated.push(dominated) }) - return dominatedTrials + return isDominated } -const getIsDominatedTrial2D = (normalizedValues: number[][]) => { +const getIsDominated2D = (normalizedValues: number[][]) => { if (normalizedValues.length === 0) { return [] } @@ -201,37 +201,35 @@ const getIsDominatedTrial2D = (normalizedValues: number[][]) => { let maxValue0 = sorted[0][0] let minValue1 = sorted[0][1] - const dominatedTrials: boolean[] = new Array(normalizedValues.length).fill( - false - ) + const isDominated: boolean[] = new Array(normalizedValues.length).fill(false) sorted.forEach((values) => { if ( values[1] > minValue1 || (values[1] >= minValue1 && values[0] > maxValue0) ) { - dominatedTrials[values[2]] = true + isDominated[values[2]] = true minValue1 = values[1] } maxValue0 = values[0] }) - return dominatedTrials + return isDominated } -const getIsDominatedTrial1D = (normalizedValues: number[][]) => { +const getIsDominated1D = (normalizedValues: number[][]) => { const best_value = Math.min(...normalizedValues.map((values) => values[0])) return normalizedValues.map((values) => values[0] !== best_value) } -const getIsDominatedTrial = (normalizedValues: number[][]) => { +const getIsDominated = (normalizedValues: number[][]) => { if (normalizedValues.length === 0) { return [] } if (normalizedValues[0].length === 1) { - return getIsDominatedTrial1D(normalizedValues) + return getIsDominated1D(normalizedValues) } else if (normalizedValues[0].length === 2) { - return getIsDominatedTrial2D(normalizedValues) + return getIsDominated2D(normalizedValues) } else { - return getIsDominatedTrialND(normalizedValues) + return getIsDominatedND(normalizedValues) } } @@ -288,11 +286,11 @@ const plotParetoFront = ( } }) - const dominatedTrials: boolean[] = getIsDominatedTrial(normalizedValues) + const isDominated: boolean[] = getIsDominated(normalizedValues) const plotData: Partial[] = [ makeScatterObject( - feasibleTrials.filter((t, i) => dominatedTrials[i]), + feasibleTrials.filter((t, i) => isDominated[i]), objectiveXId, objectiveYId, infeasibleTrials.length === 0 @@ -303,7 +301,7 @@ const plotParetoFront = ( mode ), makeScatterObject( - feasibleTrials.filter((t, i) => !dominatedTrials[i]), + feasibleTrials.filter((t, i) => !isDominated[i]), objectiveXId, objectiveYId, "%{text}Best Trial", From a9b23aee2e81035666f3739bee84a0e30637a109 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Thu, 14 Dec 2023 13:56:12 +0900 Subject: [PATCH 11/14] remove unnecessary condition --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 6aad593e..aba20a3e 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -181,9 +181,6 @@ const getIsDominatedND = (normalizedValues: number[][]) => { } const getIsDominated2D = (normalizedValues: number[][]) => { - if (normalizedValues.length === 0) { - return [] - } // Fast pareto front algorithm (O(N log N) complexity). const sorted = normalizedValues .map((values, i) => [values[0], values[1], i]) From 29d44abefab17a3283f90a4e66fe1656e4049ad4 Mon Sep 17 00:00:00 2001 From: Contramundum Date: Thu, 14 Dec 2023 23:03:42 +0900 Subject: [PATCH 12/14] Fix bug --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index aba20a3e..ed6bfa56 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -202,9 +202,10 @@ const getIsDominated2D = (normalizedValues: number[][]) => { sorted.forEach((values) => { if ( values[1] > minValue1 || - (values[1] >= minValue1 && values[0] > maxValue0) + (values[1] === minValue1 && values[0] > maxValue0) ) { isDominated[values[2]] = true + } else { minValue1 = values[1] } maxValue0 = values[0] From 4315c9d47e7d9afaf2bb0bb9237931cf607420cf Mon Sep 17 00:00:00 2001 From: contramundum53 Date: Wed, 20 Dec 2023 18:08:05 +0900 Subject: [PATCH 13/14] Update optuna_dashboard/ts/components/GraphParetoFront.tsx Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com> --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index ed6bfa56..8ecea467 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -195,8 +195,8 @@ const getIsDominated2D = (normalizedValues: number[][]) => { ? -1 : 0 ) - let maxValue0 = sorted[0][0] - let minValue1 = sorted[0][1] + let maxValueSeen0 = sorted[0][0] + let minValueSeen1 = sorted[0][1] const isDominated: boolean[] = new Array(normalizedValues.length).fill(false) sorted.forEach((values) => { From 120350182050a1bb748033bcf5f4c06132bfd04d Mon Sep 17 00:00:00 2001 From: Contramundum Date: Wed, 20 Dec 2023 18:09:55 +0900 Subject: [PATCH 14/14] Rename variable --- optuna_dashboard/ts/components/GraphParetoFront.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 8ecea467..3f487aab 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -201,14 +201,14 @@ const getIsDominated2D = (normalizedValues: number[][]) => { const isDominated: boolean[] = new Array(normalizedValues.length).fill(false) sorted.forEach((values) => { if ( - values[1] > minValue1 || - (values[1] === minValue1 && values[0] > maxValue0) + values[1] > minValueSeen1 || + (values[1] === minValueSeen1 && values[0] > maxValueSeen0) ) { isDominated[values[2]] = true } else { - minValue1 = values[1] + minValueSeen1 = values[1] } - maxValue0 = values[0] + maxValueSeen0 = values[0] }) return isDominated }