Source code for fides.constants

"""
Constants
-----------
This module provides a central place to define native python enums and
constants that are used in multiple other modules
"""

import enum
from numbers import Integral, Real
from pathlib import PosixPath, WindowsPath
from typing import Dict

import numpy as np


[docs]class Options(str, enum.Enum): """ Defines all the fields that can be specified in Options to :py:class:`Optimizer` """ MAXITER = 'maxiter' #: maximum number of allowed iterations MAXTIME = 'maxtime' #: maximum amount of walltime in seconds FATOL = 'fatol' #: absolute tolerance for convergence based on fval FRTOL = 'frtol' #: relative tolerance for convergence based on fval XTOL = 'xtol' #: tolerance for convergence based on x GATOL = 'gatol' #: absolute tolerance for convergence based on grad GRTOL = 'grtol' #: relative tolerance for convergence based on grad SUBSPACE_DIM = 'subspace_solver' #: trust region subproblem subspace STEPBACK_STRAT = 'stepback_strategy' #: method to use for stepback THETA_MAX = 'theta_max' #: maximal fraction of step that would hit bounds DELTA_INIT = 'delta_init' #: initial trust region radius MU = 'mu' #: acceptance threshold for trust region ratio ETA = 'eta' #: trust region increase threshold for trust region ratio GAMMA1 = 'gamma1' #: factor by which trust region radius will be decreased GAMMA2 = 'gamma2' #: factor by which trust region radius will be increased HISTORY_FILE = 'history_file' #: when set, statistics for each start will
# be saved to the specified file
[docs]class SubSpaceDim(str, enum.Enum): r""" Defines the possible choices of subspace dimension in which the subproblem will be solved. """ TWO = '2D' #: Two dimensional Newton/Gradient subspace FULL = 'full' #: Full :math:`\mathbb{R}^n` STEIHAUG = 'scg' #: CG subspace via Steihaug's method
[docs]class StepBackStrategy(str, enum.Enum): """ Defines the possible choices of search refinement if proposed step reaches optimization boundary """ SINGLE_REFLECT = 'reflect_single' #: single reflection at boundary REFLECT = 'reflect' #: recursive reflections at boundary TRUNCATE = 'truncate' #: truncate step at boundary and re-solve # restricted subproblem MIXED = 'mixed' #: mix reflections and truncations REFINE = 'refine' #: perform optimization to refine step
DEFAULT_OPTIONS = { Options.MAXITER: 1e3, Options.MAXTIME: np.inf, Options.FATOL: 1e-8, Options.FRTOL: 1e-8, Options.XTOL: 0, Options.GATOL: 1e-6, Options.GRTOL: 0, Options.SUBSPACE_DIM: SubSpaceDim.TWO, Options.STEPBACK_STRAT: StepBackStrategy.REFLECT, Options.THETA_MAX: 0.95, Options.DELTA_INIT: 1.0, Options.MU: 0.25, # [NodedalWright2006] Options.ETA: 0.75, # [NodedalWright2006] Options.GAMMA1: 1 / 4, # [NodedalWright2006] Options.GAMMA2: 2, # [NodedalWright2006] Options.HISTORY_FILE: None, }
[docs]class ExitFlag(int, enum.Enum): """ Defines possible exitflag values for the optimizer to indicate why optimization exited. Negative value indicate errors while positive values indicate convergence. """ DID_NOT_RUN = 0 #: Optimizer did not run MAXITER = -1 #: Reached maximum number of allowed iterations MAXTIME = -2 #: Expected to reach maximum allowed time in next iteration NOT_FINITE = -3 #: Encountered non-finite fval/grad/hess EXCEEDED_BOUNDARY = -4 #: Exceeded specified boundaries DELTA_TOO_SMALL = -5 #: Trust Region Radius too small to proceed FTOL = 1 #: Converged according to fval difference XTOL = 2 #: Converged according to x difference GTOL = 3 #: Converged according to gradient norm
[docs]def validate_options(options: Dict): """Check if the chosen options are valid""" expected_types = { Options.MAXITER: Integral, Options.MAXTIME: Real, Options.FATOL: Real, Options.FRTOL: Real, Options.XTOL: Real, Options.GATOL: Real, Options.GRTOL: Real, Options.SUBSPACE_DIM: (SubSpaceDim, str), Options.STEPBACK_STRAT: (StepBackStrategy, str), Options.THETA_MAX: Real, Options.DELTA_INIT: Real, Options.MU: Real, Options.ETA: Real, Options.GAMMA1: Real, Options.GAMMA2: Real, Options.HISTORY_FILE: (str, PosixPath, WindowsPath), } for option_key, option_value in options.items(): try: option = Options(option_key) except ValueError: raise ValueError(f'{option_key} is not a valid options field.') if option_key is Options.SUBSPACE_DIM: option_value = SubSpaceDim(option_value) if option_key is Options.STEPBACK_STRAT: option_value = StepBackStrategy(option_value) expected_type = expected_types[option] if not isinstance(option_value, expected_type): if expected_type == Integral and int(option_value) == option_value: continue raise TypeError( f'Type mismatch for option {option_key}. ' f'Expected {expected_type} but got ' f'{type(option_value)}' )