amplify-bbopt 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amplify_bbopt-0.1.0/LICENSE.txt +21 -0
- amplify_bbopt-0.1.0/PKG-INFO +73 -0
- amplify_bbopt-0.1.0/README.md +16 -0
- amplify_bbopt-0.1.0/amplify_bbopt/__init__.py +92 -0
- amplify_bbopt-0.1.0/amplify_bbopt/__version__.py +6 -0
- amplify_bbopt-0.1.0/amplify_bbopt/bb_func.py +281 -0
- amplify_bbopt-0.1.0/amplify_bbopt/constraint.py +365 -0
- amplify_bbopt-0.1.0/amplify_bbopt/data_gen.py +154 -0
- amplify_bbopt-0.1.0/amplify_bbopt/data_list.py +242 -0
- amplify_bbopt-0.1.0/amplify_bbopt/history.py +74 -0
- amplify_bbopt-0.1.0/amplify_bbopt/logger.py +51 -0
- amplify_bbopt-0.1.0/amplify_bbopt/misc.py +75 -0
- amplify_bbopt-0.1.0/amplify_bbopt/model.py +307 -0
- amplify_bbopt-0.1.0/amplify_bbopt/objective_example.py +58 -0
- amplify_bbopt-0.1.0/amplify_bbopt/optimizer.py +1045 -0
- amplify_bbopt-0.1.0/amplify_bbopt/optimizer_bo.py +144 -0
- amplify_bbopt-0.1.0/amplify_bbopt/plot.py +103 -0
- amplify_bbopt-0.1.0/amplify_bbopt/poly.py +86 -0
- amplify_bbopt-0.1.0/amplify_bbopt/solution_type.py +340 -0
- amplify_bbopt-0.1.0/amplify_bbopt/trainer.py +607 -0
- amplify_bbopt-0.1.0/amplify_bbopt/variable.py +1643 -0
- amplify_bbopt-0.1.0/amplify_bbopt/variables.py +380 -0
- amplify_bbopt-0.1.0/amplify_bbopt.egg-info/PKG-INFO +73 -0
- amplify_bbopt-0.1.0/amplify_bbopt.egg-info/SOURCES.txt +42 -0
- amplify_bbopt-0.1.0/amplify_bbopt.egg-info/dependency_links.txt +1 -0
- amplify_bbopt-0.1.0/amplify_bbopt.egg-info/requires.txt +7 -0
- amplify_bbopt-0.1.0/amplify_bbopt.egg-info/top_level.txt +1 -0
- amplify_bbopt-0.1.0/pyproject.toml +144 -0
- amplify_bbopt-0.1.0/setup.cfg +4 -0
- amplify_bbopt-0.1.0/setup.py +3 -0
- amplify_bbopt-0.1.0/test/test_bbfunc.py +165 -0
- amplify_bbopt-0.1.0/test/test_constraint.py +295 -0
- amplify_bbopt-0.1.0/test/test_data_gen.py +30 -0
- amplify_bbopt-0.1.0/test/test_data_list.py +74 -0
- amplify_bbopt-0.1.0/test/test_misc.py +25 -0
- amplify_bbopt-0.1.0/test/test_model.py +105 -0
- amplify_bbopt-0.1.0/test/test_objective_example.py +33 -0
- amplify_bbopt-0.1.0/test/test_optimizer.py +270 -0
- amplify_bbopt-0.1.0/test/test_optimizer_bo.py +51 -0
- amplify_bbopt-0.1.0/test/test_poly.py +23 -0
- amplify_bbopt-0.1.0/test/test_solution_type.py +64 -0
- amplify_bbopt-0.1.0/test/test_trainer.py +102 -0
- amplify_bbopt-0.1.0/test/test_variable.py +351 -0
- amplify_bbopt-0.1.0/test/test_variables.py +264 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Fixstars Amplify Corporation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: amplify-bbopt
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An Amplify-based library to facilitate black-box optimization
|
|
5
|
+
Author-email: Fixstars Amplify Corporation <y_matsuda@fixstars.com>
|
|
6
|
+
Maintainer-email: Yoshiki Matsuda <y_matsuda@fixstars.com>, Yuki Minamoto <yuki.minamoto@fixstars.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2024 Fixstars Amplify Corporation
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: Changelog, https://amplify.fixstars.com/docs/amplify-bbopt/v0/changelog.html
|
|
30
|
+
Project-URL: Documentation, https://amplify.fixstars.com/docs/amplify-bbopt/v0/
|
|
31
|
+
Project-URL: Homepage, https://amplify.fixstars.com/
|
|
32
|
+
Project-URL: Tutorial, https://amplify.fixstars.com/demo
|
|
33
|
+
Keywords: amplify,black-box optimization,Bayesian optimization
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Development Status :: 3 - Alpha
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: Intended Audience :: Science/Research
|
|
38
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
39
|
+
Classifier: Topic :: Scientific/Engineering
|
|
40
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
41
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
42
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
46
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
47
|
+
Requires-Python: >=3.9
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
License-File: LICENSE.txt
|
|
50
|
+
Requires-Dist: amplify>=1.2.0
|
|
51
|
+
Requires-Dist: numpy
|
|
52
|
+
Requires-Dist: pandas
|
|
53
|
+
Requires-Dist: torch
|
|
54
|
+
Requires-Dist: plotly
|
|
55
|
+
Requires-Dist: gpyopt
|
|
56
|
+
Requires-Dist: matplotlib
|
|
57
|
+
|
|
58
|
+
# Amplify-BBOpt
|
|
59
|
+
|
|
60
|
+
Amplify-BBOpt is a Python package to facilitate the execution of black-box optimization developed by [Fixstars Amplify](https://amplify.fixstars.com/en).
|
|
61
|
+
|
|
62
|
+
- Documentation:
|
|
63
|
+
https://amplify.fixstars.com/docs/amplify-bbopt/v0/
|
|
64
|
+
- Contributing (bug reports, improvements):
|
|
65
|
+
https://amplify.fixstars.com/en/contact
|
|
66
|
+
https://github.com/fixstars/amplify-bbopt/issues
|
|
67
|
+
|
|
68
|
+
Amplify-BBOpt is built around the [Amplify SDK](https://amplify.fixstars.com/en/docs/amplify/). Annealing-based black-box optimization methods, FMQA and kernel-QA, are available in conjunction with quantum annealing machines and Ising machines (hence using Amplify SDK). Important features include (but not limited to):
|
|
69
|
+
|
|
70
|
+
* Easy to run and change methods
|
|
71
|
+
* Applicability to high-dimensional problems
|
|
72
|
+
* Consideration of constraints
|
|
73
|
+
* Multi-objective optimization
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Amplify-BBOpt
|
|
2
|
+
|
|
3
|
+
Amplify-BBOpt is a Python package to facilitate the execution of black-box optimization developed by [Fixstars Amplify](https://amplify.fixstars.com/en).
|
|
4
|
+
|
|
5
|
+
- Documentation:
|
|
6
|
+
https://amplify.fixstars.com/docs/amplify-bbopt/v0/
|
|
7
|
+
- Contributing (bug reports, improvements):
|
|
8
|
+
https://amplify.fixstars.com/en/contact
|
|
9
|
+
https://github.com/fixstars/amplify-bbopt/issues
|
|
10
|
+
|
|
11
|
+
Amplify-BBOpt is built around the [Amplify SDK](https://amplify.fixstars.com/en/docs/amplify/). Annealing-based black-box optimization methods, FMQA and kernel-QA, are available in conjunction with quantum annealing machines and Ising machines (hence using Amplify SDK). Important features include (but not limited to):
|
|
12
|
+
|
|
13
|
+
* Easy to run and change methods
|
|
14
|
+
* Applicability to high-dimensional problems
|
|
15
|
+
* Consideration of constraints
|
|
16
|
+
* Multi-objective optimization
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Copyright (c) Fixstars Amplify Corporation.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the MIT license found in the
|
|
4
|
+
# LICENSE file in the root directory of this source tree.
|
|
5
|
+
|
|
6
|
+
from .__version__ import __version__
|
|
7
|
+
from .bb_func import BlackBoxFuncBase, BlackBoxFuncList, blackbox
|
|
8
|
+
from .constraint import Constraint, Constraints, clamp, equal_to, greater_equal, less_equal
|
|
9
|
+
from .data_gen import DatasetGenerator
|
|
10
|
+
from .data_list import DataList, load_dataset
|
|
11
|
+
from .history import History
|
|
12
|
+
from .logger import Logger, logger
|
|
13
|
+
from .misc import exec_func_neat_stdout, print_to_str
|
|
14
|
+
from .model import ModelKernel, QUBOConvertibleBase, TorchFM
|
|
15
|
+
from .optimizer import FMQAOptimizer, KernelQAOptimizer, MultiObjectiveOptimizer, OptimizerBase, QAOptimizerBase
|
|
16
|
+
from .optimizer_bo import BayesianOptimizer
|
|
17
|
+
from .plot import anneal_history, plot_history
|
|
18
|
+
from .poly import Poly
|
|
19
|
+
from .solution_type import FlatSolution, FlatSolutionDict, StructuredSolution, StructuredSolutionDict
|
|
20
|
+
from .trainer import GramMatrixHandler, ModelKernelTrainer, PolyCoefMatrixHandler, TorchFMTrainer, TrainerBase
|
|
21
|
+
from .variable import (
|
|
22
|
+
BinaryVariable,
|
|
23
|
+
BinaryVariableList,
|
|
24
|
+
DiscreteVariable,
|
|
25
|
+
DiscreteVariableList,
|
|
26
|
+
IntegerVariable,
|
|
27
|
+
IntegerVariableList,
|
|
28
|
+
RealVariable,
|
|
29
|
+
RealVariableList,
|
|
30
|
+
RealVariableListLogUniform,
|
|
31
|
+
RealVariableLogUniform,
|
|
32
|
+
Variable,
|
|
33
|
+
VariableBase,
|
|
34
|
+
VariableListBase,
|
|
35
|
+
)
|
|
36
|
+
from .variables import Variables
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"BayesianOptimizer",
|
|
40
|
+
"BinaryVariable",
|
|
41
|
+
"BinaryVariableList",
|
|
42
|
+
"BlackBoxFuncBase",
|
|
43
|
+
"BlackBoxFuncList",
|
|
44
|
+
"Constraint",
|
|
45
|
+
"Constraints",
|
|
46
|
+
"DataList",
|
|
47
|
+
"DatasetGenerator",
|
|
48
|
+
"DiscreteVariable",
|
|
49
|
+
"DiscreteVariableList",
|
|
50
|
+
"FMQAOptimizer",
|
|
51
|
+
"FlatSolution",
|
|
52
|
+
"FlatSolutionDict",
|
|
53
|
+
"GramMatrixHandler",
|
|
54
|
+
"History",
|
|
55
|
+
"IntegerVariable",
|
|
56
|
+
"IntegerVariableList",
|
|
57
|
+
"KernelQAOptimizer",
|
|
58
|
+
"Logger",
|
|
59
|
+
"ModelKernel",
|
|
60
|
+
"ModelKernelTrainer",
|
|
61
|
+
"MultiObjectiveOptimizer",
|
|
62
|
+
"OptimizerBase",
|
|
63
|
+
"Poly",
|
|
64
|
+
"PolyCoefMatrixHandler",
|
|
65
|
+
"QAOptimizerBase",
|
|
66
|
+
"QUBOConvertibleBase",
|
|
67
|
+
"RealVariable",
|
|
68
|
+
"RealVariableList",
|
|
69
|
+
"RealVariableListLogUniform",
|
|
70
|
+
"RealVariableLogUniform",
|
|
71
|
+
"StructuredSolution",
|
|
72
|
+
"StructuredSolutionDict",
|
|
73
|
+
"TorchFM",
|
|
74
|
+
"TorchFMTrainer",
|
|
75
|
+
"TrainerBase",
|
|
76
|
+
"Variable",
|
|
77
|
+
"VariableBase",
|
|
78
|
+
"VariableListBase",
|
|
79
|
+
"Variables",
|
|
80
|
+
"__version__",
|
|
81
|
+
"anneal_history",
|
|
82
|
+
"blackbox",
|
|
83
|
+
"clamp",
|
|
84
|
+
"equal_to",
|
|
85
|
+
"exec_func_neat_stdout",
|
|
86
|
+
"greater_equal",
|
|
87
|
+
"less_equal",
|
|
88
|
+
"load_dataset",
|
|
89
|
+
"logger",
|
|
90
|
+
"plot_history",
|
|
91
|
+
"print_to_str",
|
|
92
|
+
]
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Copyright (c) Fixstars Amplify Corporation.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the MIT license found in the
|
|
4
|
+
# LICENSE file in the root directory of this source tree.
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import abc
|
|
9
|
+
import contextlib
|
|
10
|
+
import inspect
|
|
11
|
+
import time
|
|
12
|
+
from typing import TYPE_CHECKING, Any, Callable, get_type_hints
|
|
13
|
+
|
|
14
|
+
from .constraint import Constraint, Constraints
|
|
15
|
+
from .variable import VariableBase, VariableListBase
|
|
16
|
+
from .variables import Variables
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Generator, Iterator
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BlackBoxFuncBase(abc.ABC):
|
|
23
|
+
"""Base class to define a black box objective function class.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
abc: Abstract base class.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self) -> None:
|
|
30
|
+
"""Initialize the base class."""
|
|
31
|
+
self._variables = Variables()
|
|
32
|
+
self._constraints = Constraints()
|
|
33
|
+
self._name = f"bb_func_{time.perf_counter_ns()}"
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def name(self) -> str:
|
|
37
|
+
"""Name of the black-box objective function."""
|
|
38
|
+
return self._name
|
|
39
|
+
|
|
40
|
+
@name.setter
|
|
41
|
+
def name(self, value: str) -> None:
|
|
42
|
+
"""Set a black-box function name. If a black-box function class is defined by using the :obj:`blackbox` decorator, the name is automatically set.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
value (str): A black-box function name.
|
|
46
|
+
""" # noqa: E501
|
|
47
|
+
self._name = value
|
|
48
|
+
|
|
49
|
+
def __setattr__(self, name: str, value: Any) -> None: # noqa: ANN401
|
|
50
|
+
"""Set decision variables.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
name (str): The name of a decision variable.
|
|
54
|
+
value (Any): A decision variable.
|
|
55
|
+
"""
|
|
56
|
+
super().__setattr__(name, value)
|
|
57
|
+
if isinstance(value, (VariableBase, VariableListBase)):
|
|
58
|
+
self._variables._set_variable(name, value) # noqa: SLF001
|
|
59
|
+
elif name in self._variables.var_dict:
|
|
60
|
+
self._variables._del_variable(name) # noqa: SLF001
|
|
61
|
+
|
|
62
|
+
def _call_objective(self, **kwargs: bool | int | float | list[bool] | list[int] | list[float]) -> float: # noqa: PYI041
|
|
63
|
+
"""Call the objective function with input arguments to the function.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
float: The objective function value.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
@contextlib.contextmanager
|
|
70
|
+
def replace_ctx() -> Generator[Any, Any, Any]:
|
|
71
|
+
try:
|
|
72
|
+
# Replace variables with values
|
|
73
|
+
for pred_name, pred_value in kwargs.items():
|
|
74
|
+
if pred_name in self._variables.var_dict:
|
|
75
|
+
super(BlackBoxFuncBase, self).__setattr__(pred_name, pred_value)
|
|
76
|
+
yield
|
|
77
|
+
finally:
|
|
78
|
+
# Replace values with variables
|
|
79
|
+
for name, bb_var in self._variables.var_dict.items():
|
|
80
|
+
self.__setattr__(name, bb_var) # noqa: PLC2801
|
|
81
|
+
|
|
82
|
+
with replace_ctx():
|
|
83
|
+
return self.objective()
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def variables(self) -> Variables:
|
|
87
|
+
"""Decision variables associated with this black-box objective function."""
|
|
88
|
+
return self._variables
|
|
89
|
+
|
|
90
|
+
@abc.abstractmethod
|
|
91
|
+
def objective(self) -> float:
|
|
92
|
+
"""Evaluate the objective function. An evaluator sets the class variable attributes having the names and valueas of the input.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
float: An objective function value.
|
|
96
|
+
""" # noqa: E501
|
|
97
|
+
|
|
98
|
+
def add_constraint(
|
|
99
|
+
self,
|
|
100
|
+
constraint: Constraint | Constraints | list[Constraint | Constraints] | list[Constraint] | list[Constraints],
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Add user-defined constraints to the black-box function class instance.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
constraint (Constraint | Constraints | list[Constraint | Constraints] | list[Constraint] | list[Constraints]): User-defined constraints.
|
|
106
|
+
""" # noqa: E501
|
|
107
|
+
self._constraints.append(constraint)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def constraints(self) -> Constraints:
|
|
111
|
+
"""User-defined constraints associated with this black-box function class."""
|
|
112
|
+
return self._constraints
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def blackbox(func: Callable) -> BlackBoxFuncBase:
|
|
116
|
+
"""Decorator function to create a black-box objective function class instance.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
func (Callable): A black-box objective function.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
ValueError: If decision variables are not appropriately set for the input arguments to a black-box function.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
BlackBoxFunc: A black-box function class instance which associates a black-box function and decision variables.
|
|
126
|
+
"""
|
|
127
|
+
parameters = inspect.signature(func).parameters
|
|
128
|
+
arguments = {v.name for v in parameters.values()}
|
|
129
|
+
|
|
130
|
+
# Set variables defined as default values
|
|
131
|
+
variables = Variables()
|
|
132
|
+
for k, v in parameters.items():
|
|
133
|
+
if isinstance(v.default, (VariableBase, VariableListBase)):
|
|
134
|
+
variables._set_variable(k, v.default) # noqa: SLF001
|
|
135
|
+
|
|
136
|
+
# Set variables defined with Annotated
|
|
137
|
+
annotations = get_type_hints(func, include_extras=True)
|
|
138
|
+
for k, v in annotations.items():
|
|
139
|
+
if k == "return":
|
|
140
|
+
continue
|
|
141
|
+
if (
|
|
142
|
+
hasattr(v, "__metadata__")
|
|
143
|
+
and len(v.__metadata__) == 1
|
|
144
|
+
and isinstance(v.__metadata__[0], (VariableBase, VariableListBase))
|
|
145
|
+
):
|
|
146
|
+
variables._set_variable(k, v.__metadata__[0]) # noqa: SLF001
|
|
147
|
+
|
|
148
|
+
missing_args = arguments - set(variables.names)
|
|
149
|
+
if len(missing_args) != 0:
|
|
150
|
+
for arg in missing_args:
|
|
151
|
+
raise ValueError(
|
|
152
|
+
f"Argument `{arg}` of {func.__name__} must be annotated with `Annotated[..., Variable(...)`"
|
|
153
|
+
f" or has a default value as `Variable`."
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
class BlackBoxFunc(BlackBoxFuncBase):
|
|
157
|
+
def __init__(self) -> None: # type: ignore
|
|
158
|
+
super().__init__()
|
|
159
|
+
self._name = func.__name__
|
|
160
|
+
for name, variable in variables.var_dict.items():
|
|
161
|
+
setattr(self, name, variable)
|
|
162
|
+
|
|
163
|
+
def __call__(self, *args, **kwargs) -> float: # noqa: ANN002, ANN003
|
|
164
|
+
return func(*args, **kwargs)
|
|
165
|
+
|
|
166
|
+
def objective(self) -> float:
|
|
167
|
+
return func(**{k: getattr(self, k) for k in self._variables.var_dict})
|
|
168
|
+
|
|
169
|
+
return BlackBoxFunc()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class BlackBoxFuncList:
|
|
173
|
+
"""Class handles multiple black-box objective functions for multi-objective optimization."""
|
|
174
|
+
|
|
175
|
+
def __init__(self, objectives: list[BlackBoxFuncBase], unify_variables: bool = False) -> None:
|
|
176
|
+
"""Initialize a black-box function list class.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
objectives (list[BlackBoxFuncBase]): A list of class instances of black-box functions to be considered in multi-objective optimization.
|
|
180
|
+
unify_variables (bool, optional): Whether to unify variables and constraints of multiple objectives in :obj:`BlackBoxFuncList.handle_duplicates`). Note that if you are performing multi-objective optimizations and want to manually operate `amplify.PolyArray` for variables (e.g. for creating custom constraints), this has to be done AFTER the last execution of :obj:`BlackBoxFuncList.handle_duplicates` with `unify_variables = True`. Since this unification is expected to be executed in the initializers of the optimizers, such operation usually should be done after the instantiation of the relevant optimizers. Defaults to `False`.
|
|
181
|
+
""" # noqa: E501
|
|
182
|
+
self._objectives: list[BlackBoxFuncBase] = []
|
|
183
|
+
|
|
184
|
+
self._constraints = Constraints()
|
|
185
|
+
for bb_func in objectives:
|
|
186
|
+
self._objectives.append(bb_func)
|
|
187
|
+
self._constraints.append(bb_func.constraints)
|
|
188
|
+
self._unify_variables = unify_variables
|
|
189
|
+
self.handle_duplicates()
|
|
190
|
+
|
|
191
|
+
def handle_duplicates(self) -> None:
|
|
192
|
+
"""Handle redundancy of variables and consistent issuance of `amplify.PolyArray` for different black-box objective functions, and unify variables and constraints. Expected to call this each time there is change in the objective functions to consider. The unification happens when `unify_variables = True` in :obj:`BlackBoxFuncList.__init__`.""" # noqa: E501
|
|
193
|
+
# Variable dictionary
|
|
194
|
+
var_dict_universe: dict[str, Any] = {}
|
|
195
|
+
for bb_func in self._objectives:
|
|
196
|
+
var_dict_universe.update(bb_func.variables.var_dict)
|
|
197
|
+
|
|
198
|
+
elemental_variable_name_list: list[str] = []
|
|
199
|
+
for bb_func in self._objectives:
|
|
200
|
+
elemental_variable_name_list += bb_func.variables.flat_names
|
|
201
|
+
self._variable_names = list(dict.fromkeys(elemental_variable_name_list))
|
|
202
|
+
|
|
203
|
+
if self._unify_variables:
|
|
204
|
+
# Nullify all existing Amplify SDK's variables.
|
|
205
|
+
for i, bb_func in enumerate(self._objectives):
|
|
206
|
+
bb_func.variables.nullify_poly_array(i)
|
|
207
|
+
# Update Variables.var_dict and re-issue Amplify SDK variables.
|
|
208
|
+
variable_generator_common = self._objectives[0].variables.variable_generator
|
|
209
|
+
for bb_func in self._objectives:
|
|
210
|
+
bb_func.variables.unify_variables(var_dict_universe, variable_generator_common)
|
|
211
|
+
# Reconstruct constraints based on unified variables described in Variables.var_dict.
|
|
212
|
+
for bb_func in self._objectives:
|
|
213
|
+
bb_func.constraints.unify_variables(var_dict_universe)
|
|
214
|
+
|
|
215
|
+
def __getattr__(self, name: str) -> BlackBoxFuncBase:
|
|
216
|
+
"""Get a variable in var_dict.
|
|
217
|
+
|
|
218
|
+
Raises:
|
|
219
|
+
ValueError: If the specified object is not found.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
BlackBoxFuncBase: A black-box function class instance.
|
|
223
|
+
"""
|
|
224
|
+
names = [obj.name for obj in self._objectives]
|
|
225
|
+
|
|
226
|
+
if name not in names:
|
|
227
|
+
raise ValueError(f"No such objective {name} is found. [{names}].")
|
|
228
|
+
return self._objectives[names.index(name)]
|
|
229
|
+
|
|
230
|
+
def add_constraint(
|
|
231
|
+
self,
|
|
232
|
+
constraint: Constraint | Constraints | list[Constraint | Constraints] | list[Constraint] | list[Constraints],
|
|
233
|
+
) -> None:
|
|
234
|
+
"""Add a user-defined constraint to the black-box function class.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
constraint ( constraint: Constraint | Constraints | list[Constraint | Constraints] | list[Constraint] | list[Constraints]): User-defined constraints.
|
|
238
|
+
""" # noqa: E501
|
|
239
|
+
self._constraints.append(constraint)
|
|
240
|
+
|
|
241
|
+
def append(self, bb: BlackBoxFuncBase) -> None:
|
|
242
|
+
"""Append a black-box function class.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
bb (BlackBoxFuncBase): A black-box function class instance.
|
|
246
|
+
"""
|
|
247
|
+
self._objectives.append(bb)
|
|
248
|
+
self.handle_duplicates()
|
|
249
|
+
|
|
250
|
+
def __len__(self) -> int:
|
|
251
|
+
"""Return a number of black-box function class instances."""
|
|
252
|
+
return len(self._objectives)
|
|
253
|
+
|
|
254
|
+
def __getitem__(self, i: int) -> BlackBoxFuncBase:
|
|
255
|
+
"""Return the i-th black-box function class instance.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
i (int): Index of a black-box function class instance.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
BlackBoxFuncBase: The i-th black-box function class instance.
|
|
262
|
+
"""
|
|
263
|
+
return self._objectives[i]
|
|
264
|
+
|
|
265
|
+
def __iter__(self) -> Iterator[BlackBoxFuncBase]:
|
|
266
|
+
"""The list of black-box function class instances.
|
|
267
|
+
|
|
268
|
+
Yields:
|
|
269
|
+
Iterator[BlackBoxFuncBase]: A black-box function class instance.
|
|
270
|
+
"""
|
|
271
|
+
yield from self._objectives
|
|
272
|
+
|
|
273
|
+
@property
|
|
274
|
+
def constraints(self) -> Constraints:
|
|
275
|
+
"""Constraints associated with this black-box function list."""
|
|
276
|
+
return self._constraints
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def variable_names(self) -> list[str]:
|
|
280
|
+
"""Names of variables associated with this black-box function list."""
|
|
281
|
+
return self._variable_names
|