mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-11 12:30:25 +08:00
Run fmt
This commit is contained in:
Vendored
+68
-68
@@ -1,99 +1,99 @@
|
||||
declare const IS_VSCODE: boolean
|
||||
declare const IS_VSCODE: boolean;
|
||||
|
||||
type TrialState = "Running" | "Complete" | "Pruned" | "Fail" | "Waiting"
|
||||
type TrialStateFinished = "Complete" | "Fail" | "Pruned"
|
||||
type StudyDirection = "maximize" | "minimize" | "not_set"
|
||||
type TrialState = "Running" | "Complete" | "Pruned" | "Fail" | "Waiting";
|
||||
type TrialStateFinished = "Complete" | "Fail" | "Pruned";
|
||||
type StudyDirection = "maximize" | "minimize" | "not_set";
|
||||
|
||||
type OptunaStorage = {
|
||||
getStudies: () => Promise<StudySummary[]>
|
||||
getStudy: (idx: number) => Promise<Study | null>
|
||||
}
|
||||
getStudies: () => Promise<StudySummary[]>;
|
||||
getStudy: (idx: number) => Promise<Study | null>;
|
||||
};
|
||||
|
||||
type FloatDistribution = {
|
||||
type: "FloatDistribution"
|
||||
low: number
|
||||
high: number
|
||||
step: number | null
|
||||
log: boolean
|
||||
}
|
||||
type: "FloatDistribution";
|
||||
low: number;
|
||||
high: number;
|
||||
step: number | null;
|
||||
log: boolean;
|
||||
};
|
||||
|
||||
type IntDistribution = {
|
||||
type: "IntDistribution"
|
||||
low: number
|
||||
high: number
|
||||
step: number | null
|
||||
log: boolean
|
||||
}
|
||||
type: "IntDistribution";
|
||||
low: number;
|
||||
high: number;
|
||||
step: number | null;
|
||||
log: boolean;
|
||||
};
|
||||
|
||||
type CategoricalChoiceType = null | boolean | number | string
|
||||
type CategoricalChoiceType = null | boolean | number | string;
|
||||
type CategoricalDistribution = {
|
||||
type: "CategoricalDistribution"
|
||||
choices: CategoricalChoiceType[]
|
||||
}
|
||||
type: "CategoricalDistribution";
|
||||
choices: CategoricalChoiceType[];
|
||||
};
|
||||
|
||||
type TrialIntermediateValue = {
|
||||
step: number
|
||||
value: number
|
||||
}
|
||||
step: number;
|
||||
value: number;
|
||||
};
|
||||
|
||||
type Distribution =
|
||||
| FloatDistribution
|
||||
| IntDistribution
|
||||
| CategoricalDistribution
|
||||
| CategoricalDistribution;
|
||||
|
||||
type Attribute = {
|
||||
key: string
|
||||
value: string
|
||||
}
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
type AttributeSpec = {
|
||||
key: string
|
||||
sortable: boolean
|
||||
}
|
||||
key: string;
|
||||
sortable: boolean;
|
||||
};
|
||||
|
||||
type StudySummary = {
|
||||
study_id: number
|
||||
study_name: string
|
||||
directions: StudyDirection[]
|
||||
}
|
||||
study_id: number;
|
||||
study_name: string;
|
||||
directions: StudyDirection[];
|
||||
};
|
||||
|
||||
type Study = {
|
||||
study_id: number
|
||||
study_name: string
|
||||
directions: StudyDirection[]
|
||||
union_search_space: SearchSpaceItem[]
|
||||
intersection_search_space: SearchSpaceItem[]
|
||||
union_user_attrs: AttributeSpec[]
|
||||
datetime_start?: Date
|
||||
trials: Trial[]
|
||||
}
|
||||
study_id: number;
|
||||
study_name: string;
|
||||
directions: StudyDirection[];
|
||||
union_search_space: SearchSpaceItem[];
|
||||
intersection_search_space: SearchSpaceItem[];
|
||||
union_user_attrs: AttributeSpec[];
|
||||
datetime_start?: Date;
|
||||
trials: Trial[];
|
||||
};
|
||||
|
||||
type Trial = {
|
||||
trial_id: number
|
||||
number: number
|
||||
study_id: number
|
||||
state: TrialState
|
||||
values?: number[]
|
||||
params: TrialParam[]
|
||||
intermediate_values: TrialIntermediateValue[]
|
||||
user_attrs: Attribute[]
|
||||
datetime_start?: Date
|
||||
datetime_complete?: Date
|
||||
}
|
||||
trial_id: number;
|
||||
number: number;
|
||||
study_id: number;
|
||||
state: TrialState;
|
||||
values?: number[];
|
||||
params: TrialParam[];
|
||||
intermediate_values: TrialIntermediateValue[];
|
||||
user_attrs: Attribute[];
|
||||
datetime_start?: Date;
|
||||
datetime_complete?: Date;
|
||||
};
|
||||
|
||||
type TrialParam = {
|
||||
name: string
|
||||
param_internal_value: number
|
||||
param_external_value: CategoricalChoiceType
|
||||
param_external_type: string
|
||||
distribution: Distribution
|
||||
}
|
||||
name: string;
|
||||
param_internal_value: number;
|
||||
param_external_value: CategoricalChoiceType;
|
||||
param_external_type: string;
|
||||
distribution: Distribution;
|
||||
};
|
||||
|
||||
type SearchSpaceItem = {
|
||||
name: string
|
||||
}
|
||||
name: string;
|
||||
};
|
||||
|
||||
type ParamImportance = {
|
||||
name: string
|
||||
importance: number
|
||||
}
|
||||
name: string;
|
||||
importance: number;
|
||||
};
|
||||
|
||||
+142
-140
@@ -1,4 +1,4 @@
|
||||
import { SetterOrUpdater } from "recoil"
|
||||
import { SetterOrUpdater } from "recoil";
|
||||
|
||||
// JournalStorage
|
||||
enum JournalOperation {
|
||||
@@ -15,92 +15,92 @@ enum JournalOperation {
|
||||
}
|
||||
|
||||
interface JournalOpBase {
|
||||
op_code: JournalOperation
|
||||
workor_id: string
|
||||
op_code: JournalOperation;
|
||||
workor_id: string;
|
||||
}
|
||||
|
||||
interface JournalOpCreateStudy extends JournalOpBase {
|
||||
study_name: string
|
||||
directions: number[] // TODO(gen740): introduce Study Direction enum
|
||||
study_name: string;
|
||||
directions: number[]; // TODO(gen740): introduce Study Direction enum
|
||||
}
|
||||
|
||||
interface JournalOpDeleteStudy extends JournalOpBase {
|
||||
study_id: number
|
||||
study_id: number;
|
||||
}
|
||||
|
||||
interface JournalOpCreateTrial extends JournalOpBase {
|
||||
study_id: number
|
||||
datetime_start?: string
|
||||
datetime_complete?: string
|
||||
distributions?: { [key: string]: string }
|
||||
study_id: number;
|
||||
datetime_start?: string;
|
||||
datetime_complete?: string;
|
||||
distributions?: { [key: string]: string };
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
params?: { [key: string]: any }
|
||||
params?: { [key: string]: any };
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
user_attrs?: { [key: string]: any }
|
||||
user_attrs?: { [key: string]: any };
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
system_attrs?: { [key: string]: any }
|
||||
state?: number
|
||||
intermediate_values?: { [key: string]: number }
|
||||
value?: number
|
||||
values?: number[]
|
||||
system_attrs?: { [key: string]: any };
|
||||
state?: number;
|
||||
intermediate_values?: { [key: string]: number };
|
||||
value?: number;
|
||||
values?: number[];
|
||||
}
|
||||
|
||||
interface JournalOpSetTrialParam extends JournalOpBase {
|
||||
trial_id: number
|
||||
param_name: string
|
||||
param_value_internal: number
|
||||
distribution: string
|
||||
trial_id: number;
|
||||
param_name: string;
|
||||
param_value_internal: number;
|
||||
distribution: string;
|
||||
}
|
||||
|
||||
interface JournalOpSetTrialStateValue extends JournalOpBase {
|
||||
trial_id: number
|
||||
state: number
|
||||
values?: number[]
|
||||
datetime_start?: string
|
||||
datetime_complete?: string
|
||||
trial_id: number;
|
||||
state: number;
|
||||
values?: number[];
|
||||
datetime_start?: string;
|
||||
datetime_complete?: string;
|
||||
}
|
||||
|
||||
interface JournalOpSetTrialIntermediateValue extends JournalOpBase {
|
||||
trial_id: number
|
||||
step: number
|
||||
intermediate_value: number
|
||||
trial_id: number;
|
||||
step: number;
|
||||
intermediate_value: number;
|
||||
}
|
||||
|
||||
interface JournalOpSetTrialUserAttr extends JournalOpBase {
|
||||
trial_id: number
|
||||
trial_id: number;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
user_attr: { [key: string]: any }
|
||||
user_attr: { [key: string]: any };
|
||||
}
|
||||
|
||||
const trialStateNumToTrialState = (state: number): TrialState => {
|
||||
switch (state) {
|
||||
case 0:
|
||||
return "Running"
|
||||
return "Running";
|
||||
case 1:
|
||||
return "Complete"
|
||||
return "Complete";
|
||||
case 2:
|
||||
return "Pruned"
|
||||
return "Pruned";
|
||||
case 3:
|
||||
return "Fail"
|
||||
return "Fail";
|
||||
case 4:
|
||||
return "Waiting"
|
||||
return "Waiting";
|
||||
default:
|
||||
return "Running"
|
||||
return "Running";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const parseDistribution = (distribution: string): Distribution => {
|
||||
const distributionJson = JSON.parse(distribution)
|
||||
const distributionJson = JSON.parse(distribution);
|
||||
if (distributionJson.name === "IntDistribution") {
|
||||
return {
|
||||
...distributionJson.attributes,
|
||||
type: "IntDistribution",
|
||||
}
|
||||
};
|
||||
} else if (distributionJson.name === "FloatDistribution") {
|
||||
return {
|
||||
...distributionJson.attributes,
|
||||
type: "FloatDistribution",
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
// TODO(gen740): support other types
|
||||
@@ -110,59 +110,59 @@ const parseDistribution = (distribution: string): Distribution => {
|
||||
return {
|
||||
pytype: "str",
|
||||
value: choice.toString(),
|
||||
}
|
||||
};
|
||||
}),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class JournalStorage {
|
||||
private studies: Study[] = []
|
||||
private nextStudyId = 0
|
||||
private studyIdToTrialIDs: Map<number, number[]> = new Map()
|
||||
private trialIdToStudyId: Map<number, number> = new Map()
|
||||
private trialID = 0
|
||||
private studies: Study[] = [];
|
||||
private nextStudyId = 0;
|
||||
private studyIdToTrialIDs: Map<number, number[]> = new Map();
|
||||
private trialIdToStudyId: Map<number, number> = new Map();
|
||||
private trialID = 0;
|
||||
|
||||
public getStudies(): Study[] {
|
||||
for (const study of this.studies) {
|
||||
const unionUserAttrs: Set<string> = new Set()
|
||||
const unionSearchSpace: Set<string> = new Set()
|
||||
let intersectionSearchSpace: string[] = []
|
||||
const unionUserAttrs: Set<string> = new Set();
|
||||
const unionSearchSpace: Set<string> = new Set();
|
||||
let intersectionSearchSpace: string[] = [];
|
||||
|
||||
study.trials.forEach((trial, index) => {
|
||||
for (const userAttr of trial.user_attrs) {
|
||||
unionUserAttrs.add(userAttr.key)
|
||||
unionUserAttrs.add(userAttr.key);
|
||||
}
|
||||
for (const param of trial.params) {
|
||||
unionSearchSpace.add(param.name)
|
||||
unionSearchSpace.add(param.name);
|
||||
}
|
||||
if (index === 0) {
|
||||
intersectionSearchSpace = Array.from(unionSearchSpace)
|
||||
intersectionSearchSpace = Array.from(unionSearchSpace);
|
||||
} else {
|
||||
intersectionSearchSpace = intersectionSearchSpace.filter((name) => {
|
||||
return trial.params.some((param) => param.name === name)
|
||||
})
|
||||
return trial.params.some((param) => param.name === name);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
study.union_user_attrs = Array.from(unionUserAttrs).map((key) => {
|
||||
return {
|
||||
key: key,
|
||||
sortable: false,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
study.union_search_space = Array.from(unionSearchSpace).map((name) => {
|
||||
return {
|
||||
name: name,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
study.intersection_search_space = intersectionSearchSpace.map((name) => {
|
||||
return {
|
||||
name: name,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return this.studies
|
||||
return this.studies;
|
||||
}
|
||||
|
||||
public applyCreateStudy(log: JournalOpCreateStudy): void {
|
||||
@@ -174,20 +174,22 @@ class JournalStorage {
|
||||
intersection_search_space: [],
|
||||
union_user_attrs: [],
|
||||
trials: [],
|
||||
})
|
||||
this.nextStudyId++
|
||||
});
|
||||
this.nextStudyId++;
|
||||
}
|
||||
|
||||
public applyDeleteStudy(log: JournalOpDeleteStudy): void {
|
||||
this.studies = this.studies.filter((item) => item.study_id !== log.study_id)
|
||||
this.studies = this.studies.filter(
|
||||
(item) => item.study_id !== log.study_id,
|
||||
);
|
||||
}
|
||||
|
||||
public applyCreateTrial(log: JournalOpCreateTrial): void {
|
||||
const thisStudy = this.studies.find(
|
||||
(item) => item.study_id === log.study_id
|
||||
)
|
||||
(item) => item.study_id === log.study_id,
|
||||
);
|
||||
if (thisStudy === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const params: TrialParam[] =
|
||||
@@ -195,32 +197,32 @@ class JournalStorage {
|
||||
? []
|
||||
: Object.entries(log.params).map(([name, value]) => {
|
||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||
const distribution = parseDistribution(log.distributions![name])
|
||||
const distribution = parseDistribution(log.distributions![name]);
|
||||
return {
|
||||
name: name,
|
||||
param_internal_value: value,
|
||||
param_external_type: distribution.type,
|
||||
param_external_value: (() => {
|
||||
if (distribution.type === "FloatDistribution") {
|
||||
return value.toString()
|
||||
return value.toString();
|
||||
} else if (distribution.type === "IntDistribution") {
|
||||
return value.toString()
|
||||
return value.toString();
|
||||
} else {
|
||||
return distribution.choices[value]
|
||||
return distribution.choices[value];
|
||||
}
|
||||
})(),
|
||||
distribution: distribution,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
const userAtter = log.user_attrs
|
||||
? Object.entries(log.user_attrs).map(([key, value]) => {
|
||||
return {
|
||||
key: key,
|
||||
value: value,
|
||||
}
|
||||
};
|
||||
})
|
||||
: []
|
||||
: [];
|
||||
|
||||
thisStudy.trials.push({
|
||||
trial_id: this.trialID,
|
||||
@@ -229,11 +231,11 @@ class JournalStorage {
|
||||
state: trialStateNumToTrialState(log.state ?? 0),
|
||||
values: (() => {
|
||||
if (log.value !== undefined) {
|
||||
return [log.value]
|
||||
return [log.value];
|
||||
} else if (log.values !== undefined) {
|
||||
return log.values
|
||||
return log.values;
|
||||
} else {
|
||||
return undefined
|
||||
return undefined;
|
||||
}
|
||||
})(),
|
||||
params: params,
|
||||
@@ -245,36 +247,36 @@ class JournalStorage {
|
||||
datetime_complete: log.datetime_complete
|
||||
? new Date(log.datetime_complete)
|
||||
: undefined,
|
||||
})
|
||||
});
|
||||
this.studyIdToTrialIDs.set(
|
||||
log.study_id,
|
||||
this.studyIdToTrialIDs.get(log.study_id)?.concat([this.trialID]) ?? [
|
||||
this.trialID,
|
||||
]
|
||||
)
|
||||
this.trialIdToStudyId.set(this.trialID, log.study_id)
|
||||
this.trialID++
|
||||
],
|
||||
);
|
||||
this.trialIdToStudyId.set(this.trialID, log.study_id);
|
||||
this.trialID++;
|
||||
}
|
||||
|
||||
private getStudyAndTrial(trial_id: number): [Study?, Trial?] {
|
||||
const study = this.studies.find(
|
||||
(item) => item.study_id === this.trialIdToStudyId.get(trial_id)
|
||||
)
|
||||
(item) => item.study_id === this.trialIdToStudyId.get(trial_id),
|
||||
);
|
||||
if (study === undefined) {
|
||||
return [undefined, undefined]
|
||||
return [undefined, undefined];
|
||||
}
|
||||
|
||||
const trial = study.trials.find((item) => item.trial_id === trial_id)
|
||||
const trial = study.trials.find((item) => item.trial_id === trial_id);
|
||||
if (trial === undefined) {
|
||||
return [study, undefined]
|
||||
return [study, undefined];
|
||||
}
|
||||
return [study, trial]
|
||||
return [study, trial];
|
||||
}
|
||||
|
||||
public applySetTrialParam(log: JournalOpSetTrialParam) {
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id)
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id);
|
||||
if (thisStudy === undefined || thisTrial === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
thisTrial.params.push({
|
||||
name: log.param_name,
|
||||
@@ -282,51 +284,51 @@ class JournalStorage {
|
||||
param_external_type: "FloatDistribution",
|
||||
param_external_value: log.param_value_internal.toString(),
|
||||
distribution: parseDistribution(log.distribution),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
public applySetTrialStateValues(log: JournalOpSetTrialStateValue): void {
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id)
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id);
|
||||
if (thisStudy === undefined || thisTrial === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
thisTrial.state = trialStateNumToTrialState(log.state)
|
||||
thisTrial.values = log.values
|
||||
thisTrial.state = trialStateNumToTrialState(log.state);
|
||||
thisTrial.values = log.values;
|
||||
thisTrial.datetime_start = log.datetime_start
|
||||
? new Date(log.datetime_start)
|
||||
: undefined
|
||||
: undefined;
|
||||
thisTrial.datetime_complete = log.datetime_complete
|
||||
? new Date(log.datetime_complete)
|
||||
: undefined
|
||||
: undefined;
|
||||
}
|
||||
|
||||
public applySetTrialIntermediateValue(
|
||||
log: JournalOpSetTrialIntermediateValue
|
||||
log: JournalOpSetTrialIntermediateValue,
|
||||
) {
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id)
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id);
|
||||
if (thisStudy === undefined || thisTrial === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
thisTrial.intermediate_values.push({
|
||||
step: log.step,
|
||||
value: log.intermediate_value,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
public applySetTrialUserAttr(log: JournalOpSetTrialUserAttr) {
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id)
|
||||
const [thisStudy, thisTrial] = this.getStudyAndTrial(log.trial_id);
|
||||
if (thisStudy === undefined || thisTrial === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
for (const [key, value] of Object.entries(log.user_attr)) {
|
||||
const index = thisTrial.user_attrs.findIndex((item) => item.key === key)
|
||||
const index = thisTrial.user_attrs.findIndex((item) => item.key === key);
|
||||
if (index !== -1) {
|
||||
thisTrial.user_attrs[index].value = value.toString()
|
||||
thisTrial.user_attrs[index].value = value.toString();
|
||||
} else {
|
||||
thisTrial.user_attrs.push({
|
||||
key: key,
|
||||
value: value.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,58 +336,58 @@ class JournalStorage {
|
||||
|
||||
export const loadJournalStorage = (
|
||||
arrayBuffer: ArrayBuffer,
|
||||
setter: SetterOrUpdater<Study[]>
|
||||
setter: SetterOrUpdater<Study[]>,
|
||||
): void => {
|
||||
const decoder = new TextDecoder("utf-8")
|
||||
const logs = decoder.decode(arrayBuffer).split("\n")
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const logs = decoder.decode(arrayBuffer).split("\n");
|
||||
|
||||
const journalStorage = new JournalStorage()
|
||||
const journalStorage = new JournalStorage();
|
||||
|
||||
for (const log of logs) {
|
||||
if (log === "") {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
const parsedLog: JournalOpBase = JSON.parse(log)
|
||||
const parsedLog: JournalOpBase = JSON.parse(log);
|
||||
switch (parsedLog.op_code) {
|
||||
case JournalOperation.CREATE_STUDY:
|
||||
journalStorage.applyCreateStudy(parsedLog as JournalOpCreateStudy)
|
||||
break
|
||||
journalStorage.applyCreateStudy(parsedLog as JournalOpCreateStudy);
|
||||
break;
|
||||
case JournalOperation.DELETE_STUDY:
|
||||
journalStorage.applyDeleteStudy(parsedLog as JournalOpDeleteStudy)
|
||||
break
|
||||
journalStorage.applyDeleteStudy(parsedLog as JournalOpDeleteStudy);
|
||||
break;
|
||||
case JournalOperation.SET_STUDY_USER_ATTR:
|
||||
// Unsupported
|
||||
break
|
||||
break;
|
||||
case JournalOperation.SET_STUDY_SYSTEM_ATTR:
|
||||
// Unsupported
|
||||
break
|
||||
break;
|
||||
case JournalOperation.CREATE_TRIAL:
|
||||
journalStorage.applyCreateTrial(parsedLog as JournalOpCreateTrial)
|
||||
break
|
||||
journalStorage.applyCreateTrial(parsedLog as JournalOpCreateTrial);
|
||||
break;
|
||||
case JournalOperation.SET_TRIAL_PARAM:
|
||||
journalStorage.applySetTrialParam(parsedLog as JournalOpSetTrialParam)
|
||||
break
|
||||
journalStorage.applySetTrialParam(parsedLog as JournalOpSetTrialParam);
|
||||
break;
|
||||
case JournalOperation.SET_TRIAL_STATE_VALUES:
|
||||
journalStorage.applySetTrialStateValues(
|
||||
parsedLog as JournalOpSetTrialStateValue
|
||||
)
|
||||
break
|
||||
parsedLog as JournalOpSetTrialStateValue,
|
||||
);
|
||||
break;
|
||||
case JournalOperation.SET_TRIAL_INTERMEDIATE_VALUE:
|
||||
journalStorage.applySetTrialIntermediateValue(
|
||||
parsedLog as JournalOpSetTrialIntermediateValue
|
||||
)
|
||||
break
|
||||
parsedLog as JournalOpSetTrialIntermediateValue,
|
||||
);
|
||||
break;
|
||||
case JournalOperation.SET_TRIAL_USER_ATTR:
|
||||
journalStorage.applySetTrialUserAttr(
|
||||
parsedLog as JournalOpSetTrialUserAttr
|
||||
)
|
||||
break
|
||||
parsedLog as JournalOpSetTrialUserAttr,
|
||||
);
|
||||
break;
|
||||
case JournalOperation.SET_TRIAL_SYSTEM_ATTR:
|
||||
// Unsupported
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const studies = journalStorage.getStudies()
|
||||
setter((prev) => [...prev, ...studies])
|
||||
}
|
||||
const studies = journalStorage.getStudies();
|
||||
setter((prev) => [...prev, ...studies]);
|
||||
};
|
||||
|
||||
+144
-142
@@ -1,35 +1,37 @@
|
||||
// @ts-ignore
|
||||
import sqlite3InitModule from "@sqlite.org/sqlite-wasm"
|
||||
import { SetterOrUpdater } from "recoil"
|
||||
import sqlite3InitModule from "@sqlite.org/sqlite-wasm";
|
||||
import { SetterOrUpdater } from "recoil";
|
||||
|
||||
export const loadSQLite3Storage = async (
|
||||
arrayBuffer: ArrayBuffer,
|
||||
setter: SetterOrUpdater<Study[]>
|
||||
setter: SetterOrUpdater<Study[]>,
|
||||
) => {
|
||||
const sqlite3Storage = new SQLite3Storage(arrayBuffer)
|
||||
const studySummaries = await sqlite3Storage.getStudies()
|
||||
const sqlite3Storage = new SQLite3Storage(arrayBuffer);
|
||||
const studySummaries = await sqlite3Storage.getStudies();
|
||||
const studies = (
|
||||
await Promise.all(
|
||||
studySummaries.map((summary) => sqlite3Storage.getStudy(summary.study_id))
|
||||
studySummaries.map((summary) =>
|
||||
sqlite3Storage.getStudy(summary.study_id),
|
||||
),
|
||||
)
|
||||
).filter((s) => s !== null) as Study[]
|
||||
setter((prev) => [...prev, ...studies])
|
||||
}
|
||||
).filter((s) => s !== null) as Study[];
|
||||
setter((prev) => [...prev, ...studies]);
|
||||
};
|
||||
|
||||
type SQLite3DB = {
|
||||
exec(options: {
|
||||
sql: string
|
||||
sql: string;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (...args: any[]) => void
|
||||
}): void
|
||||
}
|
||||
callback: (...args: any[]) => void;
|
||||
}): void;
|
||||
};
|
||||
|
||||
export class SQLite3Storage implements OptunaStorage {
|
||||
db: Promise<SQLite3DB>
|
||||
summaries_cache: StudySummary[] | null
|
||||
db: Promise<SQLite3DB>;
|
||||
summaries_cache: StudySummary[] | null;
|
||||
constructor(arrayBuffer: ArrayBuffer) {
|
||||
this.db = this.initDB(arrayBuffer)
|
||||
this.summaries_cache = null
|
||||
this.db = this.initDB(arrayBuffer);
|
||||
this.summaries_cache = null;
|
||||
}
|
||||
|
||||
async initDB(arrayBuffer: ArrayBuffer): Promise<SQLite3DB> {
|
||||
@@ -38,8 +40,8 @@ export class SQLite3Storage implements OptunaStorage {
|
||||
printErr: console.log,
|
||||
// @ts-ignore
|
||||
}).then((sqlite3) => {
|
||||
const p = sqlite3.wasm.allocFromTypedArray(arrayBuffer)
|
||||
const db = new sqlite3.oo1.DB()
|
||||
const p = sqlite3.wasm.allocFromTypedArray(arrayBuffer);
|
||||
const db = new sqlite3.oo1.DB();
|
||||
const rc = sqlite3.capi.sqlite3_deserialize(
|
||||
// @ts-ignore
|
||||
db.pointer,
|
||||
@@ -47,72 +49,72 @@ export class SQLite3Storage implements OptunaStorage {
|
||||
p,
|
||||
arrayBuffer.byteLength,
|
||||
arrayBuffer.byteLength,
|
||||
sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE
|
||||
)
|
||||
db.checkRc(rc)
|
||||
return db
|
||||
})
|
||||
sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE,
|
||||
);
|
||||
db.checkRc(rc);
|
||||
return db;
|
||||
});
|
||||
}
|
||||
|
||||
getStudies = async (): Promise<StudySummary[]> => {
|
||||
const db = await this.db
|
||||
this.summaries_cache = getStudySummaries(db)
|
||||
return this.summaries_cache
|
||||
}
|
||||
const db = await this.db;
|
||||
this.summaries_cache = getStudySummaries(db);
|
||||
return this.summaries_cache;
|
||||
};
|
||||
|
||||
getStudy = async (idx: number): Promise<Study | null> => {
|
||||
const db = await this.db
|
||||
const schemaVersion = getSchemaVersion(db)
|
||||
const db = await this.db;
|
||||
const schemaVersion = getSchemaVersion(db);
|
||||
if (!isSupportedSchema(schemaVersion)) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
if (this.summaries_cache === null) {
|
||||
this.summaries_cache = getStudySummaries(db)
|
||||
this.summaries_cache = getStudySummaries(db);
|
||||
}
|
||||
const summary = this.summaries_cache[idx]
|
||||
const summary = this.summaries_cache[idx];
|
||||
if (summary === undefined) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
return getStudy(db, schemaVersion, summary)
|
||||
}
|
||||
return getStudy(db, schemaVersion, summary);
|
||||
};
|
||||
}
|
||||
|
||||
const getSchemaVersion = (db: SQLite3DB): string => {
|
||||
let schemaVersion = ""
|
||||
let schemaVersion = "";
|
||||
db.exec({
|
||||
sql: "SELECT version_num FROM alembic_version LIMIT 1",
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (vals: any[]) => {
|
||||
schemaVersion = vals[0]
|
||||
schemaVersion = vals[0];
|
||||
},
|
||||
})
|
||||
return schemaVersion
|
||||
}
|
||||
});
|
||||
return schemaVersion;
|
||||
};
|
||||
|
||||
const isSupportedSchema = (schemaVersion: string): boolean => {
|
||||
const lowestVersion = "v2.6.0.a" // supported: "v3.2.0.a", "v3.0.0.{a,b,c,d}", "v2.6.0.a"
|
||||
if (schemaVersion === lowestVersion) return true
|
||||
return isGreaterSchemaVersion(schemaVersion, lowestVersion)
|
||||
}
|
||||
const lowestVersion = "v2.6.0.a"; // supported: "v3.2.0.a", "v3.0.0.{a,b,c,d}", "v2.6.0.a"
|
||||
if (schemaVersion === lowestVersion) return true;
|
||||
return isGreaterSchemaVersion(schemaVersion, lowestVersion);
|
||||
};
|
||||
|
||||
const isGreaterSchemaVersion = (
|
||||
leftVersion: string,
|
||||
rightVersion: string
|
||||
rightVersion: string,
|
||||
): boolean => {
|
||||
// return leftVersion > rightVersion
|
||||
const leftSuffix = leftVersion.split(".").reverse()[0]
|
||||
const rightSuffix = rightVersion.split(".").reverse()[0]
|
||||
const leftVersion_ = leftVersion.replace(/\D/g, "")
|
||||
const rightVersion_ = rightVersion.replace(/\D/g, "")
|
||||
const leftSuffix = leftVersion.split(".").reverse()[0];
|
||||
const rightSuffix = rightVersion.split(".").reverse()[0];
|
||||
const leftVersion_ = leftVersion.replace(/\D/g, "");
|
||||
const rightVersion_ = rightVersion.replace(/\D/g, "");
|
||||
|
||||
const left = Number(leftVersion_)
|
||||
const right = Number(rightVersion_)
|
||||
if (left === right) return leftSuffix > rightSuffix
|
||||
return left > right
|
||||
}
|
||||
const left = Number(leftVersion_);
|
||||
const right = Number(rightVersion_);
|
||||
if (left === right) return leftSuffix > rightSuffix;
|
||||
return left > right;
|
||||
};
|
||||
|
||||
const getStudySummaries = (db: SQLite3DB): StudySummary[] => {
|
||||
const summaries: StudySummary[] = []
|
||||
const summaries: StudySummary[] = [];
|
||||
db.exec({
|
||||
sql:
|
||||
"SELECT s.study_id, s.study_name, sd.direction, sd.objective" +
|
||||
@@ -120,31 +122,31 @@ const getStudySummaries = (db: SQLite3DB): StudySummary[] => {
|
||||
" ON s.study_id = sd.study_id ORDER BY sd.study_direction_id",
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (vals: any[]) => {
|
||||
const studyId = vals[0]
|
||||
const studyName = vals[1]
|
||||
const studyId = vals[0];
|
||||
const studyName = vals[1];
|
||||
const direction: StudyDirection =
|
||||
vals[2] === "MINIMIZE" ? "minimize" : "maximize"
|
||||
const objective = vals[3]
|
||||
vals[2] === "MINIMIZE" ? "minimize" : "maximize";
|
||||
const objective = vals[3];
|
||||
|
||||
if (objective === 0) {
|
||||
summaries.push({
|
||||
study_id: studyId,
|
||||
study_name: studyName,
|
||||
directions: [direction],
|
||||
})
|
||||
return
|
||||
});
|
||||
return;
|
||||
}
|
||||
const index = summaries.findIndex((s) => s.study_id === studyId)
|
||||
summaries[index].directions.push(direction)
|
||||
const index = summaries.findIndex((s) => s.study_id === studyId);
|
||||
summaries[index].directions.push(direction);
|
||||
},
|
||||
})
|
||||
return summaries
|
||||
}
|
||||
});
|
||||
return summaries;
|
||||
};
|
||||
|
||||
const getStudy = (
|
||||
db: SQLite3DB,
|
||||
schemaVersion: string,
|
||||
summary: StudySummary
|
||||
summary: StudySummary,
|
||||
): Study => {
|
||||
const study: Study = {
|
||||
study_id: summary.study_id,
|
||||
@@ -154,57 +156,57 @@ const getStudy = (
|
||||
intersection_search_space: [],
|
||||
union_user_attrs: [],
|
||||
trials: [],
|
||||
}
|
||||
};
|
||||
|
||||
let intersection_search_space: Set<SearchSpaceItem> = new Set()
|
||||
study.trials = getTrials(db, summary.study_id, schemaVersion)
|
||||
let intersection_search_space: Set<SearchSpaceItem> = new Set();
|
||||
study.trials = getTrials(db, summary.study_id, schemaVersion);
|
||||
for (const trial of study.trials) {
|
||||
const userAttrs = getTrialUserAttributes(db, trial.trial_id)
|
||||
const userAttrs = getTrialUserAttributes(db, trial.trial_id);
|
||||
for (const attr of userAttrs) {
|
||||
if (study.union_user_attrs.findIndex((s) => s.key === attr.key) === -1) {
|
||||
study.union_user_attrs.push({ key: attr.key, sortable: false })
|
||||
study.union_user_attrs.push({ key: attr.key, sortable: false });
|
||||
}
|
||||
}
|
||||
|
||||
const params = getTrialParams(db, trial.trial_id)
|
||||
const param_names = new Set<string>()
|
||||
const params = getTrialParams(db, trial.trial_id);
|
||||
const param_names = new Set<string>();
|
||||
for (const param of params) {
|
||||
param_names.add(param.name)
|
||||
param_names.add(param.name);
|
||||
if (
|
||||
study.union_search_space.findIndex((s) => s.name === param.name) === -1
|
||||
) {
|
||||
study.union_search_space.push({ name: param.name })
|
||||
study.union_search_space.push({ name: param.name });
|
||||
}
|
||||
}
|
||||
if (intersection_search_space.size === 0) {
|
||||
param_names.forEach((s) => {
|
||||
intersection_search_space.add({ name: s })
|
||||
})
|
||||
intersection_search_space.add({ name: s });
|
||||
});
|
||||
} else {
|
||||
intersection_search_space = new Set(
|
||||
Array.from(intersection_search_space).filter((s) =>
|
||||
param_names.has(s.name)
|
||||
)
|
||||
)
|
||||
param_names.has(s.name),
|
||||
),
|
||||
);
|
||||
}
|
||||
trial.params = params
|
||||
trial.user_attrs = userAttrs
|
||||
trial.params = params;
|
||||
trial.user_attrs = userAttrs;
|
||||
}
|
||||
study.intersection_search_space = Array.from(intersection_search_space)
|
||||
return study
|
||||
}
|
||||
study.intersection_search_space = Array.from(intersection_search_space);
|
||||
return study;
|
||||
};
|
||||
|
||||
const getTrials = (
|
||||
db: SQLite3DB,
|
||||
studyId: number,
|
||||
schemaVersion: string
|
||||
schemaVersion: string,
|
||||
): Trial[] => {
|
||||
const trials: Trial[] = []
|
||||
const trials: Trial[] = [];
|
||||
db.exec({
|
||||
sql: `SELECT trial_id, number, state, datetime_start, datetime_complete FROM trials WHERE study_id = ${studyId} ORDER BY number`,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (vals: any[]) => {
|
||||
const trialId = vals[0]
|
||||
const trialId = vals[0];
|
||||
const state: TrialState =
|
||||
vals[2] === "COMPLETE"
|
||||
? "Complete"
|
||||
@@ -214,7 +216,7 @@ const getTrials = (
|
||||
? "Running"
|
||||
: vals[2] === "WAITING"
|
||||
? "Waiting"
|
||||
: "Fail"
|
||||
: "Fail";
|
||||
const trial: Trial = {
|
||||
trial_id: trialId,
|
||||
number: vals[1],
|
||||
@@ -224,25 +226,25 @@ const getTrials = (
|
||||
intermediate_values: getTrialIntermediateValues(
|
||||
db,
|
||||
trialId,
|
||||
schemaVersion
|
||||
schemaVersion,
|
||||
),
|
||||
params: [], // Set this column later
|
||||
user_attrs: [], // Set this column later
|
||||
datetime_start: vals[3],
|
||||
datetime_complete: vals[4],
|
||||
}
|
||||
trials.push(trial)
|
||||
};
|
||||
trials.push(trial);
|
||||
},
|
||||
})
|
||||
return trials
|
||||
}
|
||||
});
|
||||
return trials;
|
||||
};
|
||||
|
||||
const getTrialValues = (
|
||||
db: SQLite3DB,
|
||||
trialId: number,
|
||||
schemaVersion: string
|
||||
schemaVersion: string,
|
||||
): number[] => {
|
||||
const values: number[] = []
|
||||
const values: number[] = [];
|
||||
if (isGreaterSchemaVersion(schemaVersion, "v3.0.0.c")) {
|
||||
db.exec({
|
||||
sql: `SELECT value, value_type FROM trial_values WHERE trial_id = ${trialId} ORDER BY objective`,
|
||||
@@ -253,59 +255,59 @@ const getTrialValues = (
|
||||
? -Infinity
|
||||
: vals[1] === "INF_POS"
|
||||
? Infinity
|
||||
: vals[0]
|
||||
)
|
||||
: vals[0],
|
||||
);
|
||||
},
|
||||
})
|
||||
});
|
||||
} else {
|
||||
db.exec({
|
||||
sql: `SELECT value FROM trial_values WHERE trial_id = ${trialId} ORDER BY objective`,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (vals: any[]) => {
|
||||
values.push(vals[0])
|
||||
values.push(vals[0]);
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
return values
|
||||
}
|
||||
return values;
|
||||
};
|
||||
|
||||
const getTrialParams = (db: SQLite3DB, trialId: number): TrialParam[] => {
|
||||
const params: TrialParam[] = []
|
||||
const params: TrialParam[] = [];
|
||||
db.exec({
|
||||
sql: `SELECT param_name, param_value, distribution_json FROM trial_params WHERE trial_id = ${trialId}`,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
callback: (vals: any[]) => {
|
||||
const distribution = parseDistributionJSON(vals[2])
|
||||
const distribution = parseDistributionJSON(vals[2]);
|
||||
params.push({
|
||||
name: vals[0],
|
||||
param_internal_value: vals[1],
|
||||
param_external_type: distribution.type,
|
||||
param_external_value: paramInternalValueToExternalValue(
|
||||
distribution,
|
||||
vals[1]
|
||||
vals[1],
|
||||
),
|
||||
distribution: distribution,
|
||||
})
|
||||
});
|
||||
},
|
||||
})
|
||||
return params
|
||||
}
|
||||
});
|
||||
return params;
|
||||
};
|
||||
|
||||
const paramInternalValueToExternalValue = (
|
||||
distribution: Distribution,
|
||||
internalValue: number
|
||||
internalValue: number,
|
||||
): CategoricalChoiceType => {
|
||||
if (distribution.type === "FloatDistribution") {
|
||||
return internalValue.toString()
|
||||
return internalValue.toString();
|
||||
}
|
||||
if (distribution.type === "IntDistribution") {
|
||||
return internalValue.toString()
|
||||
return internalValue.toString();
|
||||
}
|
||||
return distribution.choices[internalValue]
|
||||
}
|
||||
return distribution.choices[internalValue];
|
||||
};
|
||||
|
||||
const parseDistributionJSON = (t: string): Distribution => {
|
||||
const parsed = JSON.parse(t)
|
||||
const parsed = JSON.parse(t);
|
||||
if (parsed.name === "FloatDistribution") {
|
||||
return {
|
||||
type: "FloatDistribution",
|
||||
@@ -313,7 +315,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: parsed.attributes.step as number,
|
||||
log: parsed.attributes.log as boolean,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "UniformDistribution") {
|
||||
return {
|
||||
@@ -322,7 +324,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: null,
|
||||
log: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "LogUniformDistribution") {
|
||||
return {
|
||||
@@ -331,7 +333,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: null,
|
||||
log: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "DiscreteUniformDistribution") {
|
||||
return {
|
||||
@@ -340,7 +342,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: parsed.attributes.q,
|
||||
log: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "IntDistribution") {
|
||||
return {
|
||||
@@ -349,7 +351,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: parsed.attributes.step as number,
|
||||
log: parsed.attributes.log as boolean,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "IntUniformDistribution") {
|
||||
return {
|
||||
@@ -358,7 +360,7 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: parsed.attributes.step as number,
|
||||
log: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
if (parsed.name === "IntLogUniformDistribution") {
|
||||
return {
|
||||
@@ -367,19 +369,19 @@ const parseDistributionJSON = (t: string): Distribution => {
|
||||
high: parsed.attributes.high as number,
|
||||
step: parsed.attributes.step as number,
|
||||
log: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: "CategoricalDistribution",
|
||||
choices: parsed.attributes.choices,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const getTrialUserAttributes = (
|
||||
db: SQLite3DB,
|
||||
trialId: number
|
||||
trialId: number,
|
||||
): Attribute[] => {
|
||||
const attrs: Attribute[] = []
|
||||
const attrs: Attribute[] = [];
|
||||
db.exec({
|
||||
sql: `SELECT key, value_json FROM trial_user_attributes WHERE trial_id = ${trialId}`,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
@@ -387,18 +389,18 @@ const getTrialUserAttributes = (
|
||||
attrs.push({
|
||||
key: vals[0],
|
||||
value: vals[1],
|
||||
})
|
||||
});
|
||||
},
|
||||
})
|
||||
return attrs
|
||||
}
|
||||
});
|
||||
return attrs;
|
||||
};
|
||||
|
||||
const getTrialIntermediateValues = (
|
||||
db: SQLite3DB,
|
||||
trialId: number,
|
||||
schemaVersion: string
|
||||
schemaVersion: string,
|
||||
): TrialIntermediateValue[] => {
|
||||
const values: TrialIntermediateValue[] = []
|
||||
const values: TrialIntermediateValue[] = [];
|
||||
if (isGreaterSchemaVersion(schemaVersion, "v3.0.0.c")) {
|
||||
db.exec({
|
||||
sql: `SELECT step, intermediate_value, intermediate_value_type FROM trial_intermediate_values WHERE trial_id = ${trialId} ORDER BY step`,
|
||||
@@ -414,9 +416,9 @@ const getTrialIntermediateValues = (
|
||||
: vals[2] === "NAN"
|
||||
? NaN
|
||||
: vals[1],
|
||||
})
|
||||
});
|
||||
},
|
||||
})
|
||||
});
|
||||
} else {
|
||||
db.exec({
|
||||
sql: `SELECT step, intermediate_value FROM trial_intermediate_values WHERE trial_id = ${trialId} ORDER BY step`,
|
||||
@@ -425,9 +427,9 @@ const getTrialIntermediateValues = (
|
||||
values.push({
|
||||
step: vals[0],
|
||||
value: vals[1],
|
||||
})
|
||||
});
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
return values
|
||||
}
|
||||
return values;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user