Package: cexprtk
cexprtk: Mathematical Expression Parsing and Evaluation in Pythoncexprtkis a cython wrapper around the "ExprTK: C++ Mathematical Expression  Toolkit Library"  by Arash Partow. Usingcexprtka powerful mathematical expression engine can be incorporated into your python project.Table of ContentsInstallationUsageExample: Evaluate a simple equationExample: Using VariablesExample: Re-using expressionsExample: Defining custom functionsExample: Defining an unknown symbol resolverExample: expressions that contain return statements to produce multiple valuesAPI ReferenceClass Referenceclass Expression:Defining unknown symbol-resolver:definit(self,expression,symbol_table,unknown_symbol_resolver_callback= None):def results(self):def value(self):defcall(self):symbol_tableclass Symbol_Table:definit(self,variables,constants= {},add_constants= False, functions = {}):variablesconstantsfunctionsclass USRSymbolType:VARIABLECONSTANTUtility Functionsdef check_expression (expression)def evaluate_expression (expression,variables)AuthorsLicenseInstallationThe latest version ofcexprtkcan be installed usingpip:$pipinstallcexprtkNote:Installation requires a compatible C++ compiler to be installed (unless installing from a binary wheel).UsageThe following examples show the major features ofcexprtk.Example: Evaluate a simple equationThe following shows how the arithmetic expression(5+5) * 23can be evaluated:>>>importcexprtk>>>cexprtk.evaluate_expression("(5+5) * 23",{})230.0Example: Using VariablesVariables can be used within expressions by passing a dictionary to theevaluate_expressionfunction. This maps variable names to their values. The expression from the previous example can be re-calculated using variable values:>>>importcexprtk>>>cexprtk.evaluate_expression("(A+B) * C",{"A":5,"B":5,"C":23})230.0Example: Re-using expressionsWhen using theevaluate_expression()function, the mathematical expression is parsed, evaluated and then immediately thrown away. This example shows how to re-use anExpressionfor multiple evaluations.An expression will be defined to calculate the circumference of circle, this will then be re-used to calculate the value for several different radii.First aSymbol_Tableis created containing a variabler(for radius), it is also populated with some useful constants such as π.>>>importcexprtk>>>st=cexprtk.Symbol_Table({'r':1.0},add_constants=True)Now an instance ofExpressionis created, defining our function:>>>circumference=cexprtk.Expression('2*pi*r',st)TheSymbol_Tablewas initialised withr=1, the expression can be evaluated for this radius simply by calling it:>>>circumference()6.283185307179586Now update the radius to a value of 3.0 using the dictionary like object returned by theSymbol_Table's.variablesproperty:>>>st.variables['r']=3.0>>>circumference()18.84955592153876Example: Defining custom functionsPython functions can be registered with aSymbol_Tablethen used in anExpression. In this example a custom function will be defined which produces a random number within a given range.A suitable function exists in therandommodule, namelyrandom.uniform. As this is an instance method it needs to be wrapped in function:>>>importrandom>>>defrnd(low,high):...returnrandom.uniform(low,high)...Ourrndfunction now needs to be registered with aSymbol_Table:>>>importcexprtk>>>st=cexprtk.Symbol_Table({})>>>st.functions["rand"]=rndThefunctionsproperty of theSymbol_Tableis accessed like a dictionary. In the preceding code snippet, a symbol table is created and then therndfunction is assigned to therandkey. This key is used as the function's name in acexprtkexpression. The key cannot be the same as an existing variable, constant or reserved function name.Therandfunction will now be used in an expression. This expression chooses a random number between 5 and 8 and then multiplies it by 10. The followin snippet shows the instantiation of theExpressionwhich is then evaluated a few times. You will probably get different numbers out of your expression than shown, this is because your random number generator will have been initialised with a different seed than used in the example.>>>e=cexprtk.Expression("rand(5,8) * 10",st)>>>e()61.4668441077191>>>e()77.13523163246415>>>e()59.14881842716157>>>e()69.1476535568958Example: Defining an unknown symbol resolverA callback can be passed to theExpressionconstructor through theunknown_symbol_resolver_callbackparameter. This callback is invoked during expression parsing when a variable or constant is encountered that isn't in theSymbol_Tableassociated with theExpression.The callback can be used to provide some logic that leads to a new symbol being registered or for an error condition to be flagged.The Problem:The following example shows a potential use for the symbol resolver:An expression contains variables of the formm_VARIABLENAMEandf_VARIABLENAME.m_orf_prefix the  actual variable name (perhaps indicating gender).VARIABLENAMEshould be used to look up the desired value in a dictionary.The dictionary value ofVARIABLENAMEshould then be weighted according to its prefix:m_variables should be multiplied by 0.8.f_variables should be multiplied by 1.1.The Solution:First theVARIABLENAMEdictionary is defined:variable_values={'county_a':82,'county_b':76}Now the callback is defined. This takes a single argument,symbol, which gives the name of the missing variable found in the expression:defcallback(symbol):# Tokenize the symbol name into prefix and VARIABLENAME components.prefix,variablename=symbol.split("_",1)# Get the value for this VARIABLENAME from the variable_values dictvalue=variable_values[variablename]# Find the correct weight for the prefixifprefix=='m':weight=0.8elifprefix=='f':weight=1.1else:# Flag an error condition if prefix not found.errormsg="Unknown prefix "+str(prefix)return(False,cexprtk.USRSymbolType.VARIABLE,0.0,errormsg)# Apply the weight to thevalue*=weight# Indicate success and return value to cexprtkreturn(True,cexprtk.USRSymbolType.VARIABLE,value,"")All that remains is to register the callback with an instance ofExpressionand to evaluate an expression. The expression to be evaluated is:(m_county_a - f_county_b)This should give a value of(0.8*82) - (1.1*76) = -18>>>st=cexprtk.Symbol_Table({})>>>e=cexprtk.Expression("(m_county_a - f_county_b)",st,callback)>>>e.value()-18.0Example: expressions that contain return statements to produce multiple valuesExprtk expressions can return multiple values the results these expressions can be accessed through theresults()method.The following example shows the result of adding a constant value to a vector containing numbers:>>>st=cexprtk.Symbol_Table({})>>>e=cexprtk.Expression("var v[3] := {1,2,3}; return [v+1];",st)>>>e.value()nan>>>e.results()[[2.0,3.0,4.0]]Note that expression has to be evaluated before calling theresults()method.The value accessed throughresults()can contain a mixture of strings, vectors and real values:>>>st=cexprtk.Symbol_Table({'c':3})>>>e=cexprtk.Expression("if(c>1){return ['bigger than one', c];} else { return ['not bigger than one',c];};",st)>>>e.value()nan>>>e.results()['bigger than one',3.0]>>>st.variables['c']=0.5>>>e.value()nan>>>e.results()['not bigger than one',0.5]API ReferenceFor information about expressions supported bycexprtkplease refer to the original C++ExprTKdocumentation:Class Referenceclass Expression:Class representing mathematical expression.Following instantiation, the expression is evaluated calling the expression or invoking itsvalue()method.The variable values used by the Expression can be modified through thevariablesproperty of theSymbol_Tableinstance associated with the expression. TheSymbol_Tablecan be accessed using theExpression.symbol_tableproperty.Defining unknown symbol-resolver:Theunknown_symbol_resolver_callbackargument  to theExpressionconstructor accepts a callable which is invoked  whenever a symbol (i.e. a
variable or a constant), is not found in theSymbol_Tablegiven by thesymbol_tableargument. Theunknown_symbol_resolver_callbackcan be
used to provide a value for the missing value or to set an error condition.The callable should have following signature:defcallback(symbol_name):...Wheresymbol_nameis a string identifying the missing symbol.The callable should return a tuple of the form:(HANDLED_FLAG,USR_SYMBOL_TYPE,SYMBOL_VALUE,ERROR_STRING)Where:HANDLED_FLAGis a boolean:Trueindicates that callback was able handle the error condition and thatSYMBOL_VALUEshould be used for the missing symbol.False, flags and error condition, the reason why the unknown symbol could not be resolved by the callback is described byERROR_STRING.USR_SYMBOL_TYPEgives type of symbol (constant or variable) that should be added to thesymbol_tablewhen unkown symbol is resolved. Value should be one of those given incexprtk.USRSymbolType. e.g.cexprtk.USRSymbolType.VARIABLEcexprtk.USRSymbolType.CONSTANTSYMBOL_VALUE, floating point value that should be used when resolving missing symbol.ERROR_STRINGwhenHANDLED_FLAGisFalsethis can be used to describe error condition.definit(self,expression,symbol_table,unknown_symbol_resolver_callback= None):InstantiateExpressionfrom a text string giving formula andSymbol_Tableinstance encapsulating variables and constants used by the expression.Parameters:expression(str) String giving expression to be calculated.symbol_table(Symbol_Table) Object defining variables and constants.unknown_symbol_resolver_callback(callable)  See description above.def results(self):If an expression contains areturn []statement, the returned values are accessed using this method.A python list is returned which may contain real values, strings or vectors.Note:the expression should be evaluated by callingvalue()before trying to access results.Returns:(list) List of values produced by expression'sreturnstatement.def value(self):Evaluate expression using variable values currently set within associatedSymbol_TableReturns:(float) Value resulting from evaluation of expression.defcall(self):Equivalent to callingvalue()method.Returns:(float) Value resulting from evaluation of expression.symbol_tableRead only property that returnsSymbol_Tableinstance associated with this expression.Returns:(Symbol_Table)Symbol_Tableassociated with thisExpression.class Symbol_Table:Class for providing variable and constant values toExpressioninstances.definit(self,variables,constants= {},add_constants= False, functions = {},string_variables= {}):InstantiateSymbol_Tabledefining variables and constants for use withExpressionclass.Example:To instantiate aSymbol_Tablewith:x = 1y = 5define a constantk = 1.3806488e-23The following code would be used:st=cexprtk.Symbol_Table({'x':1,'y':5},{'k'=1.3806488e-23})Parameters:variables(dict) Mapping between variable name and initial variable value.constants(dict) Dictionary containing values that should be added toSymbol_Tableas constants. These can be used a variables within expressions but their values cannot be updated followingSymbol_Tableinstantiation.add_constants(bool) IfTrue, add the standard constantspi,inf,epsilonto the 'constants' dictionary before populating theSymbol_Tablefunctions(dict) Dictionary containing custom functions to be made available to expressions. Dictionary keys specify function names and values should be functions.string_variables(dict) Mapping between variable name and initial variable value for string variables.variablesReturns dictionary like object containing variable values.Symbol_Tablevalues can be updated through this object.Example:>>>importcexprtk>>>st=cexprtk.Symbol_Table({'x':5,'y':5})>>>expression=cexprtk.Expression('x+y',st)>>>expression()10.0Update the value ofxin the symbol table and re-evaluate the expression:>>>expression.symbol_table.variables['x']=11.0>>>expression()16.0Returns:Dictionary like giving variables stored in thisSymbol_Table. Keys are variables names and these map to variable values.constantsProperty giving constants stored in thisSymbol_Table.Returns:Read-only dictionary like object mapping constant names stored inSymbol_Tableto their values.functionsReturns dictionary like object containing custom python functions to use in expressions.Returns:Dictionary like giving function stored in thisSymbol_Table. Keys are function names (as used inExpression) and these map to python callable objects including functions, functors, andfunctools.partial.string_variablesReturns dictionary like object containing string variable values.Symbol_Tablevalues can be updated through this object.Example:>>>importcexprtk>>>st=cexprtk.Symbol_Table({})>>>st.string_variables['s1']='he'>>>st.string_variables['s2']='l'>>>st.string_variables['s3']='lo'>>>expression=cexprtk.Expression("return[s1+s2+s3+' world']",st)>>>expression.value()nan>>>expression.results()['hello world']Returns:Dictionary like giving the string variables stored in thisSymbol_Table. Keys are variables names and these map to string values.class USRSymbolType:Defines constant values used to determine symbol type returned byunknown_symbol_resolver_callback(seeExpressionconstructor documentation for more).VARIABLEValue that should be returned by anunknown_symbol_resolver_callbackto define a variable.CONSTANTValue that should be returned by anunknown_symbol_resolver_callbackto define a constant.Utility Functionsdef check_expression (expression)Check that expression can be parsed. If successful do nothing, if unsuccessful raiseParseException.Parameters:expression(str) Formula to be evaluatedRaises:ParseException: If expression is invalid.def evaluate_expression (expression,variables)Evaluate a mathematical formula using the exprtk library and return result.For more information about supported functions and syntax see theexprtk C++ library website.Parameters:expression(str) Expression to be evaluated.variables(dict) Dictionary containing variable name, variable value pairs to be used in expression.Returns:(float): Evaluated expressionRaises:ParseException: ifexpressionis invalid.AuthorsCython wrapper by Michael Rushton (m.j.d.rushton@gmail.com), although most credit should go to Arash Partow for creating the underlyingExprTKlibrary.Thanks to:jciskeyfor adding theExpression.results()support.Caleb Hattinghfor getting cexprtk to build using MSVC on Windows.Licensecexprtkis released under the same terms as theExprTKlibrary theCommon Public License Version 1.0(CPL).