finesse.symbols module

Symbolic manipulations (expand, collect, etc.) are based on the book:

Cohen JS. Computer algebra and symbolic computation: mathematical methods. First edition, 2003.

class finesse.symbols.Constant(value, name=None)[source]

Bases: Symbol

Defines a constant symbol that can be used in symbolic math.

Parameters

valuefloat, int

Value of constant

namestr, optional

Name of the constant to use when printing

eval(subs=None, **kwargs)[source]

Evaluate this constant.

If a substitution is available the value of that will be used instead of self.value

property is_named[source]

Was this constant given a specific name.

property name[source]
substitute(subs)[source]

Uses a dictionary to substitute terms in this expression with another. This does not perform any evaluation of any terms, unlike eval(subs=…).

Parameters

subsdict

Dictionary of substitutions to make. Keys can be the actual symbol or the name of the symbol in string form. Values must all be proper symbols.

class finesse.symbols.Function(name, operation, *args)[source]

Bases: Symbol

This is a symbol to represent a mathematical function. This could be a simple addition, or a more complicated multi-argument function.

It supports creating new mathematical operations:

import math
import cmath

cos   = lambda x: finesse.symbols.Function("cos", math.cos, x)
sin   = lambda x: finesse.symbols.Function("sin", math.sin, x)
atan2 = lambda y, x: finesse.symbols.Function("atan2", math.atan2, y, x)

Complex math can also be used:

import numpy as np
angle = lambda x: finesse.symbols.Function("angle", np.angle, x)
print(f"{angle(1+1j)} = {angle(1+1j).eval()}")

Parameters

namestr

The operation name. This is used for dumping operations to kat script.

operationcallable

The function to pass the arguments of this operation to.

Other Parameters

*args

The arguments to pass to operation during a call.

property contains_unresolved_symbol[source]

Whether the operation contains any unresolved symbols.

Getter:

Returns true if any symbol in the operation is an instance of Resolving, false otherwise. Read-only.

eval(**kwargs)[source]

Evaluates the operation.

Parameters

subsdict, optional

Parameter substitutions can be given via an optional subs dict (mapping parameters to substituted values).

keepiterable, str

A collection of names of variables to keep as variables when evaluating.

Notes

A division by zero will return a NaN, rather than raise an exception.

Returns

resultnumber or array-like

The single-valued result of evaluation of the operation (if no substitutions given, or all substitutions are scalar-valued). Otherwise, if any parameter substitution was a numpy.ndarray, then a corresponding array of results.

substitute(subs)[source]

Uses a dictionary to substitute terms in this expression with another. This does not perform any evaluation of any terms, unlike eval(subs=…).

Parameters

subsdict

Dictionary of substitutions to make. Keys can be the actual symbol or the name of the symbol in string form. Values must all be proper symbols.

class finesse.symbols.LazySymbol(name, function, *args)[source]

Bases: Symbol

A generic way to make some lazily evaluated symbol.

The value is dependant on a lambda function and some arbitrary arguments which will be called when the symbol is evaluated.

Parameters

namestr

Human readable string name for the symbol

functioncallable

Function to call when evaluating the symbol

*argsobjects

Arguments to pass to function when evaluating

Examples

>>> a = LazyVariable('a', lambda x: x**2, 10)
>>> print(a)
<Symbolic='(a*10)' @ 0x7fd6587e6760>
>>> print((a*10).eval())
1000
eval(**kwargs)[source]
property name[source]
finesse.symbols.MAKE_LOP(name, opfn)[source]
finesse.symbols.MAKE_LOP_simplify_truediv()[source]
finesse.symbols.MAKE_ROP(name, opfn)[source]
finesse.symbols.MAKE_ROP_simplify_truediv()[source]
finesse.symbols.MAKE_simplify_add(dir)[source]
finesse.symbols.MAKE_simplify_mul(dir)[source]
finesse.symbols.MAKE_simplify_neg()[source]
finesse.symbols.MAKE_simplify_pos()[source]
finesse.symbols.MAKE_simplify_pow(dir)[source]
finesse.symbols.MAKE_simplify_sub(dir)[source]
class finesse.symbols.Matrix(name)[source]

Bases: Symbol

A Matrix symbol.

eval(**kwargs)[source]
class finesse.symbols.Resolving[source]

Bases: Symbol

A special symbol that represents a symbol that is not yet resolved.

This is used in the parser to support self-referencing parameters.

An error is thrown if the value is attempted to be read.

eval(**kwargs)[source]
property name[source]
class finesse.symbols.Symbol[source]

Bases: ABC

all(predicate, memo=None)[source]

Returns all the symbols that are present in this expression which satisify the predicate.

Parameters

predicatecallable

Method which takes in an argument and returns True if it matches.

Examples

To select all Constant`s and `Variable`s from an expression `y:

>>> y.all(lambda a: isinstance(a, (Constant, Variable)))
arccos()[source]
arcsin()[source]
arctan()[source]
arctan2(x)[source]
changing_parameters()[source]
collect()[source]

Collects like terms in the expressions.

conj()[source]
conjugate()[source]
cos()[source]
deg2rad()[source]
degrees()[source]
abstractmethod eval() float | complex | int[source]
exp()[source]
expand()[source]

Performs a basic expansion of the symbolic expression.

expand_symbols()[source]

A method that expands any symbolic parameter references that are themselves symbolic. This can be used to get an expression that only depends on references that are numeric.

Examples

>>> import finesse
>>> model = finesse.Model()
>>> model.parse(
...     '''
...     var d 300
...     var c 6000
...     var b c+d
...     var a b+1
...     '''
... )
>>> model.a.value.expand_symbols()
<Symbolic='((c+d)+1)' @ 0x7faa4d351c10>

Parameters

symSymbolic

Symbolic equation to expand

property imag[source]
property is_changing[source]

Returns True if one of the arguements of this symbolic object is varying whilst a :class:`` is running.

lambdify(*args, expand_symbols=False, ignore_unused_symbols=False)[source]

Converts this symbolic expression into a function that can be called.

Parameters

argsSymbols

Symbols to use to make up the arguments of the generated function. If none are provided then the current values of ParameterRef`s are used and `Variables are left as they are.

expand_symbolsbool, optional

If True, the expression will first have any dependent variables expanded. See .expand_symbols.

log()[source]
log10()[source]
parameters(memo=None)[source]

Returns all the parameters that are present in this symbolic expression.

Parameters are symbols whose values are attached to a model

rad2deg()[source]
radians()[source]
property real[source]
sin()[source]
sqrt()[source]
substitute(mapping)[source]

Uses a dictionary to substitute terms in this expression with another. This does not perform any evaluation of any terms, unlike eval(subs=…).

Notes

The symbolic substitution implemented here is not recursive, consider:

>>> y = a + b
>>> y.subs({a:a+b, b:a}) # results in => a+b+a

Here b is not replaced in the substitutions. The only time this happens is if one mapping is purely numeric:

>>> y.subs({a:a+b, b:1}) # results in => a+2

Parameters

mappingdict

Dictionary of substitutions/mappings to make. Keys can be the actual symbol or the name of the symbol in string form. Values must all be proper symbols.

sympy_simplify()[source]

Converts this expression into a Sympy symbol.

tan()[source]
to_binary_add_mul()[source]

Converts a symbolic expression to use binary forms of operator.add and operator.mul operators, rather than the n-ary operator_add and operator_mul.

Returns

Symbol

to_nary_add_mul()[source]

Converts a symbolic expression to use n-ary forms of operator_add and operator_mul operators, rather than the binary-ary operator.add and operator.mul.

Returns

Symbol

to_sympy()[source]

Converts a Finesse symbolic expression into a Sympy expression.

Warning: for large functions this can be quite slow.

property value[source]

The current value of this symbol

class finesse.symbols.Variable(name)[source]

Bases: Symbol

Makes a variable symbol that can be used in symbolic math. Values must be substituted in when evaluating an expression.

Examples

Using some variables to make an expression and evaluating it:

>>> import numpy as np
>>> x = Variable('x')
>>> y = Variable('y')
>>> z = 4*x**2 - np.cos(y)
>>> print(f"{z} = {z.eval(subs={x:2, y:3})} : x={2}, y={3}")
(4*x**2-y) = 13 : x=2, y=3

Parameters

valuefloat, int

Value of constant

namestr, optional

Name of the constant to use when printing

eval(subs=None, keep=None, **kwargs)[source]

Evaluates this variable and returns either itself or a substituted value.

Parameters

subsdict

Dictionary of object

keepiterable, str

A collection of names of variables to keep as variables when evaluating. Keep will override any substitution.

property name[source]
finesse.symbols.add_sort_key(a)[source]
finesse.symbols.as_symbol(x)[source]
finesse.symbols.base_exponent(y)[source]
finesse.symbols.coefficient_and_term(y)[source]
finesse.symbols.collect(y)[source]
finesse.symbols.display(a, dunder=(), num_format: str | None = None)[source]

For a given Symbol this method will return a human readable string representing the various operations it contains.

Parameters

aSymbol

Symbol to print

dundertuple

Names of variables to display with double underscores pre- and suf-fixing the names.

num_format: str | None

Possible python format string to format numbers in the expression

Returns

String form of Symbol

finesse.symbols.eval_symbolic_numpy(a, *keep)[source]
finesse.symbols.evaluate(x)[source]

Evaluates a symbol or N-dimensional array of symbols.

Parameters

xSymbol or array-like

A symbolic expression or an array of symbolic expressions.

Returns

outfloat, complex, numpy.ndarray

A single value for the evaluated expression if x is not array-like, otherwise an array of the evaluated expressions.

finesse.symbols.expand(y)[source]
finesse.symbols.expand_mul(y)[source]
finesse.symbols.expand_pow(y)[source]
finesse.symbols.finesse2sympy(expr, iter_num=0)[source]

Notes

It might be common for this this function to throw a NotImplementedError. This function maps, by hand, various operator and numpy functions to sympy. If you come across this error, you’ll need to update the if-statement to include the missing operations. Over time this should get fixed for most use cases.

finesse.symbols.format_arg(arg, num_format: str | None = None)[source]
finesse.symbols.is_integer(n)[source]

Checks if n is an integer.

Parameters

nstr, float

Input to check

finesse.symbols.mul_sort_key(a)[source]

Sorting key for multiplication arguments. Puts constants first then others

finesse.symbols.np_eval_symbolic_numpy(a, *keep)[source]
finesse.symbols.operator_add(*args)[source]
finesse.symbols.operator_mul(*args)[source]
finesse.symbols.operator_sub(*args)[source]
finesse.symbols.reduce_mul_args(args)[source]

Sorts and reduces a multiply operation arguments.

Collect constants and sort variables by their str.

finesse.symbols.simplification(allow_flagged=False)[source]

When used any symbolic operations will apply various simplification rules rather than recording everything symbolic operation, to preserve intent. This is useful when you want situations like 0*a -> 0, or a*a -> a**2. A complete simplification is not applied but it will generally yeild more efficient symbolic expressions. Intent preservation is required by KatScript so that it can serialise and deserialise (unparse and parse) a model into a script form without losing specific equations. For example, it often useful to record how many minus signs or factors of two have been used in an expression, rather than cancelling them out for record keeping.

Parameters

allow_flaggedbool, optional

When True, it will not throw an error if already in a simplification state.

finesse.symbols.sympy2finesse(expr, symbol_dict=None, iter_num=0)[source]