diff --git a/docs/index.html b/docs/index.html
index d0e1c9b..d960a6b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -132,7 +132,7 @@
OPL – Optimisation problem library
>=2 |
2 |
|
- unknown | box |
+ box | unknown |
>=2 |
|
|
@@ -154,7 +154,7 @@ OPL – Optimisation problem library
|
BSO-toolbox |
C++ |
- {'40 seconds', '1 second'} |
+ {'1 second', '40 seconds'} |
https://github.com/TUe-excellent-buildings/BSO-toolbox |
Building Spatial Design toolbox (TU/e) |
|
@@ -292,7 +292,7 @@ OPL – Optimisation problem library
fn_gasoline |
Gasoline direct injection engine design |
Problem |
- integer | continuous |
+ continuous | integer |
14 |
2 |
multi-fidelity |
@@ -661,7 +661,7 @@ OPL – Optimisation problem library
gen_ealain |
Ealain |
Generator |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
[1, 10, 2, 3, 4, 5, 6, 7, 8, 9] |
dynamic | multi-fidelity |
@@ -767,11 +767,11 @@ OPL – Optimisation problem library
|
>=1 |
|
- IOHGNBG | GNBG-II |
+ GNBG-II | IOHGNBG |
|
|
- https://github.com/IOHprofiler/IOHGNBG | https://github.com/rohitsalgotra/GNBG-II |
- IOHprofiler version of GNBG | Generalized Numerical Benchmark Generator version 2 |
+ https://github.com/rohitsalgotra/GNBG-II | https://github.com/IOHprofiler/IOHGNBG |
+ Generalized Numerical Benchmark Generator version 2 | IOHprofiler version of GNBG |
|
|
|
@@ -1030,7 +1030,7 @@ OPL – Optimisation problem library
gen_randoptgen |
RandOptGen |
Generator |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
[1, 10, 2, 3, 4, 5, 6, 7, 8, 9] |
|
@@ -1194,7 +1194,7 @@ OPL – Optimisation problem library
suite_amvop |
AMVOP |
Suite |
- categorical | continuous | integer |
+ integer | categorical | continuous |
>=3 |
1 |
|
@@ -1317,7 +1317,7 @@ OPL – Optimisation problem library
suite_bbob_biobj_mixint |
BBOB-biobj-mixint |
Suite |
- integer | continuous |
+ continuous | integer |
10-320 |
2 |
|
@@ -1440,7 +1440,7 @@ OPL – Optimisation problem library
suite_bbob_mixint |
BBOB-mixint |
Suite |
- integer | continuous |
+ continuous | integer |
10-320 |
1 |
|
@@ -1833,11 +1833,11 @@ OPL – Optimisation problem library
|
>=1 |
|
- IOHexperimenter | CEC2022 reference code |
+ CEC2022 reference code | IOHexperimenter |
C++/Python |
|
- https://github.com/IOHprofiler/IOHexperimenter | https://github.com/P-N-Suganthan/2022-SO-BO |
- IOHprofiler experimenter framework | Suganthan's reference implementation |
+ https://github.com/P-N-Suganthan/2022-SO-BO | https://github.com/IOHprofiler/IOHexperimenter |
+ Suganthan's reference implementation | IOHprofiler experimenter framework |
|
|
|
@@ -1891,7 +1891,7 @@ OPL – Optimisation problem library
suite_cre |
CRE |
Suite |
- integer | continuous |
+ continuous | integer |
6-14 |
[2, 3, 4, 5] |
|
@@ -1932,7 +1932,7 @@ OPL – Optimisation problem library
suite_cuter |
CUTEr |
Suite |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
1 |
|
@@ -1973,11 +1973,11 @@ OPL – Optimisation problem library
suite_cutest |
CUTEst |
Suite |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
1 |
|
- unknown | box |
+ box | unknown |
>=2 |
|
|
@@ -2178,11 +2178,11 @@ OPL – Optimisation problem library
suite_expobench |
EXPObench |
Suite |
- continuous | categorical | integer |
+ continuous | integer | categorical |
30-405 |
1 |
noisy |
- unknown | box |
+ box | unknown |
>=2 |
|
["observational", "real-life"] |
@@ -2204,7 +2204,7 @@ OPL – Optimisation problem library
10-135 |
EXPObench |
Python |
- {'2 seconds', '80 seconds'} |
+ {'80 seconds', '2 seconds'} |
https://github.com/AlgTUDelft/ExpensiveOptimBenchmark |
EXPensive Optimization benchmark library (wind farm layout, gas filter design, pipe shape, hyperparameter tuning, hospital simulation) |
|
@@ -2245,7 +2245,7 @@ OPL – Optimisation problem library
|
coco-gbea |
|
- {'34 seconds', '5 seconds'} |
+ {'5 seconds', '34 seconds'} |
https://github.com/ttusar/coco-gbea |
Game-Benchmark for Evolutionary Algorithms (COCO fork) |
|
@@ -2325,11 +2325,11 @@ OPL – Optimisation problem library
|
>=1 |
|
- IOHGNBG | GNBG-II |
+ GNBG-II | IOHGNBG |
|
|
- https://github.com/IOHprofiler/IOHGNBG | https://github.com/rohitsalgotra/GNBG-II |
- IOHprofiler version of GNBG | Generalized Numerical Benchmark Generator version 2 |
+ https://github.com/rohitsalgotra/GNBG-II | https://github.com/IOHprofiler/IOHGNBG |
+ Generalized Numerical Benchmark Generator version 2 | IOHprofiler version of GNBG |
|
|
|
@@ -2696,7 +2696,7 @@ OPL – Optimisation problem library
|
MECHBench |
Python |
- {'1 minute', '7 minutes'} |
+ {'7 minutes', '1 minute'} |
https://github.com/BayesOptApp/MECHBench |
Structural mechanics design optimization benchmark |
|
@@ -3039,7 +3039,7 @@ OPL – Optimisation problem library
suite_re |
RE |
Suite |
- integer | continuous |
+ continuous | integer |
4-14 |
[2, 3, 4, 5, 6, 7, 8, 9] |
|
@@ -3080,7 +3080,7 @@ OPL – Optimisation problem library
suite_rwmvop |
RWMVOP |
Suite |
- categorical | continuous | integer |
+ integer | categorical | continuous |
>=3 |
1 |
|
diff --git a/docs/problems.html b/docs/problems.html
index ab6e46f..d0aa9ac 100644
--- a/docs/problems.html
+++ b/docs/problems.html
@@ -106,7 +106,7 @@
>=2 |
2 |
|
- unknown | box |
+ box | unknown |
>=2 |
|
|
@@ -128,7 +128,7 @@
|
BSO-toolbox |
C++ |
- {'40 seconds', '1 second'} |
+ {'1 second', '40 seconds'} |
https://github.com/TUe-excellent-buildings/BSO-toolbox |
Building Spatial Design toolbox (TU/e) |
|
@@ -266,7 +266,7 @@
fn_gasoline |
Gasoline direct injection engine design |
Problem |
- integer | continuous |
+ continuous | integer |
14 |
2 |
multi-fidelity |
@@ -635,7 +635,7 @@
gen_ealain |
Ealain |
Generator |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
[1, 10, 2, 3, 4, 5, 6, 7, 8, 9] |
dynamic | multi-fidelity |
@@ -741,11 +741,11 @@
|
>=1 |
|
- IOHGNBG | GNBG-II |
+ GNBG-II | IOHGNBG |
|
|
- https://github.com/IOHprofiler/IOHGNBG | https://github.com/rohitsalgotra/GNBG-II |
- IOHprofiler version of GNBG | Generalized Numerical Benchmark Generator version 2 |
+ https://github.com/rohitsalgotra/GNBG-II | https://github.com/IOHprofiler/IOHGNBG |
+ Generalized Numerical Benchmark Generator version 2 | IOHprofiler version of GNBG |
|
|
|
@@ -1004,7 +1004,7 @@
gen_randoptgen |
RandOptGen |
Generator |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
[1, 10, 2, 3, 4, 5, 6, 7, 8, 9] |
|
@@ -1168,7 +1168,7 @@
suite_amvop |
AMVOP |
Suite |
- categorical | continuous | integer |
+ integer | categorical | continuous |
>=3 |
1 |
|
@@ -1291,7 +1291,7 @@
suite_bbob_biobj_mixint |
BBOB-biobj-mixint |
Suite |
- integer | continuous |
+ continuous | integer |
10-320 |
2 |
|
@@ -1414,7 +1414,7 @@
suite_bbob_mixint |
BBOB-mixint |
Suite |
- integer | continuous |
+ continuous | integer |
10-320 |
1 |
|
@@ -1807,11 +1807,11 @@
|
>=1 |
|
- IOHexperimenter | CEC2022 reference code |
+ CEC2022 reference code | IOHexperimenter |
C++/Python |
|
- https://github.com/IOHprofiler/IOHexperimenter | https://github.com/P-N-Suganthan/2022-SO-BO |
- IOHprofiler experimenter framework | Suganthan's reference implementation |
+ https://github.com/P-N-Suganthan/2022-SO-BO | https://github.com/IOHprofiler/IOHexperimenter |
+ Suganthan's reference implementation | IOHprofiler experimenter framework |
|
|
|
@@ -1865,7 +1865,7 @@
suite_cre |
CRE |
Suite |
- integer | continuous |
+ continuous | integer |
6-14 |
[2, 3, 4, 5] |
|
@@ -1906,7 +1906,7 @@
suite_cuter |
CUTEr |
Suite |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
1 |
|
@@ -1947,11 +1947,11 @@
suite_cutest |
CUTEst |
Suite |
- binary | continuous | integer |
+ integer | binary | continuous |
>=3 |
1 |
|
- unknown | box |
+ box | unknown |
>=2 |
|
|
@@ -2152,11 +2152,11 @@
suite_expobench |
EXPObench |
Suite |
- continuous | categorical | integer |
+ continuous | integer | categorical |
30-405 |
1 |
noisy |
- unknown | box |
+ box | unknown |
>=2 |
|
["observational", "real-life"] |
@@ -2178,7 +2178,7 @@
10-135 |
EXPObench |
Python |
- {'2 seconds', '80 seconds'} |
+ {'80 seconds', '2 seconds'} |
https://github.com/AlgTUDelft/ExpensiveOptimBenchmark |
EXPensive Optimization benchmark library (wind farm layout, gas filter design, pipe shape, hyperparameter tuning, hospital simulation) |
|
@@ -2219,7 +2219,7 @@
|
coco-gbea |
|
- {'34 seconds', '5 seconds'} |
+ {'5 seconds', '34 seconds'} |
https://github.com/ttusar/coco-gbea |
Game-Benchmark for Evolutionary Algorithms (COCO fork) |
|
@@ -2299,11 +2299,11 @@
|
>=1 |
|
- IOHGNBG | GNBG-II |
+ GNBG-II | IOHGNBG |
|
|
- https://github.com/IOHprofiler/IOHGNBG | https://github.com/rohitsalgotra/GNBG-II |
- IOHprofiler version of GNBG | Generalized Numerical Benchmark Generator version 2 |
+ https://github.com/rohitsalgotra/GNBG-II | https://github.com/IOHprofiler/IOHGNBG |
+ Generalized Numerical Benchmark Generator version 2 | IOHprofiler version of GNBG |
|
|
|
@@ -2670,7 +2670,7 @@
|
MECHBench |
Python |
- {'1 minute', '7 minutes'} |
+ {'7 minutes', '1 minute'} |
https://github.com/BayesOptApp/MECHBench |
Structural mechanics design optimization benchmark |
|
@@ -3013,7 +3013,7 @@
suite_re |
RE |
Suite |
- integer | continuous |
+ continuous | integer |
4-14 |
[2, 3, 4, 5, 6, 7, 8, 9] |
|
@@ -3054,7 +3054,7 @@
suite_rwmvop |
RWMVOP |
Suite |
- categorical | continuous | integer |
+ integer | categorical | continuous |
>=3 |
1 |
|
diff --git a/problems.yaml b/problems.yaml
index 9ff660a..880fbc3 100644
--- a/problems.yaml
+++ b/problems.yaml
@@ -44,8 +44,8 @@ fn_building_spatial:
evaluations.
dynamic_type: null
evaluation_time:
- - 40 seconds
- 1 second
+ - 40 seconds
fidelity_levels: null
implementations:
- impl_bso_toolbox
@@ -70,11 +70,11 @@ fn_building_spatial:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
fn_convex_dtlz2:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -119,10 +119,6 @@ fn_emdo:
can_evaluate_objectives_independently: null
code_examples: null
constraints:
- - equality: null
- hard: yes
- number: null
- type: box
- equality: null
hard: some
number: null
@@ -131,6 +127,10 @@ fn_emdo:
hard: yes
number: 12
type: unknown
+ - equality: null
+ hard: yes
+ number: null
+ type: box
description: "# Goal\nFind a design of a synchronous electric motor for power steering
systems that minimizes costs and satisfies all constraints.\n\n# Motivation\n\
Challenging to find good solutions in a limited time.\n\n# Key Challenges\n* Time-consuming
@@ -205,8 +205,8 @@ fn_fleetopt:
type: problem
variables:
- dim:
- - 13208
- 54
+ - 13208
type: integer
fn_gasoline:
allows_partial_evaluation: null
@@ -282,11 +282,11 @@ fn_invdeceptive_deceptive_rotell:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
fn_inverted_dtlz1:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -398,11 +398,11 @@ fn_onemax_sphere_deceptive_rotell:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
fn_onemax_sphere_zeromax_sphere:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -434,11 +434,11 @@ fn_onemax_sphere_zeromax_sphere:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
fn_radar_waveform:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -598,11 +598,11 @@ gen_ealain:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
- dim:
max: null
min: 1
@@ -929,11 +929,11 @@ gen_randoptgen:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
- dim:
max: null
min: 1
@@ -1082,8 +1082,8 @@ impl_bonobench:
impl_bso_toolbox:
description: Building Spatial Design toolbox (TU/e)
evaluation_time:
- - 40 seconds
- 1 second
+ - 40 seconds
language: C++
links:
- type: repository
@@ -1221,8 +1221,8 @@ impl_gasoline:
impl_gbea:
description: Game-Benchmark for Evolutionary Algorithms (COCO fork)
evaluation_time:
- - 5 seconds
- 34 seconds
+ - 5 seconds
language: null
links:
- type: repository
@@ -1306,8 +1306,8 @@ impl_ma_bbob:
impl_mechbench:
description: Structural mechanics design optimization benchmark
evaluation_time:
- - 7 minutes
- 1 minute
+ - 7 minutes
language: Python
links:
- type: repository
@@ -1518,15 +1518,15 @@ suite_amvop:
- dim:
max: null
min: 1
- type: continuous
+ type: categorical
- dim:
max: null
min: 1
- type: integer
+ type: continuous
- dim:
max: null
min: 1
- type: categorical
+ type: integer
suite_bbob:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -1625,11 +1625,11 @@ suite_bbob_biobj_mixint:
- dim:
max: 160
min: 5
- type: integer
+ type: continuous
- dim:
max: 160
min: 5
- type: continuous
+ type: integer
suite_bbob_constrained:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -1732,11 +1732,11 @@ suite_bbob_mixint:
- dim:
max: 160
min: 5
- type: integer
+ type: continuous
- dim:
max: 160
min: 5
- type: continuous
+ type: integer
suite_bbob_noisy:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -1946,8 +1946,8 @@ suite_cec2013:
evaluation_time: null
fidelity_levels: null
implementations:
- - impl_iohexperimenter
- impl_cec2013
+ - impl_iohexperimenter
long_name: null
modality: null
name: CEC2013
@@ -2052,8 +2052,8 @@ suite_cec2022:
evaluation_time: null
fidelity_levels: null
implementations:
- - impl_iohexperimenter
- impl_cec2022
+ - impl_iohexperimenter
long_name: null
modality: null
name: CEC2022
@@ -2196,11 +2196,11 @@ suite_cuter:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
- dim:
max: null
min: 1
@@ -2210,16 +2210,16 @@ suite_cutest:
can_evaluate_objectives_independently: null
code_examples: null
constraints:
- - equality: null
- hard: yes
- number: null
- type: box
- equality: null
hard: some
number:
max: null
min: 1
type: unknown
+ - equality: null
+ hard: yes
+ number: null
+ type: box
description: CUTEst for optimization software
dynamic_type: null
evaluation_time: null
@@ -2248,11 +2248,11 @@ suite_cutest:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
- dim:
max: null
min: 1
@@ -2454,14 +2454,14 @@ suite_expobench:
can_evaluate_objectives_independently: null
code_examples: null
constraints:
- - equality: null
- hard: yes
- number: null
- type: box
- equality: null
hard: some
number: null
type: unknown
+ - equality: null
+ hard: yes
+ number: null
+ type: box
description: Wind farm layout optimization, gas filter design, pipe shape
optimization, hyperparameter tuning, and hospital simulation
dynamic_type: null
@@ -2473,8 +2473,8 @@ suite_expobench:
modality: null
name: EXPObench
noise_type:
- - real-life
- observational
+ - real-life
objectives:
- 1
problems: null
@@ -2492,15 +2492,15 @@ suite_expobench:
- dim:
max: 135
min: 10
- type: integer
+ type: categorical
- dim:
max: 135
min: 10
- type: categorical
+ type: continuous
- dim:
max: 135
min: 10
- type: continuous
+ type: integer
suite_gbea:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -2703,11 +2703,11 @@ suite_l1_zdt:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
suite_l2_dtlz:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -2777,11 +2777,11 @@ suite_l2_zdt:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
suite_l3_dtlz:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -2851,11 +2851,11 @@ suite_l3_zdt:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
suite_maop:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -3131,10 +3131,10 @@ suite_modact:
tags: null
type: suite
variables:
- - dim: 20
- type: integer
- dim: 20
type: continuous
+ - dim: 20
+ type: integer
suite_morepo:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -3272,11 +3272,11 @@ suite_re:
- dim:
max: 7
min: 2
- type: integer
+ type: continuous
- dim:
max: 7
min: 2
- type: continuous
+ type: integer
suite_rwmvop:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -3312,15 +3312,15 @@ suite_rwmvop:
- dim:
max: null
min: 1
- type: continuous
+ type: categorical
- dim:
max: null
min: 1
- type: integer
+ type: continuous
- dim:
max: null
min: 1
- type: categorical
+ type: integer
suite_sbox_cost:
allows_partial_evaluation: null
can_evaluate_objectives_independently: null
@@ -3590,8 +3590,8 @@ suite_zdt:
- dim:
max: null
min: 1
- type: continuous
+ type: binary
- dim:
max: null
min: 1
- type: binary
+ type: continuous
diff --git a/src/opltools/schema.py b/src/opltools/schema.py
index ea80c89..ec3925e 100644
--- a/src/opltools/schema.py
+++ b/src/opltools/schema.py
@@ -1,12 +1,66 @@
+import json
from enum import Enum
from typing import Any
from typing_extensions import Self
-from pydantic import BaseModel, RootModel, ConfigDict, model_validator
+from pydantic import (
+ BaseModel,
+ RootModel,
+ ConfigDict,
+ SerializerFunctionWrapHandler,
+ model_serializer,
+ model_validator,
+)
from .yesnosome import YesNoSome
from .utils import ValueRange, union_range
+def _sort_key(item: Any) -> Any:
+ """Stable, total-order sort key for an already-serialized set member.
+
+ Scalars (str, int, float, bool) sort by their natural ordering, so e.g.
+ `{2, 10}` sorts numerically rather than as the strings "10" < "2". Dicts
+ and lists (serialized nested models) have no natural ordering, so those
+ fall back to a canonical JSON string.
+ """
+ if isinstance(item, (dict, list)):
+ return json.dumps(item, sort_keys=True, default=str)
+ return item
+
+
+class _CanonicalMixin:
+ """Serialize any `set`-valued field as a sorted list.
+
+ `set` iteration order depends on Python's hash randomization, so two
+ otherwise-identical models can serialize to different YAML on every run
+ unless we impose a fixed order. Rather than hand-listing every `set`
+ field on every model, this inspects each model's actual field values at
+ serialization time and sorts whichever ones happen to be a `set` -
+ including nested models' own sets (each canonicalizes itself the same
+ way) and any `extra="allow"` fields.
+ """
+
+ @model_serializer(mode="wrap")
+ def _canonicalize(self, handler: SerializerFunctionWrapHandler) -> Any:
+ data = handler(self)
+ values = dict(self.__dict__)
+ extra = getattr(self, "__pydantic_extra__", None)
+ if extra:
+ values.update(extra)
+ for name, value in values.items():
+ if isinstance(value, set) and name in data:
+ data[name] = sorted(data[name], key=_sort_key)
+ return data
+
+
+class CanonicalModel(_CanonicalMixin, BaseModel):
+ pass
+
+
+class CanonicalRootModel(_CanonicalMixin, RootModel):
+ pass
+
+
class OPLType(Enum):
problem = "problem"
suite = "suite"
@@ -14,7 +68,7 @@ class OPLType(Enum):
implementation = "implementation"
-class Link(BaseModel):
+class Link(CanonicalModel):
type: str | None = None
url: str
@@ -22,12 +76,12 @@ def __hash__(self):
return hash(self.type) + hash(self.url)
-class Thing(BaseModel):
+class Thing(CanonicalModel):
type: OPLType
model_config = ConfigDict(extra="allow")
-class Objectives(RootModel):
+class Objectives(CanonicalRootModel):
root: int | set[int] | ValueRange = 0
def union(self, other: Self) -> Self:
@@ -43,7 +97,7 @@ class VariableType(Enum):
unknown = "unknown"
-class Variable(BaseModel):
+class Variable(CanonicalModel):
type: VariableType = VariableType.unknown
dim: int | set[int] | ValueRange | None = 0
@@ -62,7 +116,7 @@ class ConstraintType(Enum):
unknown = "unknown"
-class Constraint(BaseModel):
+class Constraint(CanonicalModel):
type: ConstraintType = ConstraintType.unknown
hard: YesNoSome | None = None
equality: YesNoSome | None = None
@@ -73,7 +127,7 @@ def __hash__(self):
return hash((self.type, self.hard, self.equality, number))
-class Reference(BaseModel):
+class Reference(CanonicalModel):
title: str | None = None
authors: list[str] | None = None
link: Link | None = None
@@ -136,7 +190,7 @@ class Generator(ProblemLike):
type: OPLType = OPLType.generator
-class Library(RootModel):
+class Library(CanonicalRootModel):
root: dict[str, Problem | Generator | Suite | Implementation] = {}
def _check_id_references(self, ids, type: OPLType) -> None: