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:
SymbolDefines 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
- 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:
SymbolThis 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
subsdict (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:
SymbolA 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
- class finesse.symbols.Resolving[source]
Bases:
SymbolA 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.
- 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)))
- 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 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.
- 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
- 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.
- 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
- class finesse.symbols.Variable(name)[source]
Bases:
SymbolMakes 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
- 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
- a
Symbol 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
- a
- finesse.symbols.evaluate(x)[source]
Evaluates a symbol or N-dimensional array of symbols.
Parameters
- x
Symbolor 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.
- x
- 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.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.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.