gpe.minimize#

Robust GPE minimizer

Attributes#

Classes#

Minimize

General minimization class.

MinimizeState

Minimizer for states with the pytimeode.interfaces.IStateForABMEvolver

MinimizeStateFixedPhase

Minimizer with fixed phase.

Module Contents#

_EPS[source]#
_TINY[source]#
class Minimize(x=None, x_scale=1.0, f_scale=1.0, plot=False)[source]#

General minimization class.

x_scale = 1.0[source]#
f_scale = 1.0[source]#
plot = False[source]#
init()[source]#

Overload this to initialize your state if needed.

abstractmethod f_df(x)[source]#

Return the objective function and it’s derivative as a function of the unpacked state x.

check(x=None)[source]#

Check that the state.get_energy() and state.get_Hy() are correct (i.e. that Hy is derivative of E().

minimize(plot=False, callback=None, method='L-BFGS-B', polish=False, broyden_alpha=None, broyden_opts=None, f_tol=1e-12, x_tol=1e-07, use_scipy=True, ignore_f=False, _test=False, _debug=False, _log=False, use_cache=True, bounds=None, **kw)[source]#

Return the state with minimized energy.

If x_tol < sqrt(eps), then we use the canned L-BFGS-B algorithm from scipy as the is very robust. If we need higher precision on x, then we use a custom L-BFGS algorithm with a modified stopping criterion.

Parameters:
  • f_tol (float) – Relative stopping tolerance for the energy.

  • x_tol (float) – Relative stopping tolerance for the wavefunction.

  • polish (bool) –

    If True, then build an approximation to the hessian during the minimization phase so that this can be used with Broyden’s method to polish the solution to high accuracy after the energy is minimized. This allows us to ensure that the wavefunction is also converged to high accuracy. (Since the energy is quadratic about the minimum, it is common for the energy to be converged to machine precision eps even though the state is only converged to about sqrt(eps)).

    Currently does not actually polish the solution - only stores the data in self.broyden_data. See use_scipy below.

  • broyden_alpha (None, float) – Initial inverse Jacobian approximation is alpha times the identity. If None, then this will be estimated by performing a line search in the descent direction.

  • broyden_opts (dict()) – Arguments to pass through to mmfutils.solve.broyden.DyadicSum().

  • use_scipy (bool) –

    If True, then use the scipy solvers, otherwise, if x_tol < sqrt(eps), then use our custom solver that performs Broyden iterations after. The issue here is that the minimizer might bail out prematurely because of the f_tol criterion before reaching the desired x_tol because the minimum is quadratic. Since we have information about the hessian, we can in principle continue to refine the solution with Broyden iterations to minimize the norm of the residual.

    This is the idea of the polish option, but one can “trick” scipy into doing this by setting f_tol=np.nan. This will always invalidate the criterion (even f_tol=0 can fail sometimes when the energy is very flat) and force scipy to continue until x_tol is met or the method fails. Always check your answer if you do this!

  • _debug (bool) – If True then return (x, f, df, locals()).

Returns:

  • x (array) – Solution

  • f, df (functions) – Objective function and its gradient in the packed representation.

  • Developer notes

    1. Do not mutate state0. Use state as a working copy if a – true state is needed.

  • 2. Be careful which version of state or state0 you use as the – argument to get_Hy and get_energy since this determines the non-linear portions. In general one should use state, but if one implements a minimization on the norm of Hy then for the derivative one must be careful.

_minimize(f, df, x0, method, callback, bounds, options)[source]#

Interface to the scipy minimizer.

_minimize_L_BFGS(f, df, x0, callback, x_tol=1e-12, safe=True, tries=5, disp=0)[source]#

Custom L-BFGS minimizer.

_minimize_norm(df, x0, callback, broyden_alpha=None, x_tol=1e-12, safe=True, tries=5, disp=0)[source]#

Custom Broyden minimizer for df only.

This looks for solutions to df=0 without regard to them being minima of the energy. This is useful for finding saddle points.

check_derivative(f, df, x, rtol=0.0001)[source]#
class MinimizeState(state, real=False, fix_N=True, **kw)[source]#

Bases: Minimize

Minimizer for states with the pytimeode.interfaces.IStateForABMEvolver interface.

state[source]#
fix_N = True[source]#
real = False[source]#
_active_inds[source]#
property x[source]#

Get current state. Must allow setting and unsetting.

property _x_dtype[source]#
init()[source]#

Overload this to initialize your state if needed.

unpack(x, state=None)[source]#

Unpack x into state including factors of x_scale

Note: Do not scale or otherwise mutate x.

pack(state)[source]#

This is not symmetric with unpack as it does not scale the solution by any factors. (This is because we unpack both states and Hpsi which have different scalings.).

f_df(x)[source]#

Return the objective function and it’s derivative as a function of the unpacked state x.

g_dg(x)[source]#

Return the objective function minimizing the residual norm.

INCOMPLETE.

minimize(psi_tol=1e-08, E_tol=1e-12, callback=None, _debug=False, **kw)[source]#

Return the state with minimized energy.

If x_tol < sqrt(eps), then we use the canned L-BFGS-B algorithm from scipy as the is very robust. If we need higher precision on x, then we use a custom L-BFGS algorithm with a modified stopping criterion.

Parameters:
  • f_tol (float) – Relative stopping tolerance for the energy.

  • x_tol (float) – Relative stopping tolerance for the wavefunction.

  • polish (bool) –

    If True, then build an approximation to the hessian during the minimization phase so that this can be used with Broyden’s method to polish the solution to high accuracy after the energy is minimized. This allows us to ensure that the wavefunction is also converged to high accuracy. (Since the energy is quadratic about the minimum, it is common for the energy to be converged to machine precision eps even though the state is only converged to about sqrt(eps)).

    Currently does not actually polish the solution - only stores the data in self.broyden_data. See use_scipy below.

  • broyden_alpha (None, float) – Initial inverse Jacobian approximation is alpha times the identity. If None, then this will be estimated by performing a line search in the descent direction.

  • broyden_opts (dict()) – Arguments to pass through to mmfutils.solve.broyden.DyadicSum().

  • use_scipy (bool) –

    If True, then use the scipy solvers, otherwise, if x_tol < sqrt(eps), then use our custom solver that performs Broyden iterations after. The issue here is that the minimizer might bail out prematurely because of the f_tol criterion before reaching the desired x_tol because the minimum is quadratic. Since we have information about the hessian, we can in principle continue to refine the solution with Broyden iterations to minimize the norm of the residual.

    This is the idea of the polish option, but one can “trick” scipy into doing this by setting f_tol=np.nan. This will always invalidate the criterion (even f_tol=0 can fail sometimes when the energy is very flat) and force scipy to continue until x_tol is met or the method fails. Always check your answer if you do this!

  • _debug (bool) – If True then return (x, f, df, locals()).

Returns:

  • x (array) – Solution

  • f, df (functions) – Objective function and its gradient in the packed representation.

  • Developer notes

    1. Do not mutate state0. Use state as a working copy if a – true state is needed.

  • 2. Be careful which version of state or state0 you use as the – argument to get_Hy and get_energy since this determines the non-linear portions. In general one should use state, but if one implements a minimization on the norm of Hy then for the derivative one must be careful.

class MinimizeStateFixedPhase(state, phase, fix_N=True, **kw)[source]#

Bases: MinimizeState

Minimizer with fixed phase.

phase[source]#
init()[source]#

Overload this to initialize your state if needed.

unpack(x, state=None)[source]#

Unpack x into state including factors of x_scale

Note: Do not scale or otherwise mutate x.

pack(state)[source]#

This is not symmetric with unpack as it does not scale the solution by any factors. (This is because we unpack both states and Hpsi which have different scalings.).

f_df(x)[source]#

Return the objective function and it’s derivative as a function of the unpacked state x.

minimize(**kw)[source]#

Return the state with minimized energy.

If x_tol < sqrt(eps), then we use the canned L-BFGS-B algorithm from scipy as the is very robust. If we need higher precision on x, then we use a custom L-BFGS algorithm with a modified stopping criterion.

Parameters:
  • f_tol (float) – Relative stopping tolerance for the energy.

  • x_tol (float) – Relative stopping tolerance for the wavefunction.

  • polish (bool) –

    If True, then build an approximation to the hessian during the minimization phase so that this can be used with Broyden’s method to polish the solution to high accuracy after the energy is minimized. This allows us to ensure that the wavefunction is also converged to high accuracy. (Since the energy is quadratic about the minimum, it is common for the energy to be converged to machine precision eps even though the state is only converged to about sqrt(eps)).

    Currently does not actually polish the solution - only stores the data in self.broyden_data. See use_scipy below.

  • broyden_alpha (None, float) – Initial inverse Jacobian approximation is alpha times the identity. If None, then this will be estimated by performing a line search in the descent direction.

  • broyden_opts (dict()) – Arguments to pass through to mmfutils.solve.broyden.DyadicSum().

  • use_scipy (bool) –

    If True, then use the scipy solvers, otherwise, if x_tol < sqrt(eps), then use our custom solver that performs Broyden iterations after. The issue here is that the minimizer might bail out prematurely because of the f_tol criterion before reaching the desired x_tol because the minimum is quadratic. Since we have information about the hessian, we can in principle continue to refine the solution with Broyden iterations to minimize the norm of the residual.

    This is the idea of the polish option, but one can “trick” scipy into doing this by setting f_tol=np.nan. This will always invalidate the criterion (even f_tol=0 can fail sometimes when the energy is very flat) and force scipy to continue until x_tol is met or the method fails. Always check your answer if you do this!

  • _debug (bool) – If True then return (x, f, df, locals()).

Returns:

  • x (array) – Solution

  • f, df (functions) – Objective function and its gradient in the packed representation.

  • Developer notes

    1. Do not mutate state0. Use state as a working copy if a – true state is needed.

  • 2. Be careful which version of state or state0 you use as the – argument to get_Hy and get_energy since this determines the non-linear portions. In general one should use state, but if one implements a minimization on the norm of Hy then for the derivative one must be careful.