Skip to content

Commit

Permalink
Use strings instead of Algorithm classes in .All and .Available.
Browse files Browse the repository at this point in the history
  • Loading branch information
janosg committed Nov 5, 2024
1 parent 2853d96 commit 445747a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 16 deletions.
25 changes: 18 additions & 7 deletions .tools/create_algo_selection_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,24 +377,35 @@ def _get_base_class_code() -> str:
@dataclass(frozen=True)
class AlgoSelection:
@property
def All(self) -> list[Type[Algorithm]]:
def _all(self) -> list[Type[Algorithm]]:
raw = [field.default for field in self.__dataclass_fields__.values()]
return cast(list[Type[Algorithm]], raw)
@property
def Available(self) -> list[Type[Algorithm]]:
def _available(self) -> list[Type[Algorithm]]:
_all = self._all()
return [
a for a in self.All if a.__algo_info__.is_available # type: ignore
a for a in _all if a.__algo_info__.is_available # type: ignore
]
@property
def All(self) -> list[str]:
return [a.__algo_info__.name for a in self._all()] # type: ignore
@property
def Available(self) -> list[str]:
return [a.__algo_info__.name for a in self._available()] # type: ignore
@property
def _all_algorithms_dict(self) -> dict[str, Type[Algorithm]]:
return {a.__algo_info__.name: a for a in self.All} # type: ignore
return {a.__algo_info__.name: a for a in self._all()} # type: ignore
@property
def _available_algorithms_dict(self) -> dict[str, Type[Algorithm]]:
return {a.__algo_info__.name: a for a in self.Available} # type: ignore
return {
a.__algo_info__.name: a # type: ignore
for a in self._available()
}
""")
return out
Expand Down
42 changes: 40 additions & 2 deletions docs/source/how_to/how_to_algorithm_selection.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,46 @@
"problems and which one works best needs to be found out through experimentation.\n",
"```\n",
"\n",
"## Filtering algorithms \n",
"\n",
"An even more fine-grained version of the decision tree is built into optimagic's \n",
"algorithm selection tool, which let's you filter algorithms based on the properties of \n",
"your problem. To make this concrete, assume we are looking for a **local** optimizer for \n",
"a **differentiable scalar** problem with **bound constraints**. \n",
"\n",
"To find all algorithms that match our criteria, we can simply type:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import optimagic as om\n",
"\n",
"om.algos.Local.GradientBased.Scalar.Bounded.All"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The filters you can apply are: GradientBased, GradientFree, Global, Local, Bounded, \n",
"LinearConstrained, NonlinearConstrained, Scalar, LeastSquares, Likelihood, and Parallel.\n",
"You can apply them in any order your want. They are also discoverable, i.e. the \n",
"autocomplete feature of your editor will show you all filters you can apply as well \n",
"as all algorithms that satisfy your current filters. \n",
"\n",
"Using `.All` shows you all algorithms optimagic knows of. Some of them require optional \n",
"dependencies. To show only the algorithms that are available with the packages you have \n",
"currently installed, use `.Available` instead of `.All`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(algo-selection-example-problem)=\n",
"\n",
"## An example problem\n",
Expand Down Expand Up @@ -106,8 +146,6 @@
"source": [
"import numpy as np\n",
"\n",
"import optimagic as om\n",
"\n",
"\n",
"def trid_scalar(x):\n",
" \"\"\"Implement Trid function: https://www.sfu.ca/~ssurjano/trid.html.\"\"\"\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,15 @@ om.minimize(
)
```


For a list of all supported algorithm names, see {ref}`list_of_algorithms`.

```{note}
To provide full compatibility with scipy, you can also select algorithms with the
argument `method` under their original scipy name, e.g. `method="L-BFGS-B"` instead
of `algorithm="scipy_lbfgsb"`.
```

## Configuring an algorithm

To configure an algorithm, you can pass a dictionary to the `algo_options` argument.
Expand Down
24 changes: 17 additions & 7 deletions src/optimagic/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,36 @@

@dataclass(frozen=True)
class AlgoSelection:
@property
def All(self) -> list[Type[Algorithm]]:
def _all(self) -> list[Type[Algorithm]]:
raw = [field.default for field in self.__dataclass_fields__.values()]
return cast(list[Type[Algorithm]], raw)

@property
def Available(self) -> list[Type[Algorithm]]:
def _available(self) -> list[Type[Algorithm]]:
_all = self._all()
return [
a
for a in self.All
for a in _all
if a.__algo_info__.is_available # type: ignore
]

@property
def All(self) -> list[str]:
return [a.__algo_info__.name for a in self._all()] # type: ignore

@property
def Available(self) -> list[str]:
return [a.__algo_info__.name for a in self._available()] # type: ignore

@property
def _all_algorithms_dict(self) -> dict[str, Type[Algorithm]]:
return {a.__algo_info__.name: a for a in self.All} # type: ignore
return {a.__algo_info__.name: a for a in self._all()} # type: ignore

@property
def _available_algorithms_dict(self) -> dict[str, Type[Algorithm]]:
return {a.__algo_info__.name: a for a in self.Available} # type: ignore
return {
a.__algo_info__.name: a # type: ignore
for a in self._available()
}


@dataclass(frozen=True)
Expand Down

0 comments on commit 445747a

Please sign in to comment.