simsopt._core package
Submodules
simsopt._core.derivative module
- class simsopt._core.derivative.Derivative(data={})
Bases:
object
This class stores the derivative of a scalar output wrt to the individual
Optimizable
classes that are required to compute this output.The idea of this class is as follows:
Consider a situation
inA = OptimA() inB = OptimB() inter1 = Intermediate1(inA, inB) inter2 = Intermediate2(inA, inB) obj = Objective(inter1, inter2)
Then
obj.dJ(partials=True)
will return aDerivative
object containing a dictionary{ inA : dobj/dinA, inB : dobj/dinB, }
with
dobj/dinA = dobj/dinter1 * dinter1/dinA + dobj/dinter2 * dinter2/dinA dobj/dinB = dobj/dinter1 * dinter1/dinB + dobj/dinter2 * dinter2/dinB
SIMSOPT computes these derivatives by first computing
dobj/dinter1
anddobj/dinter2
and then passing this vector toIntermediate1.vjp
andIntermediate2.vjp
, which returns{ inA: dobj/dinter1 * dinter1/dinA inB: dobj/dinter1 * dinter1/dinB }
and
{ inA: dobj/dinter2 * dinter2/dinA inB: dobj/dinter2 * dinter2/dinB }
respectively. Due to the overloaded
__add__
and__iadd__
functions adding theDerivative
objects than results in the desired{ inA: dobj/dinter1 * dinter1/dinA + dobj/dinter2 * dinter2/dinA inB: dobj/dinter1 * dinter1/dinB + dobj/dinter2 * dinter2/dinB }
This
Derivative
can then be used to obtain partial derivatives or the full gradient ofJ
, viadJ = obj.dJ(partials=True) dJ_by_dinA = dJ(inA) # derivative of Objective w.r.t. to OptimA dJ_by_dinB = dJ(inB) # derivative of Objective w.r.t. to OptimB gradJ = dJ(obj) # gradient of Objective
For the common case in which you just want the gradient of
obj.J
and do not need the individual partial derivatives, the argumentpartials=True
can be omitted inobj.dJ()
. In this case,obj.dJ()
directly returns the gradient rather than returning theDerivative
object, acting as a shorthand forobj.dJ(partials=True)(obj)
. This behavior is implemented with the decoratorderivative_dec
.- __call__(optim, as_derivative=False)
Get the derivative with respect to all DOFs that
optim
depends on.- Parameters
optim – An Optimizable object
simsopt._core.finite_difference module
This module provides Jacobian evaluated with finite difference scheme
- class simsopt._core.finite_difference.FiniteDifference(func: Callable, x0: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, abs_step: Real = 1e-07, rel_step: Real = 0.0, diff_method: str = 'forward')
Bases:
object
Provides Jacobian evaluated with finite difference scheme. Supplies a method named jac to be used with optimizers. Use the initialization to customize the finite difference scheme
- jac(x: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None) Union[Sequence[Real], NDArray[Any, float64]]
simsopt._core.optimizable module
Provides graph based Optimizable class, whose instances can be used to build an optimization problem in a graph like manner.
- class simsopt._core.optimizable.Optimizable(x0: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, names: Optional[Sequence[str]] = None, fixed: Optional[Union[Sequence[bool], NDArray[Any, bool_]]] = None, lower_bounds: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, upper_bounds: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, *, dofs: Optional[DOFs] = None, external_dof_setter: Optional[Callable[[...], None]] = None, depends_on: Optional[Sequence[Optimizable]] = None, opt_return_fns: Optional[Sequence[Sequence[str]]] = None, funcs_in: Optional[Sequence[Callable[[...], Union[Sequence[Real], NDArray[Any, float64], Real]]]] = None, **kwargs)
Bases:
Callable
,Hashable
,GSONable
Experimental callable ABC that provides lego-like optimizable objects that can be used to partition the optimization problem into a graph.
The class provides many features that simplify defining the optimization problem.
Optimizable and its subclasses define the optimization problem. The optimization problem can be thought of as a directed acycling graph (DAG), with each instance of Optimizable being a vertex (node) in the DAG. Each Optimizable object can take other Optimizable objects as inputs and through this container logic, the edges of the DAG are defined.
Alternatively, the input Optimizable objects can be thought of as parents to the current Optimizable object. In this approach, the last grand-child defines the optimization problem by embodying all the elements of the parents and grand-parents.
Each call to child instance gets in turn propagated to the parent. In this way, the last child acts as the final optimization problem to be solved. For an example of the final optimization node, refer to simsopt.objectives.least_squares.LeastSquaresProblem
The class automatically partitions degrees of freedoms (DOFs) of the optimization problem to the associated Optimizable nodes. Each DOF defined in a parent gets passed down to the children as a needed DOF for the child. So a DOF needed by parent node can be given as an input to the methods in the child node. Any of the DOFs could be fixed in which case, it should be removed as an argument to the call-back function from the final Optimizable node.
The class implements a callable hook that provides minimal caching. All derived classes have to register methods that return objective function type values. This is done by implementing the following class attribute in the class definition: .. code-block:: python
return_fn_map = {‘name1’: method1, ‘name2’: method, …}
The Optimizable class maintains the list of return functions needed by each of the calling Optimizable objects either during child initialization or later using the provided methods. The calling optimizable object could then call the Optimizable object directly using the __call__ hook or could call the individual methods.
This back and forth propagation of DOFs partitioning and function calls happens dynamically.
The class is hashable and the names of the instances are unique. So instances of Optimizable class can be used as keys.
Note
If the Optimizable object is called using the __call__ hook, make sure to supply the argument child=self
__init__ takes instances of subclasses of Optimizable as input and modifies them to add the current object as a child for input objects. The return fns of the parent object needed by the child could be specified by using opt_return_fns argument
- __add__(other)
Add two Optimizable objects
- __eq__(other: Optimizable) bool
Checks the equality condition
- Parameters
other – Another object of subclass of Optimizable
Returns: True only if both are the same objects.
- __init__(x0: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, names: Optional[Sequence[str]] = None, fixed: Optional[Union[Sequence[bool], NDArray[Any, bool_]]] = None, lower_bounds: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, upper_bounds: Optional[Union[Sequence[Real], NDArray[Any, float64]]] = None, *, dofs: Optional[DOFs] = None, external_dof_setter: Optional[Callable[[...], None]] = None, depends_on: Optional[Sequence[Optimizable]] = None, opt_return_fns: Optional[Sequence[Sequence[str]]] = None, funcs_in: Optional[Sequence[Callable[[...], Union[Sequence[Real], NDArray[Any, float64], Real]]]] = None, **kwargs)
- Parameters
x0 – Initial state (or initial values of DOFs)
names – Human identifiable names for the DOFs
fixed – Array describing whether the DOFs are free or fixed
lower_bounds – Lower bounds for the DOFs
upper_bounds – Upper bounds for the DOFs
dofs – Degrees of freedoms as DOFs object
external_dof_setter – Function used by derivative classes to handle DOFs outside of the dofs object within the class. Mainly used when the DOFs are primarily handled by C++ code. In that case, for all intents and purposes, the internal dofs object is a duplication of the DOFs stored elsewhere. In such cases, the internal dofs object is used to handle the dof partitioning, but external dofs are used for computation of the objective function.
depends_on – Sequence of Optimizable objects on which the current Optimizable object depends on to define the optimization problem in conjuction with the DOFs. If the optimizable problem can be thought of as a direct acyclic graph based on dependencies, the optimizable objects supplied with depends_on act as parent nodes to the current Optimizable object in such an optimization graph
opt_return_fns – Specifies the return value for each of the Optimizable object. Used in the case, where Optimizable object can return different return values. Typically return values are computed by different functions defined in the Optimizable object. The return values are selected by choosing the functions. To know the various return values, use the Optimizable.get_return_fn_names function. If the list is empty, default return value is used. If the Optimizable object can return multiple values, the default is the array of all possible return values.
funcs_in – Instead of specifying depends_on and opt_return_fns, specify the methods of the Optimizable objects directly. The parent objects are identified automatically. Doesn’t work with funcs_in with a property decorator
- __mul__(other)
Multiply an Optimizable object by a scalar
- __rmul__(other)
Multiply an Optimizable object by a scalar
- _abc_impl = <_abc_data object>
- _add_child(child: Optimizable) None
Adds another Optimizable object as child. All the required processing of the dependencies is done in the child node. This method is used mainly to maintain 2-way link between parent and child.
- Parameters
child – Direct dependent (child) of the Optimizable object
- _get_ancestors() list[Optimizable]
Get all the ancestors of the current Optimizable object
- Returns
List of Optimizable objects that are parents of current Optimizable objects
- _ids = count(1)
- _remove_child(other: Optimizable) None
Remove the specific Optimizable object from the children list.
- Parameters
child – Direct dependent (child) of the Optimizable object
- _update_full_dof_size_indices() None
Updates the full DOFs lengths for this instance and those of the children. Updates the ancestors attribute as well.
Call this function whenever parents are added or removed. Recursively calls the same function in children.
- add_parent(index: int, other: Optimizable) None
Adds another Optimizable object as parent at specified index.
- Parameters
int – Index of the parent’s list
other – Another Optimizable object to be added as parent
- add_return_fn(child: Optimizable, fn: Union[str, Callable]) None
Add return function to the list of the return functions called by the child Optimizable object
- Parameters
child – an Optimizable object that is direct dependent of the current Optimizable instance
fn – method of the Optimizable object needed by the child
- append_parent(other: Optimizable) None
Appends another Optimizable object to parents list
- Parameters
other – New parent Optimizable object
- as_dict(serial_objs_dict=None) dict
A JSON serializable dict representation of an object.
- property bounds: Tuple[Union[Sequence[Real], NDArray[Any, float64]], Union[Sequence[Real], NDArray[Any, float64]]]
Lower and upper bounds of the free DOFs associated with the current Optimizable object and those of its ancestors
- property dof_names: Sequence[str]
Names (Identifiers) of the DOFs associated with the current Optimizable object and those of its ancestors
- property dof_size: Integral
Total number of free DOFs associated with the Optimizable object as well as parent Optimizable objects.
- property dofs: DOFs
Return all the attributes of local degrees of freedom via DOFs object. Mainly used to conform with the default as_dict method of GSONable and to share DOFs object between multiple Optimizable objects
- property dofs_free_status: Union[Sequence[bool], NDArray[Any, bool_]]
Boolean array denoting whether the DOFs associated with the current and ancestors Optimizable objects are free or not
- fix(key: Union[Integral, str]) None
Set the fixed attribute for the given degree of freedom.
- Parameters
key – DOF identifier
- fix_all() None
Set the ‘fixed’ attribute for all the degrees of freedom associated with the current Optimizable object including those of ancestors.
- classmethod from_file(filename: str)
- classmethod from_str(input_str: str, fmt='json')
- property full_dof_names: Sequence[str]
Names (Identifiers) of the DOFs associated with the current Optimizable object and those of its ancestors
- property full_dof_size: Integral
Total number of all (free and fixed) DOFs associated with the Optimizable object as well as parent Optimizable objects.
- property full_x: Union[Sequence[Real], NDArray[Any, float64]]
Numeric values of all the DOFs (both free and fixed) associated with the current Optimizable object and those of its ancestors
- get(key: Union[Integral, str]) Real
Get the value of specified DOF. Even fixed dofs can be obtained individually.
- Parameters
key – DOF identifier
- get_parent_return_fns_list() List[List[Callable]]
Get a list of the funcs returned by the parents as list of lists
- Returns
The funcs returned by all the parents of the Optimizable object
- get_return_fn_list() List[List[Callable]]
Gets return functions from this Optimizable object used by all the child Optimizable objects
- Returns
List of methods that return a value when the current Optimizable object is called from the children.
- get_return_fn_names() List[str]
Return the names of the functions that could be used as objective functions.
- Returns
List of function names that could be used as objective functions
- get_return_fns(child: Optimizable) List[Callable]
Gets return functions from this Optimizable object used by the child Optimizable object
- Parameters
child – Dependent Optimizable object
- Returns
List of methods that return a value when the current Optimizable object is called from the child
- is_fixed(key: Union[Integral, str]) bool
Checks if the specified dof is fixed
- Parameters
key – DOF identifier
- is_free(key: Union[Integral, str]) bool
Checks if the specified dof is free
- Parameters
key – DOF identifier
- property local_bounds: Tuple[Union[Sequence[Real], NDArray[Any, float64]], Union[Sequence[Real], NDArray[Any, float64]]]
Lower and upper bounds of the free DOFs associated with this Optimizable object
- property local_dof_names: Sequence[str]
Names (Identifiers) of the DOFs associated with this Optimizable object
- property local_dof_size: Integral
Number of free DOFs associated with the Optimizable object.
- Returns
Number of free DOFs associated with the Optimizable object.
- property local_dofs_free_status: Union[Sequence[bool], NDArray[Any, bool_]]
Boolean array denoting whether the DOFs associated with the current Optimizable object are free or not
- local_fix_all() None
Set the ‘fixed’ attribute for all local degrees of freedom associated with the current Optimizable object.
- property local_full_dof_names: Sequence[str]
Names (Identifiers) of the DOFs associated with this Optimizable object
- property local_full_dof_size: Integral
Number of all (free and fixed) DOFs associated with the Optimizable object.
- Returns
Total number of free and fixed DOFs associated with the Optimizable object.
- property local_full_lower_bounds: Union[Sequence[Real], NDArray[Any, float64]]
- property local_full_upper_bounds: Union[Sequence[Real], NDArray[Any, float64]]
- property local_full_x
Numeric values of all DOFs (both free and fixed) associated with this Optimizable object
- property local_lower_bounds: Union[Sequence[Real], NDArray[Any, float64]]
Lower bounds of the free DOFs associated with this Optimizable object
- local_unfix_all() None
Unset the ‘fixed’ attribute for all local degrees of freedom associated with the current Optimizable object.
- property local_upper_bounds: Union[Sequence[Real], NDArray[Any, float64]]
Upper bounds of the free DOFs associated with this Optimizable object
- property local_x: Union[Sequence[Real], NDArray[Any, float64]]
Numeric values of the free DOFs associated with this Optimizable object
- property lower_bounds: Union[Sequence[Real], NDArray[Any, float64]]
Lower bounds of the free DOFs associated with the current Optimizable object and those of its ancestors
- property parent_return_fns_no: int
Compute the total number of the return funcs of all the parents of the Optimizable object
- Returns
The total number of the return funcs of the Optimizable object’s parents.
- plot_graph(show=True)
Plot the directed acyclical graph that represents the dependencies of an
Optimizable
on its parents. The workflow is as follows: generate anetworkx
DiGraph
using thetraversal
function defined below. Next, callgraphviz_layout
which determines sensible positions for the nodes of the graph using thedot
program ofgraphviz
. Finally,networkx
plots the graph usingmatplotlib
.Note that the tool
network2tikz
at https://github.com/hackl/network2tikz can be used to convert the networkxDiGraph
and positions to a latex file for publication.- Parameters
show – Whether to call the
show()
function of matplotlib.- Returns
The
networkx
graph corresponding to thisOptimizable
’s directed acyclical graph and a dictionary of node names that map to sensible x, y positions determined bygraphviz
- pop_parent(index: int = -1) Optimizable
Removes the parent Optimizable object at specified index.
- Parameters
index – Index of the list of the parents
- Returns
The removed parent Optimizable object
- recompute_bell(parent=None)
Function to be called whenever new DOFs input is given or if the parent Optimizable’s data changed, so the output from the current Optimizable object is invalid.
This method gets called by various DOF setters. If only the local DOFs of an object are being set, the recompute_bell method is called in that object and also in the descendent objects that have a dependency on the object, whose local DOFs are being changed. If gloabl DOFs of an object are being set, the recompute_bell method is called in the object, ancestors of the object, as well as the descendents of the object.
Need to be implemented by classes that provide a dof_setter for external handling of DOFs.
- remove_parent(other: Optimizable)
Removes the specified Optimizable object from the list of parents.
- Parameters
other – The Optimizable object to be removed from the list of parents
- replace_dofs(dofs)
Calls all the required functions in correct order if the DOFs object is replaced manually by the user :param dofs: DOFs object
- return_fn_map: Dict[str, Callable] = NotImplemented
- save(filename=None, fmt=None, **kwargs)
- set(key: Union[Integral, str], new_val: Real) None
Update the value held the specified DOF. Even fixed dofs can be set this way
- Parameters
key – DOF identifier
new_val – New value of the DOF
- set_recompute_flag(parent=None)
- unfix(key: Union[Integral, str]) None
Unset the fixed attribute for the given degree of freedom
- Parameters
key – DOF identifier
- unfix_all() None
Unset the ‘fixed’ attribute for all local degrees of freedom associated with the current Optimizable object including those of the ancestors.
- property unique_dof_lineage
- update_free_dof_size_indices() None
Updates the DOFs lengths for the Optimizable object as well as those of the descendent (dependent) Optimizable objects.
Call this function whenever DOFs are fixed or unfixed or when parents are added/deleted. Recursively calls the same function in children
- property upper_bounds: Union[Sequence[Real], NDArray[Any, float64]]
Upper bounds of the free DOFs associated with the current Optimizable object and those of its ancestors
- property x: Union[Sequence[Real], NDArray[Any, float64]]
Numeric values of the free DOFs associated with the current Optimizable object and those of its ancestors
- property x0
Mimics dataclass behavior for Optimizable
- class simsopt._core.optimizable.OptimizableSum(opts)
Bases:
Optimizable
Represents a sum of
Optimizable
objects. This class is useful for combining terms in an objective function. For now, this feature works on classes for which.J()
returns an objective value and.dJ()
returns the gradient, e.g. coil optimization.- Parameters
opts – A python list of
Optimizable
object to sum.
- J()
- _abc_impl = <_abc_data object>
- _ids = count(1)
- dJ(*args, partials=False, **kwargs)
- class simsopt._core.optimizable.ScaledOptimizable(factor, opt)
Bases:
Optimizable
Represents an
Optimizable
object scaled by a constant factor. This class is useful for including a weight in front of terms in an objective function. For now, this feature works on classes for which.J()
returns an objective value and.dJ()
returns the gradient, e.g. coil optimization.- Parameters
factor – (float) The constant scale factor.
opt – An
Optimizable
object to scale.
- J()
- _abc_impl = <_abc_data object>
- _ids = count(1)
- dJ(*args, partials=False, **kwargs)
- simsopt._core.optimizable.load(filename, *args, **kwargs)
Function to load simsopt object from a file. Only JSON format is supported at this time. Support for additional formats will be added in future :param filename: Name of file from which simsopt object has to be initialized
- Returns
Simsopt object
- simsopt._core.optimizable.make_optimizable(func, *args, dof_indicators=None, **kwargs)
Factory function to generate an Optimizable instance from a function to be used with the graph framework.
- Parameters
func – Callable to be used in the optimization
args – Positional arguments to pass to “func”.
dof_indicators – List of strings that match with the length of the args and kwargs. Each string can be either of “opt” - to indicate the argument is optimizable object “dof” - argument that is a degree of freedom for optimization “non-dof” - argument that is not part of optimization. Here ordered property of the dict is used to map kwargs to dof_indicators. Another important thing to consider is dofs related to optimizable objects supplied as arguments should not be given.
kwargs – Keyword arguments to pass to “func”.
- Returns
Optimizable object to be used in the graph based optimization. This object has a bound function
J()
that calls the originally suppliedfunc()
. Ifobj
is the returned object, passobj.J
to theLeastSquaresProblem
- simsopt._core.optimizable.save(simsopt_objects, filename, *args, **kwargs)
simsopt._core.util module
This module contains small utility functions and classes needed by _core subpackage.
- exception simsopt._core.util.ObjectiveFailure
Bases:
Exception
Defines a custom exception used to indicate failure when evaluating the objective function. For example, if Vmec or Spec fail to converge, this exception will be thrown. The simsopt solvers will catch this specific exception (not others) and set the objective function to a large number.