Skip to content

Commit

Permalink
Merge pull request #228 from jorenham/optimize._shgo_lib
Browse files Browse the repository at this point in the history
`optimize`: complete `_shgo_lib` (private)
  • Loading branch information
jorenham authored Nov 29, 2024
2 parents 1499c09 + e8ad3e4 commit 3d9756c
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 146 deletions.
107 changes: 57 additions & 50 deletions scipy-stubs/optimize/_shgo_lib/_complex.pyi
Original file line number Diff line number Diff line change
@@ -1,97 +1,104 @@
from collections.abc import Generator, Sequence
from typing import Any, TypeAlias
from collections.abc import Callable, Generator, Sequence
from typing import Any, Concatenate, Final, Generic, TypeAlias
from typing_extensions import TypeVar

import numpy as np
import optype as op
import optype.numpy as onp
from scipy._typing import Untyped, UntypedCallable, UntypedTuple
from scipy.optimize._typing import Constraints
from ._vertex import VertexBase, VertexCacheBase

_Location: TypeAlias = Sequence[float]
_Bounds: TypeAlias = Sequence[tuple[float, float]]
_Constraints: TypeAlias = dict[str, object] | Sequence[dict[str, object]] # TODO: TypedDict
_Symmetry: TypeAlias = op.CanGetitem[int, op.CanIndex]
_CyclicProduct: TypeAlias = Generator[tuple[float, ...], None, tuple[float, ...]]
_Floats: TypeAlias = onp.ToFloat
_Float1D: TypeAlias = onp.Array1D[np.float64]
_FloatingND: TypeAlias = onp.ArrayND[np.floating[Any] | np.integer[Any]]

_Fun0D: TypeAlias = Callable[Concatenate[_Float1D, ...], onp.ToFloat]
_Fun1D: TypeAlias = Callable[Concatenate[_Float1D, ...], onp.ToFloat1D]

_Location: TypeAlias = _FloatingND | Sequence[float]
_Bounds: TypeAlias = _FloatingND | Sequence[tuple[onp.ToFloat, onp.ToFloat]]
_Symmetry: TypeAlias = onp.ArrayND[np.integer[Any]] | op.CanGetitem[int, op.CanIndex]

_HT = TypeVar("_HT", bound=VertexCacheBase, default=VertexCacheBase)

###

class Complex(Generic[_HT]): # undocumented
dim: Final[int]
domain: Final[_Bounds]
bounds: Final[_Bounds]
symmetry: Final[_Symmetry]
sfield: _Fun0D
sfield_args: tuple[object, ...]
min_cons: Constraints # only set if `constraints` is not None
g_cons: Final[Sequence[_Fun1D]]
g_args: Final[tuple[object, ...]]

class Complex:
dim: int
domain: _Bounds
bounds: _Bounds
symmetry: _Symmetry
sfield: UntypedCallable
sfield_args: UntypedTuple
min_cons: _Constraints # only set if `constraints` is not None
g_cons: UntypedTuple | None
g_args: UntypedTuple | None
gen: int
perm_cycle: int

H: list[Untyped]
V: VertexCacheBase
V_non_symm: list[VertexBase]
H: list[_HT] # readonly
V: Final[VertexCacheBase]
V_non_symm: Final[list[VertexBase]]
origin: list[float]
supremum: list[float]
cp: _CyclicProduct
triangulated_vectors: list[tuple[tuple[float, ...], tuple[float, ...]]]
rls: Untyped
triangulated_vectors: list[tuple[_Floats, _Floats]]

cp: Generator[_Floats, None, _Floats]
rls: Generator[VertexBase | _Floats]

def __init__(
self,
/,
dim: int,
domain: _Bounds | None = None,
sfield: UntypedCallable | None = None,
sfield_args: UntypedTuple = (),
sfield: _Fun0D | None = None,
sfield_args: tuple[object, ...] = (),
symmetry: _Symmetry | None = None,
constraints: _Constraints | None = None,
constraints: Constraints | None = None,
workers: int = 1,
) -> None: ...
def __call__(self, /) -> Untyped: ...
def __call__(self, /) -> list[_HT]: ...
def cyclic_product(
self,
/,
bounds: _Bounds,
origin: _Location,
supremum: _Location,
centroid: bool = True,
) -> _CyclicProduct: ...
centroid: onp.ToFloat = True,
) -> Generator[_Floats, None, _Floats]: ...
def triangulate(
self,
/,
n: int | None = None,
symmetry: _Symmetry | None = None,
centroid: bool = True,
printout: bool = False,
centroid: onp.ToFloat = True,
printout: onp.ToFloat = False,
) -> None: ...
def refine(self, /, n: int = 1) -> None: ...
def refine_all(self, /, centroids: bool = True) -> None: ...
def refine_all(self, /, centroids: onp.ToBool = True) -> None: ...
def refine_local_space(
self,
/,
origin: _Location,
supremum: _Location,
bounds: _Bounds,
centroid: int = 1,
) -> Generator[VertexBase | tuple[float, ...], None, None]: ...
centroid: onp.ToBool = 1,
) -> Generator[VertexBase | _Floats]: ...
def refine_star(self, /, v: VertexBase) -> None: ...
def split_edge(self, /, v1: VertexBase, v2: VertexBase) -> VertexBase: ...
def vpool(self, /, origin: _Location, supremum: _Location) -> set[VertexBase]: ...
def vf_to_vv(self, /, vertices: Sequence[VertexBase], simplices: Sequence[Untyped]) -> None: ...
def vf_to_vv(
self,
/,
vertices: Sequence[VertexBase],
simplices: Sequence[tuple[onp.ToFloat1D, onp.ToFloat1D]],
) -> None: ...
def connect_vertex_non_symm(
self,
/,
v_x: tuple[float | np.floating[Any]] | onp.Array1D[np.floating[Any]],
v_x: onp.ToFloat1D,
near: set[VertexBase] | list[VertexBase] | None = None,
) -> bool | None: ...
def in_simplex(
self,
/,
S: onp.ToFloat1D,
v_x: onp.Array1D[np.floating[Any]],
A_j0: onp.ArrayND[np.floating[Any]] | None = None,
) -> Untyped: ...
def deg_simplex(
self,
/,
S: onp.ArrayND[np.floating[Any]],
proj: onp.ArrayND[np.floating[Any]] | None = None,
) -> Untyped: ...
def in_simplex(self, /, S: onp.ToFloat1D, v_x: onp.ToFloat1D, A_j0: _FloatingND | None = None) -> bool: ...
def deg_simplex(self, /, S: _FloatingND, proj: _FloatingND | None = None) -> bool: ...
184 changes: 88 additions & 96 deletions scipy-stubs/optimize/_shgo_lib/_vertex.pyi
Original file line number Diff line number Diff line change
@@ -1,135 +1,126 @@
import abc
from collections import OrderedDict
from collections.abc import Callable, Iterable, Iterator, Sequence
from typing import Any, Final, Generic, TypeAlias
from typing_extensions import Self, TypeVar, override
from typing import Concatenate, Final, Generic, TypeAlias, type_check_only
from typing_extensions import TypeVar

import numpy as np
import optype.numpy as onp
from scipy._lib._util import MapWrapper as MapWrapper
from scipy._typing import Untyped, UntypedTuple

_SCT = TypeVar("_SCT", bound=np.number[Any], default=np.floating[Any])
_SCT_co = TypeVar("_SCT_co", bound=np.number[Any], covariant=True, default=np.floating[Any])
_VT_co = TypeVar("_VT_co", bound=VertexBase, default=VertexBase, covariant=True)

_Vector: TypeAlias = onp.Array1D[_SCT]
_VectorLike: TypeAlias = tuple[float | _SCT, ...] | _Vector[_SCT]
_Float1D: TypeAlias = onp.Array1D[np.float64]
_Fun0D: TypeAlias = Callable[Concatenate[_Float1D, ...], onp.ToFloat]
_Fun1D: TypeAlias = Callable[Concatenate[_Float1D, ...], onp.ToFloat1D]

_ScalarField: TypeAlias = Callable[[_Vector[_SCT]], float | _SCT]
_VectorField: TypeAlias = Callable[[_Vector[_SCT]], _Vector[_SCT]]
_ScalarFieldCons: TypeAlias = Callable[[_Vector[_SCT]], Untyped] # TODO
@type_check_only
class _VertexMixin:
def connect(self, /, v: VertexBase) -> None: ...
def disconnect(self, /, v: VertexBase) -> None: ...

class VertexBase(Generic[_SCT_co], metaclass=abc.ABCMeta):
x: _VectorLike[_SCT_co]
x_a: _Vector[_SCT_co] # lazy
###

class VertexBase(abc.ABC):
x: onp.ToFloat1D
x_a: _Float1D # lazy
hash: Final[int]
index: Final[int | None]
nn: set[Self]

st: set[Self] # might not be set
nn: set[VertexBase]
st: set[VertexBase] # might not be set
feasible: bool # might not be set

def __init__(self, /, x: _VectorLike[_SCT_co], nn: Iterable[Self] | None = None, index: int | None = None) -> None: ...
def __init__(self, /, x: onp.ToFloat1D, nn: Iterable[VertexBase] | None = None, index: int | None = None) -> None: ...
@abc.abstractmethod
def connect(self, /, v: Self) -> None: ...
def connect(self, /, v: VertexBase) -> None: ...
@abc.abstractmethod
def disconnect(self, /, v: Self) -> None: ...
def star(self, /) -> set[Self]: ...
def disconnect(self, /, v: VertexBase) -> None: ...
def star(self, /) -> set[VertexBase]: ...

class VertexScalarField(VertexBase[_SCT_co], Generic[_SCT_co]):
class VertexScalarField(_VertexMixin, VertexBase):
check_min: bool
check_max: bool
# TODO: Support non-empty `field_args` and `g_cons_args`

def __init__(
self,
/,
x: _VectorLike[_SCT_co],
field: _ScalarField[_SCT_co] | None = None,
nn: Iterable[Self] | None = None,
x: onp.ToFloat1D,
field: _Fun0D | None = None,
nn: Iterable[VertexBase] | None = None,
index: int | None = None,
field_args: tuple[()] = (),
g_cons: _ScalarFieldCons[_SCT_co] | None = None,
g_cons_args: tuple[()] = (),
field_args: tuple[object, ...] = (),
g_cons: _Fun1D | None = None,
g_cons_args: tuple[object, ...] = (),
) -> None: ...
@override
def connect(self, /, v: Self) -> None: ...
@override
def disconnect(self, /, v: Self) -> None: ...
#
def minimiser(self, /) -> bool: ...
def maximiser(self, /) -> bool: ...

class VertexVectorField(VertexBase[_SCT_co], Generic[_SCT_co], metaclass=abc.ABCMeta):
class VertexVectorField(_VertexMixin, VertexBase):
# NOTE: The implementaiton is a WIP
# TODO: Support non-empty `field_args`, `vfield_args`, and `g_cons_args`
def __init__(
self,
/,
x: _VectorLike[_SCT_co],
sfield: _ScalarField[_SCT_co] | None = None,
vfield: _VectorField[_SCT_co] | None = None,
field_args: tuple[()] = (),
vfield_args: tuple[()] = (),
g_cons: _ScalarFieldCons[_SCT_co] | None = None,
g_cons_args: tuple[()] = (),
nn: Iterable[Self] | None = None,
x: onp.ToFloat1D,
sfield: _Fun0D | None = None,
vfield: _Fun1D | None = None,
field_args: tuple[object, ...] = (),
vfield_args: tuple[object, ...] = (),
g_cons: _Fun1D | None = None,
g_cons_args: tuple[object, ...] = (),
nn: Iterable[VertexBase] | None = None,
index: int | None = None,
) -> None: ...
@override
def connect(self, /, v: Self) -> None: ...
@override
def disconnect(self, /, v: Self) -> None: ...

class VertexCube(VertexBase[_SCT_co], Generic[_SCT_co]):
def __init__(self, /, x: _VectorLike[_SCT_co], nn: Iterable[Self] | None = None, index: int | None = None) -> None: ...
@override
def connect(self, /, v: Self) -> None: ...
@override
def disconnect(self, /, v: Self) -> None: ...

_KT = TypeVar("_KT", default=Untyped) # TODO: Select a decent default
_VT = TypeVar("_VT", bound=VertexBase, default=VertexBase)

class VertexCacheBase(Generic[_KT, _VT]):
cache: OrderedDict[_KT, _VT]

class VertexCube(_VertexMixin, VertexBase):
def __init__(self, /, x: onp.ToFloat1D, nn: Iterable[VertexBase] | None = None, index: int | None = None) -> None: ...

class VertexCacheBase(Generic[_VT_co]):
cache: OrderedDict[onp.ToFloat1D, _VT_co]
nfev: int
index: int

def __init__(self, /) -> None: ...
def __iter__(self, /) -> Iterator[_VT]: ...
def __iter__(self, /) -> Iterator[_VT_co]: ...
def size(self, /) -> int: ...
def print_out(self, /) -> None: ...

class VertexCacheIndex(VertexCacheBase[_KT, _VT], Generic[_KT, _VT]):
Vertex: type[_VT]
def __getitem__(self, x: _KT, /, nn: None = None) -> _VT: ...
class VertexCacheIndex(VertexCacheBase[VertexCube]):
Vertex: Final[type[VertexCube]]

def __getitem__(self, x: onp.ToFloat1D, /, nn: None = None) -> VertexCube: ...

class VertexCacheField(VertexCacheBase[_KT, _VT], Generic[_KT, _VT, _SCT_co]):
class VertexCacheField(VertexCacheBase[VertexScalarField]):
Vertex: Final[type[VertexScalarField]]

field: Final[_Fun0D]
field_args: Final[tuple[object, ...]]
wfield: Final[FieldWrapper]
fpool: Final[set[VertexScalarField]]
process_fpool: Final[Callable[[], None]]

g_cons: Final[Sequence[_Fun1D]]
g_cons_args: Final[tuple[object, ...]]
wgcons: Final[ConstraintWrapper]
gpool: Final[set[VertexScalarField]]
process_gpool: Final[Callable[[], None]]

workers: Final[int]
index: int
Vertex: type[_VT]
field: _ScalarField[_SCT_co]
field_args: tuple[()]
wfield: FieldWrapper[_SCT_co]
g_cons: Sequence[_ScalarFieldCons[_SCT_co]]
g_cons_args: tuple[()]
wgcons: ConstraintWrapper[_SCT_co]
gpool: set[UntypedTuple]
fpool: set[UntypedTuple]
sfc_lock: bool
workers: int
process_gpool: Callable[[], None]
process_fpool: Callable[[], None]

def __init__(
self,
/,
field: Untyped | None = None,
field_args: tuple[()] = (),
g_cons: Sequence[_ScalarFieldCons[_SCT_co]] | None = None,
g_cons_args: tuple[()] = (),
field: _Fun0D | _Fun1D | None = None,
field_args: tuple[object, ...] = (),
g_cons: Sequence[_Fun1D] | None = None,
g_cons_args: tuple[object, ...] = (),
workers: int = 1,
) -> None: ...
def __getitem__(self, x: _KT, /, nn: Iterable[_VT] | None = None) -> _VT: ...
def __getitem__(self, x: onp.ToFloat1D, /, nn: Iterable[VertexBase] | None = None) -> VertexScalarField: ...
def process_pools(self, /) -> None: ...
def feasibility_check(self, /, v: _VT) -> bool: ...
def compute_sfield(self, /, v: _VT) -> None: ...
def feasibility_check(self, /, v: VertexBase) -> bool: ...
def compute_sfield(self, /, v: VertexBase) -> None: ...
def proc_gpool(self, /) -> None: ...
def pproc_gpool(self, /) -> None: ...
def proc_fpool_g(self, /) -> None: ...
Expand All @@ -138,15 +129,16 @@ class VertexCacheField(VertexCacheBase[_KT, _VT], Generic[_KT, _VT, _SCT_co]):
def pproc_fpool_nog(self, /) -> None: ...
def proc_minimisers(self, /) -> None: ...

class ConstraintWrapper(Generic[_SCT]):
g_cons: Sequence[_ScalarFieldCons[_SCT]]
g_cons_args: Sequence[UntypedTuple]
def __init__(self, /, g_cons: Sequence[_ScalarFieldCons[_SCT]], g_cons_args: Sequence[UntypedTuple]) -> None: ...
def gcons(self, /, v_x_a: _Vector[_SCT]) -> bool: ...

class FieldWrapper(Generic[_SCT]):
# TODO: Support non-empty `g_cons_args`
field: _ScalarField[_SCT] | _VectorField[_SCT]
field_args: tuple[()]
def __init__(self, /, field: _ScalarField[_SCT] | _VectorField[_SCT], field_args: tuple[()]) -> None: ...
def func(self, /, v_x_a: _Vector[_SCT]) -> _SCT: ...
class ConstraintWrapper:
g_cons: Sequence[_Fun1D]
g_cons_args: Sequence[tuple[object, ...]]

def __init__(self, /, g_cons: Sequence[_Fun1D], g_cons_args: Sequence[tuple[object, ...]]) -> None: ...
def gcons(self, /, v_x_a: _Float1D) -> bool: ...

class FieldWrapper:
field: _Fun0D | _Fun1D
field_args: tuple[object, ...]

def __init__(self, /, field: _Fun0D | _Fun1D, field_args: tuple[object, ...]) -> None: ...
def func(self, /, v_x_a: _Float1D) -> onp.ToFloat | onp.ToFloat1D: ...

0 comments on commit 3d9756c

Please sign in to comment.