simopt.solvers.astrodf
ASTRO-DF Solver.
The ASTRO-DF solver progressively builds local models (quadratic with diagonal Hessian) using interpolation on a set of points on the coordinate bases of the best (incumbent) solution. Solving the local models within a trust region (closed ball around the incumbent solution) at each iteration suggests a candidate solution for the next iteration. If the candidate solution is worse than the best interpolation point, it is replaced with the latter (a.k.a. direct search). The solver then decides whether to accept the candidate solution and expand the trust-region or reject it and shrink the trust-region based on a success ratio test. The sample size at each visited point is determined adaptively and based on closeness to optimality. A detailed description of the solver can be found here.
This version does not require a delta_max, instead it estimates the maximum step size using get_random_solution(). Parameter tuning on delta_max is therefore not needed and removed from this version as well. - Delta_max is so longer a factor, instead the maximum step size is estimated using get_random_solution(). - Parameter tuning on delta_max is therefore not needed and removed from this version as well. - No upper bound on sample size may be better - testing - It seems for SAN we always use pattern search - why? because the problem is convex and model may be misleading at the beginning - Added sufficient reduction for the pattern search
Module Contents
- class simopt.solvers.astrodf.ASTRODFConfig
Bases:
simopt.base.SolverConfigConfiguration for ASTRO-DF solver.
- eta_1: Annotated[float, Field(default=0.1, gt=0, description='threshold for a successful iteration')]
- eta_2: Annotated[float, Field(default=0.8, description='threshold for a very successful iteration')]
- gamma_1: Annotated[float, Field(default=2.5, gt=1, description='trust-region radius increase rate after successful iteration')]
- gamma_2: Annotated[float, Field(default=0.5, gt=0, lt=1, description='trust-region radius decrease rate after failed iteration')]
- lambda_min: Annotated[int, Field(default=5, gt=2, description='minimum sample size')]
- easy_solve: Annotated[bool, Field(default=True, description='solve the subproblem approximately with Cauchy point')]
- reuse_points: Annotated[bool, Field(default=True, description='reuse the previously visited points')]
- ps_sufficient_reduction: Annotated[float, Field(default=0.1, ge=0, description='use pattern search if with sufficient reduction, 0 always allows it, large value never does')]
- use_gradients: Annotated[bool, Field(default=True, description='if direct gradient observations are available, use them')]
- class simopt.solvers.astrodf.ASTRODF(name: str = '', fixed_factors: dict | None = None)
Bases:
simopt.base.SolverThe ASTRO-DF solver.
Initialize a solver object.
- Parameters:
name (str, optional) – Name of the solver. Defaults to an empty string.
fixed_factors (dict | None, optional) – Dictionary of user-specified solver factors. Defaults to None.
- name: str = 'ASTRODF'
- config_class: ClassVar[type[simopt.base.SolverConfig]]
Configuration class for the solver.
- class_name_abbr: ClassVar[str] = 'ASTRODF'
Short name of the solver class.
- class_name: ClassVar[str] = 'ASTRO-DF'
Long name of the solver class.
- objective_type: ClassVar[simopt.base.ObjectiveType]
Description of objective types.
- constraint_type: ClassVar[simopt.base.ConstraintType]
Description of constraint types.
- variable_type: ClassVar[simopt.base.VariableType]
Description of variable types.
- gradient_needed: ClassVar[bool] = False
True if gradient of objective function is needed, otherwise False.
- property iteration_count: int
Get the current iteration count.
- property delta_k: float
Get the current delta_k value.
- property delta_max: float
Get the current delta_max value.
- property incumbent_x: tuple[float, Ellipsis]
Get the incumbent solution.
- property incumbent_solution: simopt.base.Solution
Get the incumbent solution.
- property h_k: numpy.ndarray
Get the Hessian approximation.
- get_coordinate_vector(size: int, v_no: int) numpy.ndarray
Generate the coordinate vector corresponding to the variable number v_no.
- get_rotated_basis(first_basis: numpy.ndarray, rotate_index: numpy.ndarray) numpy.ndarray
Generate the basis (rotated coordinate).
The first vector comes from the visited design points (origin basis)
- evaluate_model(x_k: numpy.ndarray, q: numpy.ndarray) float
Evaluate a local quadratic model using linear interpolation and a diagonal Hessian.
- Parameters:
x_k (np.ndarray) – The point at which to evaluate the model (decision variables).
q (np.ndarray) – Coefficient vector defining the local quadratic model.
- Returns:
The evaluated model value as a NumPy array.
- Return type:
np.ndarray
- get_stopping_time(pilot_run: int, sig2: float, delta: float, kappa: float) int
Compute the sample size using adaptive stopping based on the optimality gap.
- Parameters:
pilot_run (int) – Number of initial samples used in the pilot run.
sig2 (float) – Estimated variance of the solution.
delta (float) – Optimality gap threshold.
kappa (float) – Constant in the stopping time denominator. If 0, it defaults to 1.
- Returns:
The computed sample size, rounded up to the nearest integer.
- Return type:
int
- select_interpolation_points(delta_k: float, f_index: int) tuple[list, list]
Select interpolation points for the local model.
- Parameters:
delta_k (float) – The current trust-region radius.
f_index (int) – The index of the farthest design point.
- Returns:
- A tuple containing:
var_y (list): The interpolation points.
var_z (list): The reused design point.
- Return type:
tuple[list, list]
- perform_adaptive_sampling(solution: simopt.base.Solution, pilot_run: int, delta_k: float, compute_kappa: bool = False) None
Perform adaptive sampling on a solution until the stopping condition is met.
- Parameters:
solution (Solution) – The solution object being sampled.
pilot_run (int) – The number of initial pilot runs.
delta_k (float) – The current trust-region radius.
compute_kappa (bool) – Whether or not to compute kappa dynamically (needed in the first iteration).
- construct_model() tuple[list[float], list, numpy.ndarray, numpy.ndarray, numpy.ndarray, list[simopt.base.Solution]]
Construct the local model for the current iteration.
Construct the “qualified” local model for each iteration k with the center point x_k reconstruct with new points in a shrunk trust-region if the model fails the criticality condition the criticality condition keeps the model gradient norm and the trust-region size in lock-step
- get_model_coefficients(y_var: list, fval: list, problem: simopt.base.Problem) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
Compute model coefficients using 2d+1 design points and function values.
This method fits a quadratic model with a diagonal Hessian by evaluating 2 * dim + 1 points centered at the solution.
- Parameters:
y_var (list) – List of sampled decision vectors (design points).
fval (list) – Corresponding function values for each design point.
problem (Problem) – Problem instance providing dimension and structure.
- Returns:
- A tuple containing:
q (np.ndarray): Coefficients of the fitted local quadratic model.
y_mean (np.ndarray): Mean of the y_var design points.
fval_mean (np.ndarray): Mean of the function values.
- Return type:
tuple[np.ndarray, np.ndarray, np.ndarray]
- get_coordinate_basis_interpolation_points(x_k: tuple[int | float, Ellipsis], delta: float, problem: simopt.base.Problem) list[list[list[int | float]]]
Compute the interpolation points (2d+1) using the coordinate basis.
- get_rotated_basis_interpolation_points(x_k: numpy.ndarray, delta: float, problem: simopt.base.Problem, rotate_matrix: numpy.ndarray, reused_x: numpy.ndarray) list[list[numpy.ndarray]]
Compute the interpolation points (2d+1) using the rotated coordinate basis.
One design point is reused, which is the farthest point from the center point.
- update_hessian(candidate_solution: simopt.base.Solution, grad: numpy.ndarray, s: numpy.ndarray) None
Performs Hessian update if gradients are enabled.
- iterate() None
Run one iteration of the ASTRO-DF algorithm.
Build and solve a local model, update the current incumbent and trust-region radius, and save the data
- solve(problem: simopt.base.Problem) None
Run a single macroreplication of a solver on a problem.
- Parameters:
problem (Problem) – Simulation-optimization problem to solve.
- Returns:
list [Solution]: List of solutions recommended throughout the budget.
- list [int]: List of intermediate budgets when recommended solutions
change.
- Return type:
tuple
- simopt.solvers.astrodf.clamp_with_epsilon(val: float, lower_bound: float, upper_bound: float, epsilon: float = 0.01) float
Clamp a value within bounds while avoiding exact boundary values.
Adds a small epsilon to the lower bound or subtracts it from the upper bound if val lies outside the specified range.
- Parameters:
val (float) – The value to clamp.
lower_bound (float) – Minimum acceptable value.
upper_bound (float) – Maximum acceptable value.
epsilon (float, optional) – Small margin to avoid returning exact boundary values. Defaults to 0.01.
- Returns:
The adjusted value, guaranteed to lie strictly within the bounds.
- Return type:
float