3.6.4. Adaptive Rate MC¶
-
class
ARMCOptimizer
(phi: float = 1.0, gamma: float = 2.0, a_target: float = 0.25, super_iter_len: int = 1000, sub_iter_len: int = 100, move_range: Union[float, Sequence[float]] = array([0.9 , 0.905, 0.91 , 0.915, 0.92 , 0.925, 0.93 , 0.935, 0.94 , 0.945, 0.95 , 0.955, 0.96 , 0.965, 0.97 , 0.975, 0.98 , 0.985, 0.99 , 0.995, 1.005, 1.01 , 1.015, 1.02 , 1.025, 1.03 , 1.035, 1.04 , 1.045, 1.05 , 1.055, 1.06 , 1.065, 1.07 , 1.075, 1.08 , 1.085, 1.09 , 1.095, 1.1 ]), move_func: Callable[[float, float], float] = <ufunc 'multiply'>)¶ An optimzer using the Addaptive Rate Monte Carlo (ARMC) algorithm.
- A trial state, \(S_{\omega}\), is generated by moving a random parameter retrieved from a user-specified parameter set (e.g. atomic charge). By default, parameters moves are applied in a multiplicative manner.
- The move is accepted if the new set of parameters, \(S_{\omega}\), lowers the auxiliary error (\(\Delta \varepsilon_{QM-MM}\)) with respect to the previous set of accepted parameters \(S_{\omega-i}\) (\(i > 0\); see (3.2)). The auxiliary error is calculated with a user-specified cost function.
(3.2)¶\[p(\omega \leftarrow \omega-i) = \Biggl \lbrace { 1, \quad \Delta \varepsilon_{QM-MM} ( S_{\omega} ) \; \lt \; \Delta \varepsilon_{QM-MM} ( S_{\omega-i} ) \atop 0, \quad \Delta \varepsilon_{QM-MM} ( S_{\omega} ) \; \gt \; \Delta \varepsilon_{QM-MM} ( S_{\omega-i} ) }\]- The parameter history is updated. Either \(S_{\omega}\) or \(S_{\omega-i}\) is increased by the variable \(\phi\) (see (3.3)) if, respectivelly, the new parameters are accepted or rejected. In this manner the underlying PES is continuously modified, preventing the optimizer from getting permanently stuck in a (local) parameter space minima.
(3.3)¶\[\Delta \varepsilon_{QM-MM} ( S_{\omega} ) + \phi \quad \text{if} \quad \Delta \varepsilon_{QM-MM} ( S_{\omega} ) \; \lt \; \Delta \varepsilon_{QM-MM} ( S_{\omega-i} ) \atop \Delta \varepsilon_{QM-MM} ( S_{\omega-i} ) + \phi \quad \text{if} \quad \Delta \varepsilon_{QM-MM} ( S_{\omega} ) \; \gt \; \Delta \varepsilon_{QM-MM} ( S_{\omega-i} )\]- The parameter \(\phi\) is updated at regular intervals in order to maintain a constant acceptance rate \(\alpha_{t}\). This is illustrated in (3.4), where \(\phi\) is updated the begining of every super-iteration \(\kappa\). In this example the total number of iterations, \(\kappa \omega\), is divided into \(\kappa\) super- and \(\omega\) sub-iterations.
(3.4)¶\[\phi_{\kappa \omega} = \phi_{ ( \kappa - 1 ) \omega} * \gamma^{ \text{sgn} ( \alpha_{t} - \overline{\alpha}_{ ( \kappa - 1 ) }) } \quad \kappa = 1, 2, 3, ..., N\]Attributes:
- phi : float
- The variable \(\phi\).
- gamma : float
- The constant \(\gamma\).
- a_target : float
- The target acceptance rate \(\alpha_{t}\).
- super_iter : range
- A range object with the total number of each super-iterations \(\kappa\). Total number of iterations: \(\kappa \omega\).
- sub_iter : range
- A range object with the the length of each ARMC sub-iteration \(\omega\). Total number of iterations: \(\kappa \omega\).
- move_range : numpy.ndarray[float]
- An array-like object containing all allowed move sizes.
- move_func : Callable[[float, float], float]
- A callable for performing the moves. The callable should take 2 floats (i.e. a single value from the parameter set S_{omega-i} and the move size) and return 1 float (i.e. an updated value for the parameter set S_{omega}).
- run : Callable
- The (bound)
ParameterOptimization.run()
method. See the function parameter inARMCOptimizer.minimize()
. - bounds : numpy.ndarray or (None, None)
- An 2D array (or 2-tuple filled with
None
) denoting minimum and maximum values for each to-be moved parameter. See the bounds parameter inARMCOptimizer.minimize()
. - x_best : numpy.ndarray[float]
- The parameter set which minimizes the user-specified error function.
- fx_best : float
- The error associated with
ARMCOptimizer.x_best
. - fx_old : float
- The error of the last set of accepted parameters.
See Also:
- Paper
- The paper describing the original ARMC implementation: Salvatore Cosseddu et al, J. Chem. Theory Comput., 2017, 13, 297–308 10.1021/acs.jctc.6b01089.
- Code
- The Python-based implementation of ARMC this class is based on: Automated Forcefield Optimization Extension github.com/nlesc-nano/auto-FOX.
-
__init__
(phi: float = 1.0, gamma: float = 2.0, a_target: float = 0.25, super_iter_len: int = 1000, sub_iter_len: int = 100, move_range: Union[float, Sequence[float]] = array([0.9 , 0.905, 0.91 , 0.915, 0.92 , 0.925, 0.93 , 0.935, 0.94 , 0.945, 0.95 , 0.955, 0.96 , 0.965, 0.97 , 0.975, 0.98 , 0.985, 0.99 , 0.995, 1.005, 1.01 , 1.015, 1.02 , 1.025, 1.03 , 1.035, 1.04 , 1.045, 1.05 , 1.055, 1.06 , 1.065, 1.07 , 1.075, 1.08 , 1.085, 1.09 , 1.095, 1.1 ]), move_func: Callable[[float, float], float] = <ufunc 'multiply'>) → None¶ Initialize a
ARMCOptimizer
instance.Parameters:
- phi : float
- The variable \(\phi\).
- gamma : float
- The constant \(\gamma\).
- a_target : float
- The target acceptance rate \(\alpha_{t}\).
- super_iter_len : int
- The total number of each super-iterations \(\kappa\). Total number of iterations: \(\kappa \omega\).
- sub_iter_len : int
- The length of each ARMC sub-iteration \(\omega\). Total number of iterations: \(\kappa \omega\).
- move_range : array-like[float]
- An array-like object containing all allowed move sizes.
- move_func : Callable[[float, float], float]
- A callable for performing the moves. The callable should take 2 floats (i.e. a single value from the parameter set S_{omega-i} and the move size) and return 1 float (i.e. an updated value for the parameter set S_{omega}).
-
bounds
¶ Get or set the bounds parameter of
ARMCOptimizer.minimize()
.
-
minimize
(function: Callable, x0: Union[float, Sequence[float]], bounds: Optional[Sequence[Tuple[float, float]]] = None, workers: int = 1) → scm.params.optimizers.base.MinimizeResult¶ Start the minimization process.
Parameters:
- function : Callable
- The (bound)
ParameterOptimization.run()
method. - x0 : array-like[float]
- A 1D array-like object representing the set of to-be optimized parameters \(S\).
- bounds : array-like[float], optional
- An (optional) 2D array-like object denoting minimum and maximum values for each to-be moved parameter. The sequence should be of the same length as x0.
- callbacks : Callable, optional
- A callable which allows for
Optimization
specific callbacks such as early stopping.
-
_inner
(x0_old: numpy.ndarray, omega: int, acceptance: numpy.ndarray) → numpy.ndarray¶ Run the inner loop of
ARMCOptimizer.minimize()
.Parameters:
- x0_old : numpy.ndarray[float]
- The last set of accepted parameters \(S_{\omega-i}\).
- omega : int
- The ARMC sub-iteration \(\omega\).
- acceptance : numpy.ndarray[bool]
- A boolean array for keeping track of accepted moves during the current sub-iteration.
Returns:
- numpy.ndarray[float]:
- The accepted parameters \(S_{\omega}\) or \(S_{\omega-i}\). Equivalent to x0_old if the new parameter set is not accepted.
-
static
callstop
(reason: Any = None)¶ Signal to terminate the
minimize()
loop while still returningMinimizeResult
.
-
move
(x0: numpy.ndarray, x0_min: Optional[numpy.ndarray] = None, x0_max: Optional[numpy.ndarray] = None) → numpy.ndarray¶ Create a copy of x0 and apply a random move to it.
The move will be applied with
ARMCOptimizer.move_func
(multiplication by default) using a random value fromARMCOptimizer.move_range
.Parameters:
- x0 : numpy.ndarray[float]
- A 1D array of parameters \(S_{\omega-i}\).
- value_min : numpy.ndarray[float], optional
- A 1D array minimum values for each to-be moved parameter. The array should be of the same length as x0.
- value_max : numpy.ndarray[float], optional
- A 1D array maximum values for each to-be moved parameter. The array should be of the same length as x0.
Returns:
- numpy.ndarray[float]
- A copy of x0 \(S_{\omega}\). A single value is moved within this parameter set.
-
phi_apply
(aux_err: float) → float¶ Apply
ARMCOptimizer.phi
to the supplied auxiliary error: \(\Delta \varepsilon_{QM-MM} + \phi\).
-
phi_update
(acceptance: numpy.ndarray) → None¶ Update the variable \(\phi\) (
ARMCOptimizer.phi
).\(\phi\) is updated based on the target accepatance rate, \(\alpha_{t}\) (
ARMCOptimizer.a_target
), and the acceptance rate, acceptance, of the current super-iteration:\[\phi_{\kappa \omega} = \phi_{ ( \kappa - 1 ) \omega} * \gamma^{ \text{sgn} ( \alpha_{t} - \overline{\alpha}_{ ( \kappa - 1 ) }) }\]Parameters:
- acceptance : numpy.ndarray[bool]
- A boolean array for keeping track of accepted moves over the course of the current sub-iteration of \(\kappa\).
The Adaptive Rate MC optimizer was contributed by Bas van Beek.