mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-10-03 12:41:13 +08:00
Add dialog to create multi-objective study
This commit is contained in:
1 parent
ea00361219
commit
c17e9127ca
4 files changed
+204
-26
No files matched your search
+15
-7
@@ -130,8 +130,12 @@ def create_app(storage_or_url: Union[str, BaseStorage]) -> Bottle:
|
||||
response.content_type = "application/json"
|
||||
|
||||
study_name = request.json.get("study_name", None)
|
||||
direction = request.json.get("direction", None)
|
||||
if study_name is None or direction not in ("minimize", "maximize"):
|
||||
directions = request.json.get("directions", [])
|
||||
if (
|
||||
study_name is None
|
||||
or len(directions) == 0
|
||||
or not all([d in ("minimize", "maximize") for d in directions])
|
||||
):
|
||||
response.status = 400 # Bad request
|
||||
return {"reason": "You need to set study_name and direction"}
|
||||
|
||||
@@ -141,11 +145,15 @@ def create_app(storage_or_url: Union[str, BaseStorage]) -> Bottle:
|
||||
response.status = 400 # Bad request
|
||||
return {"reason": f"'{study_name}' is already exists"}
|
||||
|
||||
# TODO(c-bata): Support multi-objective study.
|
||||
if direction.lower() == "maximize":
|
||||
storage.set_study_directions(study_id, [StudyDirection.MAXIMIZE])
|
||||
else:
|
||||
storage.set_study_directions(study_id, [StudyDirection.MINIMIZE])
|
||||
storage.set_study_directions(
|
||||
study_id,
|
||||
[
|
||||
StudyDirection.MAXIMIZE
|
||||
if d.lower() == "maximize"
|
||||
else StudyDirection.MINIMIZE
|
||||
for d in directions
|
||||
],
|
||||
)
|
||||
|
||||
summary = get_study_summary(storage, study_id)
|
||||
if summary is None:
|
||||
|
||||
@@ -49,8 +49,8 @@ export const actionCreator = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const createNewStudy = (studyName: string, direction: StudyDirection) => {
|
||||
createNewStudyAPI(studyName, direction)
|
||||
const createNewStudy = (studyName: string, directions: StudyDirection[]) => {
|
||||
createNewStudyAPI(studyName, directions)
|
||||
.then((study_summary) => {
|
||||
const newVal = [...studySummaries, study_summary]
|
||||
setStudySummaries(newVal)
|
||||
|
||||
@@ -138,12 +138,12 @@ interface CreateNewStudyResponse {
|
||||
|
||||
export const createNewStudyAPI = (
|
||||
studyName: string,
|
||||
direction: StudyDirection
|
||||
directions: StudyDirection[]
|
||||
): Promise<StudySummary> => {
|
||||
return axiosInstance
|
||||
.post<CreateNewStudyResponse>(`/api/studies`, {
|
||||
study_name: studyName,
|
||||
direction,
|
||||
directions,
|
||||
})
|
||||
.then((res) => {
|
||||
const study_summary = res.data.study_summary
|
||||
|
||||
@@ -20,8 +20,13 @@ import {
|
||||
DialogActions,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
Menu,
|
||||
MenuItem,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Select,
|
||||
} from "@material-ui/core"
|
||||
import { AddBox, Delete, Refresh } from "@material-ui/icons"
|
||||
import { Add, AddBox, Delete, Refresh, Remove } from "@material-ui/icons"
|
||||
|
||||
import { actionCreator } from "../action"
|
||||
import { DataGrid, DataGridColumn } from "./DataGrid"
|
||||
@@ -35,18 +40,38 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
grow: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
objectiveButton: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
export const StudyList: FC<{}> = () => {
|
||||
const classes = useStyles()
|
||||
const [openNewStudyDialog, setOpenNewStudyDialog] = React.useState(false)
|
||||
|
||||
const [
|
||||
newStudySelectionAnchorEl,
|
||||
setNewStudySelectionAnchorEl,
|
||||
] = React.useState<null | HTMLElement>(null)
|
||||
const openNewStudySelection = Boolean(newStudySelectionAnchorEl)
|
||||
const [
|
||||
openNewSingleObjectiveStudyDialog,
|
||||
setOpenNewSingleObjectiveStudyDialog,
|
||||
] = React.useState(false)
|
||||
const [
|
||||
openNewMultiObjectiveStudyDialog,
|
||||
setOpenNewMultiObjectiveStudyDialog,
|
||||
] = React.useState(false)
|
||||
const [openDeleteStudyDialog, setOpenDeleteStudyDialog] = React.useState(
|
||||
false
|
||||
)
|
||||
const [deleteStudyID, setDeleteStudyID] = React.useState(-1)
|
||||
const [newStudyName, setNewStudyName] = React.useState("")
|
||||
const [maximize, setMaximize] = React.useState<boolean>(false)
|
||||
|
||||
const [maximize, setMaximize] = React.useState(false)
|
||||
const [directions, setDirections] = React.useState<StudyDirection[]>([
|
||||
"minimize",
|
||||
])
|
||||
|
||||
const action = actionCreator()
|
||||
const studies = useRecoilValue<StudySummary[]>(studySummariesState)
|
||||
@@ -118,18 +143,31 @@ export const StudyList: FC<{}> = () => {
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
]
|
||||
|
||||
const handleCloseNewStudyDialog = () => {
|
||||
const handleCloseNewSingleObjectiveStudyDialog = () => {
|
||||
setNewStudyName("")
|
||||
setOpenNewStudyDialog(false)
|
||||
setOpenNewSingleObjectiveStudyDialog(false)
|
||||
}
|
||||
|
||||
const handleCreateNewStudy = () => {
|
||||
const handleCreateNewSingleObjectiveStudy = () => {
|
||||
const direction = maximize ? "maximize" : "minimize"
|
||||
action.createNewStudy(newStudyName, direction)
|
||||
setOpenNewStudyDialog(false)
|
||||
action.createNewStudy(newStudyName, [direction])
|
||||
setOpenNewSingleObjectiveStudyDialog(false)
|
||||
setNewStudyName("")
|
||||
}
|
||||
|
||||
const handleCloseNewMultiObjectiveStudyDialog = () => {
|
||||
setOpenNewMultiObjectiveStudyDialog(false)
|
||||
setNewStudyName("")
|
||||
setDirections(["minimize"])
|
||||
}
|
||||
|
||||
const handleCreateNewMultiObjectiveStudy = () => {
|
||||
action.createNewStudy(newStudyName, directions)
|
||||
setOpenNewMultiObjectiveStudyDialog(false)
|
||||
setNewStudyName("")
|
||||
setDirections(["minimize"])
|
||||
}
|
||||
|
||||
const handleCloseDeleteStudyDialog = () => {
|
||||
setOpenDeleteStudyDialog(false)
|
||||
setDeleteStudyID(-1)
|
||||
@@ -199,12 +237,46 @@ export const StudyList: FC<{}> = () => {
|
||||
aria-controls="menu-appbar"
|
||||
aria-haspopup="true"
|
||||
onClick={(e) => {
|
||||
setOpenNewStudyDialog(true)
|
||||
setNewStudySelectionAnchorEl(e.currentTarget)
|
||||
}}
|
||||
color="inherit"
|
||||
>
|
||||
<AddBox />
|
||||
</IconButton>
|
||||
<Menu
|
||||
id="menu-appbar"
|
||||
anchorEl={newStudySelectionAnchorEl}
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
keepMounted
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
open={openNewStudySelection}
|
||||
onClose={(e) => {
|
||||
setNewStudySelectionAnchorEl(null)
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
setNewStudySelectionAnchorEl(null)
|
||||
setOpenNewSingleObjectiveStudyDialog(true)
|
||||
}}
|
||||
>
|
||||
Single-objective
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
setNewStudySelectionAnchorEl(null)
|
||||
setOpenNewMultiObjectiveStudyDialog(true)
|
||||
}}
|
||||
>
|
||||
Multi-objective
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Toolbar>
|
||||
</Container>
|
||||
</AppBar>
|
||||
@@ -221,13 +293,15 @@ export const StudyList: FC<{}> = () => {
|
||||
</Card>
|
||||
</Container>
|
||||
<Dialog
|
||||
open={openNewStudyDialog}
|
||||
open={openNewSingleObjectiveStudyDialog}
|
||||
onClose={(e) => {
|
||||
handleCloseNewStudyDialog()
|
||||
handleCloseNewSingleObjectiveStudyDialog()
|
||||
}}
|
||||
aria-labelledby="create-study-form-dialog-title"
|
||||
aria-labelledby="create-single-objective-study-form-dialog-title"
|
||||
>
|
||||
<DialogTitle id="create-study-form-dialog-title">New study</DialogTitle>
|
||||
<DialogTitle id="create-single-objective-study-form-dialog-title">
|
||||
New single-objective study
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
To create a new study, please enter the study name here.
|
||||
@@ -259,11 +333,14 @@ export const StudyList: FC<{}> = () => {
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleCloseNewStudyDialog} color="primary">
|
||||
<Button
|
||||
onClick={handleCloseNewSingleObjectiveStudyDialog}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleCreateNewStudy}
|
||||
onClick={handleCreateNewSingleObjectiveStudy}
|
||||
color="primary"
|
||||
disabled={newStudyName === "" || newStudyNameAlreadyUsed}
|
||||
>
|
||||
@@ -271,6 +348,99 @@ export const StudyList: FC<{}> = () => {
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
open={openNewMultiObjectiveStudyDialog}
|
||||
onClose={(e) => {
|
||||
handleCloseNewMultiObjectiveStudyDialog()
|
||||
}}
|
||||
aria-labelledby="create-multi-objective-study-form-dialog-title"
|
||||
>
|
||||
<DialogTitle id="create-multi-objective-study-form-dialog-title">
|
||||
New multi-objective study
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
To create a new study, please enter the study name and directions
|
||||
here.
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
autoFocus
|
||||
error={newStudyNameAlreadyUsed}
|
||||
helperText={
|
||||
newStudyNameAlreadyUsed ? `"${newStudyName}" is already used` : ""
|
||||
}
|
||||
label="Study name"
|
||||
type="text"
|
||||
onChange={(e) => {
|
||||
setNewStudyName(e.target.value)
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
</DialogContent>
|
||||
{directions.map((d, i) => (
|
||||
<DialogContent key={i}>
|
||||
<FormControl component="fieldset" fullWidth={true}>
|
||||
<FormLabel component="legend">Objective {i}:</FormLabel>
|
||||
<Select
|
||||
value={directions[i]}
|
||||
onChange={(e) => {
|
||||
let newVal: StudyDirection[] = [...directions]
|
||||
newVal[i] = e.target.value as StudyDirection
|
||||
setDirections(newVal)
|
||||
}}
|
||||
>
|
||||
<MenuItem value="minimize">Minimize</MenuItem>
|
||||
<MenuItem value="maximize">Maximize</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</DialogContent>
|
||||
))}
|
||||
<DialogContent>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<Add />}
|
||||
className={classes.objectiveButton}
|
||||
onClick={(e) => {
|
||||
const newVal: StudyDirection[] = [...directions, "minimize"]
|
||||
setDirections(newVal)
|
||||
}}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<Remove />}
|
||||
className={classes.objectiveButton}
|
||||
disabled={directions.length <= 1}
|
||||
onClick={(e) => {
|
||||
let newVal: StudyDirection[] = [...directions]
|
||||
newVal.pop()
|
||||
setDirections(newVal)
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={handleCloseNewMultiObjectiveStudyDialog}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleCreateNewMultiObjectiveStudy}
|
||||
color="primary"
|
||||
disabled={
|
||||
newStudyName === "" ||
|
||||
newStudyNameAlreadyUsed ||
|
||||
directions.length === 0
|
||||
}
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
open={openDeleteStudyDialog}
|
||||
onClose={(e) => {
|
||||
|
||||
Reference in new issue
Block a user