Skip to content

quast_decisiontree.algorithms.classical.scipy_optimizers

quast_decisiontree.algorithms.classical.scipy_optimizers

Scipy-native optimizers for variational algorithms.

These replace the qiskit_algorithms.optimizers dependency with a thin wrapper around scipy.optimize.minimize, exposing the same .minimize(fun, x0) -> result.x interface expected by HybridAlgorithm and the OptimizerBuilder system.

ScipyOptimizer

Thin wrapper around scipy.optimize.minimize.

Provides the .minimize(fun, x0, bounds=None) interface expected by VariationalAlgorithm and QrispQAOA.

Parameters:

Name Type Description Default
method str

Scipy method name (e.g. 'COBYLA', 'Powell', 'Nelder-Mead').

required
options dict[str, Any] | None

Dict of options passed to scipy.optimize.minimize.

None
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class ScipyOptimizer:
    """Thin wrapper around scipy.optimize.minimize.

    Provides the .minimize(fun, x0, bounds=None) interface expected by
    VariationalAlgorithm and QrispQAOA.

    Args:
        method: Scipy method name (e.g. 'COBYLA', 'Powell', 'Nelder-Mead').
        options: Dict of options passed to scipy.optimize.minimize.
    """

    def __init__(self, method: str, options: dict[str, Any] | None = None) -> None:
        self.method = method
        self.options = options or {}

    def minimize(
        self,
        fun: Callable,
        x0: np.ndarray,
        jac: Callable | None = None,
        bounds: Any | None = None,
    ) -> OptimizeResult:
        """Minimize a scalar function.

        Args:
            fun: Objective function f(x) -> float.
            x0: Initial parameter vector.
            jac: Optional gradient function.
            bounds: Optional parameter bounds.

        Returns:
            scipy.optimize.OptimizeResult with .x, .fun, .nfev, etc.
        """
        return minimize(
            fun=fun,
            x0=x0,
            method=self.method,
            jac=jac,
            bounds=bounds,
            options=self.options,
        )

    def __repr__(self) -> str:
        return f"ScipyOptimizer(method={self.method!r}, options={self.options})"

method instance-attribute

method = method

options instance-attribute

options = options or {}

__init__

__init__(method, options=None)
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
34
35
36
def __init__(self, method: str, options: dict[str, Any] | None = None) -> None:
    self.method = method
    self.options = options or {}

minimize

minimize(fun, x0, jac=None, bounds=None)

Minimize a scalar function.

Parameters:

Name Type Description Default
fun Callable

Objective function f(x) -> float.

required
x0 ndarray

Initial parameter vector.

required
jac Callable | None

Optional gradient function.

None
bounds Any | None

Optional parameter bounds.

None

Returns:

Type Description
OptimizeResult

scipy.optimize.OptimizeResult with .x, .fun, .nfev, etc.

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def minimize(
    self,
    fun: Callable,
    x0: np.ndarray,
    jac: Callable | None = None,
    bounds: Any | None = None,
) -> OptimizeResult:
    """Minimize a scalar function.

    Args:
        fun: Objective function f(x) -> float.
        x0: Initial parameter vector.
        jac: Optional gradient function.
        bounds: Optional parameter bounds.

    Returns:
        scipy.optimize.OptimizeResult with .x, .fun, .nfev, etc.
    """
    return minimize(
        fun=fun,
        x0=x0,
        method=self.method,
        jac=jac,
        bounds=bounds,
        options=self.options,
    )

__repr__

__repr__()
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
65
66
def __repr__(self) -> str:
    return f"ScipyOptimizer(method={self.method!r}, options={self.options})"

CobylaScipy

Bases: ScipyOptimizer

COBYLA optimizer.

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
69
70
71
72
73
class CobylaScipy(ScipyOptimizer):
    """COBYLA optimizer."""

    def __init__(self, maxiter: int = 128) -> None:
        super().__init__(method="COBYLA", options={"maxiter": maxiter})

__init__

__init__(maxiter=128)
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
72
73
def __init__(self, maxiter: int = 128) -> None:
    super().__init__(method="COBYLA", options={"maxiter": maxiter})

PowellScipy

Bases: ScipyOptimizer

Powell optimizer.

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
76
77
78
79
80
class PowellScipy(ScipyOptimizer):
    """Powell optimizer."""

    def __init__(self, maxfev: int = 1024) -> None:
        super().__init__(method="Powell", options={"maxfev": maxfev})

__init__

__init__(maxfev=1024)
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
79
80
def __init__(self, maxfev: int = 1024) -> None:
    super().__init__(method="Powell", options={"maxfev": maxfev})

NelderMeadScipy

Bases: ScipyOptimizer

Nelder-Mead (simplex) optimizer.

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
83
84
85
86
87
class NelderMeadScipy(ScipyOptimizer):
    """Nelder-Mead (simplex) optimizer."""

    def __init__(self, maxfev: int = 1024) -> None:
        super().__init__(method="Nelder-Mead", options={"maxfev": maxfev})

__init__

__init__(maxfev=1024)
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
86
87
def __init__(self, maxfev: int = 1024) -> None:
    super().__init__(method="Nelder-Mead", options={"maxfev": maxfev})

LBFGSBScipy

Bases: ScipyOptimizer

L-BFGS-B optimizer (gradient-based, supports bounds).

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
90
91
92
93
94
class LBFGSBScipy(ScipyOptimizer):
    """L-BFGS-B optimizer (gradient-based, supports bounds)."""

    def __init__(self, maxiter: int = 128) -> None:
        super().__init__(method="L-BFGS-B", options={"maxiter": maxiter})

__init__

__init__(maxiter=128)
Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
93
94
def __init__(self, maxiter: int = 128) -> None:
    super().__init__(method="L-BFGS-B", options={"maxiter": maxiter})

adapt_optimizer

adapt_optimizer(optimizer)

Adapt an optimizer to the scipy custom minimizer interface.

Handles
  • None or str: returned as-is (scipy method name).
  • ScipyOptimizer: wrapped to match fun(x) signature.
  • Object with .minimize(fun, x0): wrapped to return OptimizeResult.

Returns:

Type Description

A scipy-compatible optimizer (str, callable, or None).

Source code in src/quast_decisiontree/algorithms/classical/scipy_optimizers.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def adapt_optimizer(optimizer):
    """Adapt an optimizer to the scipy custom minimizer interface.

    Handles:
        - None or str: returned as-is (scipy method name).
        - ScipyOptimizer: wrapped to match fun(x) signature.
        - Object with .minimize(fun, x0): wrapped to return OptimizeResult.

    Returns:
        A scipy-compatible optimizer (str, callable, or None).
    """
    if optimizer is None or isinstance(optimizer, str):
        return optimizer

    if isinstance(optimizer, ScipyOptimizer):

        def _scipy_native_minimizer(fun, x0, args=(), **options):
            if args:

                def wrapped_fun(x):
                    return fun(x, *args)

            else:
                wrapped_fun = fun
            return optimizer.minimize(wrapped_fun, x0)

        return _scipy_native_minimizer

    if hasattr(optimizer, "minimize") and callable(optimizer.minimize):

        def _custom_minimizer(fun, x0, args=(), **options):
            from scipy.optimize import OptimizeResult

            if args:

                def wrapped_fun(x):
                    return fun(x, *args)

            else:
                wrapped_fun = fun

            import numpy as np

            opt_result = optimizer.minimize(wrapped_fun, x0)
            if isinstance(opt_result, OptimizeResult):
                return opt_result
            if hasattr(opt_result, "x"):
                return OptimizeResult(
                    x=np.asarray(opt_result.x),
                    fun=(
                        opt_result.fun if hasattr(opt_result, "fun") else wrapped_fun(opt_result.x)
                    ),
                    success=True,
                    nfev=getattr(opt_result, "nfev", 0),
                )
            x = np.asarray(opt_result)
            return OptimizeResult(x=x, fun=wrapped_fun(x), success=True)

        return _custom_minimizer

    return optimizer