Source code for pycif.plugins.minimizers.m1qn3.check

import numpy as np

from logging import info


[docs] def check_options(self, chi, finit, **kwargs): """Validate M1QN3 parameters and initialise the working zone. Reads convergence parameters from the plugin instance (falling back to ``maxiter`` when ``niter``/``nsim`` are absent), validates their ranges, detects warm vs cold start from the ``mode`` flag, and writes the resolved values back to ``self`` so that ``m1qn3`` can read them. Args: self (Plugin): M1QN3 minimizer plugin instance. The following attributes are read (with defaults where noted): * ``niter`` / ``nsim`` — explicit iteration/simulation limits; if absent, both are derived from ``maxiter``. * ``nupdates`` (int, default 5) — number of L-BFGS memory pairs. * ``dxmin`` (float, default 1e-20) — absolute precision on *x*. * ``epsg`` (float, default 1e-20) — relative precision on the gradient. * ``mode`` (int, default 0) — scaling and restart mode. * ``df1`` (float, default 0.01) — expected fractional decrease of *f*. * ``iz`` (np.ndarray[int], default zeros(6)) — warm-start working zone. chi (np.ndarray): initial iterate :math:`\chi_0`, used only to read its dimension. finit (float): initial cost value; used to scale ``df1``. **kwargs: unused; accepted for interface consistency. Returns: Plugin: ``self`` with all resolved parameters written back as attributes. Raises: ValueError: if any parameter is outside its valid range, or if a warm restart is requested with an inconsistent ``iz`` vector. """ # Dimension of the control vector dim = chi.size # Number of simulations # Can be explicitly given by the user, or will be determined from 'maxiter' try: niter = self.niter nsim = self.nsim except AttributeError: maxiter = self.maxiter niter = maxiter nsim = 2 * maxiter # Default parameters m = getattr(self, "nupdates", 5) dxmin = getattr(self, "dxmin", 1.0e-20) epsg = getattr(self, "epsg", 1.0e-20) mode = getattr(self, "mode", 0) df1 = getattr(self, "df1", 0.01) * finit iz = getattr(self, "iz", np.zeros(6, dtype=int)) # Init parameters towrite = """ M1QN3 (Version 2.0b, December 1993): entry point program translated in Python language dimension of the problem (n): {} number of updates: {} absolute precision on x (dxmin) : {} expected decrease for f (df1): {} relative precision on g (epsg): {} maximal number of iterations (niter): {} maximal number of simulations (nsim): {} """.format( dim, m, dxmin, df1, epsg, niter, nsim ) info(towrite) # Checking for inconsistent definition of parameters if ( dim <= 0.0 or niter <= 0.0 or nsim <= 0.0 or dxmin <= 0.0 or epsg <= 0.0 or epsg > 1.0 or mode < 0.0 or mode > 3 or m < 1 or m > 10 ): raise ValueError( "Warning: inconsistent call in M1QN3:\n" f"- dim = {dim} should be > 0\n" f"- niter = {niter} should be > 0\n" f"- nsim = {nsim} should be >0\n" f"- dxmin = {dxmin} should be >0\n" f"- epsg = {epsg} should be in ]0, 1[\n" f"- mode = {mode} should be in ]0, 3[\n" f"- m = {m} should be in ]1, 10[\n" ) # Select mode if mode - int(mode / 2.0) * 2.0 == 0: info("M1QN3: Diagonal Initial Scaling mode") sscale = False else: info("M1QN3: Scalar Initial Scaling mode") sscale = True # Cold start or warm restart? # Check iz: iz(1)=n, iz(2)=(0 if DIS, 1 if SIS), # iz(3)=m, iz(4)=jmin, iz(5)=jmax if mode % 2 == 0: info("M1QN3: cold start") else: if ( iz[1] != dim or iz[2] != sscale or iz[3] != m or iz[4] < 1 or iz[5] < 1 or iz[4] > iz[3] or iz[5] > iz[3] ): info("Warning: M1QN3: inconsistent iz for a warm " "restart") raise ValueError info("M1QN3: warm restart") iz[1] = dim iz[2] = 0 if sscale: iz[2] = 1 iz[3] = m # Update options self.mode = mode self.iz = iz self.m = iz[3] self.jmin = iz[4] self.jmax = iz[5] self.niter = niter self.nsim = nsim self.dxmin = dxmin self.df1 = df1 self.epsg = epsg return self