basisopt.opt package

Submodules

basisopt.opt.eventemper module

class basisopt.opt.eventemper.EvenTemperedStrategy(eval_type: str = 'energy', target: float = 1e-05, max_n: int = 18, max_l: int = -1)

Bases: Strategy

Implements a strategy for an even tempered basis set, where each angular momentum shell is described by three parameters: (c, x, n) Each exponent in that shell is then given by

y_k = c*(x**k) for k=0,…,n

Algorithm:

Evaluate: energy (can change to any RMSE-compatible property) Loss: root-mean-square error Guess: null, uses _INITIAL_GUESS above Pre-conditioner: None

Initialisation:
  • Find minimum no. of shells needed

  • max_l >= min_l

  • generate initial parameters for each shell

First run:
  • optimize parameters for each shell once, sequentially

Next shell in list not marked finished:
  • re-optimise

  • below threshold or n=max_n: mark finished

  • above threshold: increment n

Repeat until all shells are marked finished.

Uses iteration, limited by two parameters:

max_n: max number of exponents in shell target: threshold for objective function

Additional attributes:

shells (list): list of (c, x, n) parameter tuples shell_done (list): list of flags for whether shell is finished (0) or not (1) target (float): threshold for optimization delta max_n (int): maximum number of primitives in shell expansion max_l (int): maximum angular momentum shell to do;

if -1, does minimal configuration

as_dict() dict[str, Any]

Returns MSONable dictionary of object

classmethod from_dict(d: dict[str, Any]) object

Creates EvenTemperedStrategy from MSONable dictionary

get_active(basis: dict[str, list[basisopt.containers.Shell]], element: str) ndarray

Returns the even temper params for the current shell

initialise(basis: dict[str, list[basisopt.containers.Shell]], element: str)

Initialises the strategy by determing the initial parameters for each angular momentum shell for the given element.

Parameters:
  • basis (InternalBasis) – the basis set being optimized

  • element (str) – the atom type of interest

next(basis: dict[str, list[basisopt.containers.Shell]], element: str, objective: float) bool

Moves the strategy forward a step (see algorithm)

Parameters:
  • basis – internal basis dictionary

  • element – symbol of atom being optimized

  • objective – value of objective function from last steps

Returns:

True if there is a next step, False if strategy is finished

set_active(values: ndarray, basis: dict[str, list[basisopt.containers.Shell]], element: str)

Given the even temper params for a shell, expands the basis Checks that the smallest exponent is >= 1e-5 and that the ratio is >= 1.01, to prevent impossible exponents

set_basis_shells(basis: dict[str, list[basisopt.containers.Shell]], element: str)

Expands parameters into a basis set

Parameters:
  • basis (InternalBasis) – the basis set to expand

  • element (str) – the atom type

basisopt.opt.optimizers module

basisopt.opt.optimizers.collective_optimize(molecules: list[basisopt.molecule.Molecule], basis: dict[str, list[basisopt.containers.Shell]], opt_data: list[tuple[str, str, basisopt.opt.strategies.Strategy, Callable[[numpy.ndarray], float], dict[str, Any]]] = [], npass: int = 3, parallel: bool = False) dict[str, dict[str, scipy.optimize._optimize.OptimizeResult]]

General purpose optimizer for a collection of atomic bases

Arguments:

molecules (list): list of Molecule objects to be included in objective basis: internal basis dictionary, will be used for all molecules opt_data (list): list of tuples, with one tuple for each atomic basis to be

optimized, (element, algorithm, strategy, regularizer, opt_params) - see the signature of _atomic_opt or optimize

npass (int): number of passes to do, i.e. it will optimize each atomic basis

listed in opt_data in order, then loop back and iterate npass times

parallel (bool): if True, will try to run Molecule calcs in parallel

Returns:

dictionary of dictionaries of scipy.optimize results for each step, corresponding to tuple in opt_data

Raises:

FailedCalculation

basisopt.opt.optimizers.optimize(molecule: ~basisopt.molecule.Molecule, element: str | None = None, algorithm: str = 'l-bfgs-b', strategy: ~basisopt.opt.strategies.Strategy = <basisopt.opt.strategies.Strategy object>, reg: ~typing.Callable[[~numpy.ndarray], float] = <function <lambda>>, opt_params: dict[str, typing.Any] = {}) dict[str, scipy.optimize._optimize.OptimizeResult]

General purpose optimizer for a single atomic basis

Parameters:
  • molecule – Molecule object

  • element (str) – symbol of atom to optimize; if None, will default to first atom in molecule

  • algorithm (str) – scipy.optimize algorithm to use

  • strategy (Strategy) – optimization strategy

  • basis_type (str) – which basis type to use; currently “orbital”, “jfit”, or “jkfit”

  • reg (func) – regularization function

  • opt_params (dict) – parameters to pass to scipy.optimize.minimize

Returns:

dictionary of scipy.optimize result objects for each step in the opt

Raises:

FailedCalculation

basisopt.opt.preconditioners module

basisopt.opt.preconditioners.inverse(inv_func: Callable[[ndarray, ...], ndarray]) Callable[[ndarray, ...], ndarray]

Decorator that adds an inverse function as an attribute All preconditioners must be decorated with an inverse, which should usually have the same signature as the parent.

Parameters:

inv_func (func) – the inverse of the preconditioner

basisopt.opt.preconditioners.logistic(x, minval=0.0001, maxval=100000.0, alpha=1.0, x0=0.0)

Logistic function

basisopt.opt.preconditioners.make_positive(x, minval=0.0001, ratio=1.4)

Returns x with all values >= minval If multiple values are < minval, the new values will be minval * (ratio**n)

basisopt.opt.preconditioners.unit(x)

Identity function

basisopt.opt.reduce module

class basisopt.opt.reduce.ReduceStrategy(starting_basis: dict[str, list[basisopt.containers.Shell]], eval_type: str = 'energy', method: str = 'scf', target: float = 1e-05, shell_mins: list[int] = [], max_l: int = -1, reopt_all: bool = True, params: dict[str, Any] = {})

Bases: Strategy

Strategy that takes a basis set and systematically removes least important exponents, until either the change in objective is larger than a threshold value, or a minimal number of exponents is reached.

Algorithm:

Evaluate: energy (can change to any RMSE-compatible property) Loss: root-mean-square error Guess: none - initial basis set to reduce must be given Pre-conditioner: any (default, make sure exponents are positive)

Initialization required, to determined parameters for reduction. While delta_objective is below threshold, and basis size > minimal:

  • rank exponents by contribution to objective, for each shell that isn’t already at its minimum size

  • remove the least important exponent, adjust basis size

  • reoptimize each shell in ascending angular-momentum order

  • recalculate delta_objective

If delta_objective > threshold:
  • reset to basis set from previous step

full_basis

internal basis to be reduced

Type:

dict

saved_basis

internal basis from last step

Type:

dict

shells

list of shells to be reduced

Type:

list(int)

target

maximum allowed change in objective value

Type:

float

method

method used to evaluate objective

Type:

str

shell_mins

minimum number of exponents in each shell, in ascending angular momentum order

Type:

list(int)

max_l

maximum angular momentum (inclusive) to reduce

Type:

int

nexps

number of exponents in each ang. momentum shell

Type:

list(int)

reduction_step

if True, an exponent will be removed when next is called

Type:

bool

as_dict() dict[str, Any]

Returns MSONable dictionary of object

classmethod from_dict(d: dict[str, Any]) object

Creates ReduceStrategy from MSONable dictionary

initialise(basis: dict[str, list[basisopt.containers.Shell]], element: str)

Initialises the strategy by determining the number of exponents in each shell, and making sure we start in a reduction step.

next(basis: dict[str, list[basisopt.containers.Shell]], element: str, objective: float) bool

Moves the strategy forward a step (see algorithm)

Parameters:
  • basis – internal basis dictionary

  • element – symbol of atom being optimized

  • objective – value of objective function from last steps

Returns:

True if there is a next step, False if strategy is finished

set_basis_shells(basis: dict[str, list[basisopt.containers.Shell]], element: str)

basisopt.opt.regularisers module

basisopt.opt.regularisers.l1_norm(x: ndarray)
basisopt.opt.regularisers.l2_norm(x: ndarray)
basisopt.opt.regularisers.linf_norm(x: ndarray)

basisopt.opt.strategies module

class basisopt.opt.strategies.Strategy(eval_type: str = 'energy', pre: ~typing.Callable[[~numpy.ndarray, ...], ~numpy.ndarray] = <function make_positive>)

Bases: MSONable

Object to describe and handle basis set optimization strategies. All strategy types should inherit from here, and give a description of the approach in the docs. This is a MINIMAL implementation, so all methods here should usually be overridden in child classes

This class also acts as a ‘Default’ optimization strategy. The alg is as follows:

Algorithm:

Evaluate: energy (can change to any RMSE-compatible property) Loss: root-mean-square error Guess: cc-pVDZ Pre-conditioner: any (default, make sure exponents are positive)

No initialisation needed. Optimize each shell in increasing order of angular momentum, so self._step = l+1, ends when self._step = max_l+1 No iteration by default.

name

identifier

Type:

str

eval_type

property to evaluate

Type:

str

params

parameters for backend, see relevant Wrapper for options

Type:

dict

guess

function to generate starting guess exponents

Type:

func

guess_params

parameters to pass to guess

Type:

dict

pre

function to precondition exponents - must have an inverse attribute

Type:

func

pre.params

parameters to pass to the preconditioner

Type:

dict

last_objective

last value of objective function

Type:

float

delta_objective

change in value of objective function from last step

Type:

float

first_run

if True, next is yet to be called

Type:

bool

basis_type

“orbital/jfit/jkfit”, allows for strategy to be applied to auxiliary bases

Type:

str

orbital_basis

if using on auxiliary basis, need to specify orbital basis here

Type:

dict

loss

function to calculate loss - currently fixed to RMSE

Type:

callable

Private attributes:

_step (int): tracks what step of optimization we’re on

as_dict() dict[str, Any]

Returns MSONable dictionary of Strategy

property eval_type: str
classmethod from_dict(d: dict[str, Any]) object

Creates a Strategy from MSONable dictionary

get_active(basis: dict[str, list[basisopt.containers.Shell]], element: str) ndarray
Parameters:
  • basis – internal basis dictionary

  • element – symbol of the atom being optimized

Returns:

the set of exponents currently being optimised

initialise(basis: dict[str, list[basisopt.containers.Shell]], element: str)

Initialises the strategy (does nothing in default)

Parameters:
  • basis – internal basis dictionary

  • element – symbol of the atom being optimized

next(basis: dict[str, list[basisopt.containers.Shell]], element: str, objective: float) bool

Moves the strategy forward a step (see algorithm)

Parameters:
  • basis – internal basis dictionary

  • element – symbol of atom being optimized

  • objective – value of objective function from last steps

Returns:

True if there is a next step, False if strategy is finished

set_active(values: ndarray, basis: dict[str, list[basisopt.containers.Shell]], element: str)

Sets the currently active exponents to the given values.

Parameters:
  • values (list) – list of new exponents

  • basis – internal basis dictionary

  • element – symbol of atom being optimized

Module contents