Optimization Examples#

This page collects example scripts and notebooks demonstrating the optimization routines available in PyOED. All optimizers are accessible from pyoed.optimization; see that page for the full API reference.

SciPy-based Optimization#

ScipyOptimizer wraps scipy.optimize.minimize() for continuous design problems. It is the default optimizer for relaxed (continuous) sensor-placement OED.

Basic usage:

from pyoed.optimization import ScipyOptimizer

optimizer = ScipyOptimizer(configs=dict(
    method='L-BFGS-B',
    bounds=(0.0, 1.0),   # broadcast to each design dimension
    tol=1e-6,
))

Usage with an OED problem:

from pyoed.oed.sensor_placement import SensorPlacementBayesianInversionOED

oed = SensorPlacementBayesianInversionOED(configs=dict(
    inverse_problem=da,          # previously configured inverse problem
    problem_is_linear=True,
    optimizer='ScipyOptimizer',
    optimizer_configs=dict(method='L-BFGS-B', bounds=(0.0, 1.0)),
))
oed.register_optimality_criterion('Bayesian A-opt')
results = oed.solve()
print("Optimal design :", oed.design)
print("Criterion value:", results.fun)

See also the Quick Start for a complete end-to-end example using ScipyOptimizer.

Binary / Discrete Optimization#

Binary optimizers find a design in \(\{0,1\}^n\) (sensor on/off) without continuous relaxation.

Greedy optimizer — adds sensors one at a time, selecting the most informative at each step:

from pyoed.optimization.binary_optimization import GreedyBinaryOptimizer

optimizer = GreedyBinaryOptimizer(configs=dict(
    num_sensors=4,    # select exactly 4 out of n candidates
))

REINFORCE-based stochastic binary optimizer — uses the REINFORCE policy-gradient algorithm with a Bernoulli policy over the design space:

from pyoed.optimization.binary_optimization import BinaryReinforceOptimizer

optimizer = BinaryReinforceOptimizer(configs=dict(
    num_sensors=4,
    n_episodes=200,
    learning_rate=0.01,
))

Constrained stochastic optimizer — enforces a cardinality constraint (exactly k sensors) during the policy gradient update:

from pyoed.optimization.binary_optimization import ConstrainedBinaryReinforceOptimizer

optimizer = ConstrainedBinaryReinforceOptimizer(configs=dict(
    num_sensors=4,
    n_episodes=500,
))

Jupyter notebook tutorials for binary and stochastic binary optimization are available in Examples & Tutorials.

Policy Gradient (REINFORCE)#

ReinforceOptimizer is the general-purpose REINFORCE optimizer. It treats any parameterized policy (see Policy) as a probability distribution over the design space and optimizes the policy parameters by estimating the gradient via Monte Carlo rollouts.

Basic usage:

from pyoed.optimization import ReinforceOptimizer

optimizer = ReinforceOptimizer(configs=dict(
    n_episodes=300,
    learning_rate=5e-3,
    random_seed=42,
))

Use with a custom policy:

from pyoed.ml.reinforcement_learning import BernoulliPolicy

policy = BernoulliPolicy(configs=dict(n=8))   # 8-dimensional design space
optimizer = ReinforceOptimizer(configs=dict(
    policy=policy,
    n_episodes=300,
))

The REINFORCE approach is particularly useful when the gradient of the criterion w.r.t. the design is unavailable or expensive to compute. See pyoed.ml.reinforcement_learning for the full list of built-in policies and pyoed.optimization.binary_optimization for binary specializations.