diff --git a/optuna_dashboard/static/components/GraphEdf.tsx b/optuna_dashboard/static/components/GraphEdf.tsx
new file mode 100644
index 00000000..7a0e9a23
--- /dev/null
+++ b/optuna_dashboard/static/components/GraphEdf.tsx
@@ -0,0 +1,80 @@
+import * as plotly from "plotly.js-dist"
+import React, { FC, useEffect } from "react"
+
+const plotDomId = "graph-edf"
+
+export const Edf: FC<{
+ trials: Trial[]
+}> = ({ trials = [] }) => {
+ useEffect(() => {
+ plotEdf(trials) // TODO(chenghuzi): Support multi-objective studies.
+ }, [trials])
+ return
+}
+
+const plotEdf = (trials: Trial[]) => {
+ // Notice that this implementation is only for single study case
+ // as it's designed for single study details.
+ if (document.getElementById(plotDomId) === null) {
+ return
+ }
+ if (trials.length === 0) {
+ plotly.react(plotDomId, [])
+ return
+ }
+
+ const target_name = "Objective Value"
+
+ const _target = (t: Trial): number => {
+ return t.values![0]
+ }
+
+ const target = _target
+
+ const layout: Partial = {
+ title: "Empirical Distribution Function Plot",
+ xaxis: {
+ title: target_name,
+ },
+ yaxis: {
+ title: "Cumulative Probability",
+ },
+ margin: {
+ l: 50,
+ r: 50,
+ b: 50,
+ },
+ }
+
+ const completedTrials = trials.filter((t) => t.state === "Complete")
+
+ if (completedTrials.length === 0) {
+ plotly.react(plotDomId, [])
+ return
+ }
+
+ const values = completedTrials.map((t) => target(t))
+ const numValues = values.length
+ const minX = Math.min(...values)
+ const maxX = Math.max(...values)
+ const numStep = 100
+ const _step = (maxX - minX) / (numStep - 1)
+
+ const xValues = []
+ const yValues = []
+ for (let i = 0; i < numStep; i++) {
+ const boundary_right = minX + _step * i
+ xValues.push(boundary_right)
+ yValues.push(values.filter((v) => v <= boundary_right).length / numValues)
+ }
+
+ const plotData: Partial[] = [
+ {
+ type: "scatter",
+ x: xValues,
+ y: yValues,
+ },
+ ]
+
+ plotly.react(plotDomId, plotData, layout)
+}
diff --git a/optuna_dashboard/static/components/StudyDetail.tsx b/optuna_dashboard/static/components/StudyDetail.tsx
index f1ba884f..6317413a 100644
--- a/optuna_dashboard/static/components/StudyDetail.tsx
+++ b/optuna_dashboard/static/components/StudyDetail.tsx
@@ -21,6 +21,8 @@ import { Home, Cached } from "@material-ui/icons"
import { DataGridColumn, DataGrid } from "./DataGrid"
import { GraphParallelCoordinate } from "./GraphParallelCoordinate"
import { HyperparameterImportances } from "./HyperparameterImportances"
+import { Edf } from "./GraphEdf"
+
import { GraphIntermediateValues } from "./GraphIntermediateValues"
import { GraphSlice } from "./GraphSlice"
import { GraphHistory } from "./GraphHistory"
@@ -210,6 +212,13 @@ export const StudyDetail: FC = () => {
+
+
+
+
+
+
+
) : null}
{studyDetail !== null ? (