forked from gdurin/pyFitting
-
Notifications
You must be signed in to change notification settings - Fork 0
/
getAnalyticalDerivatives.py
82 lines (76 loc) · 2.55 KB
/
getAnalyticalDerivatives.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import sympy
# Mappings between sympy and numpy
NUMPY_TRANSLATIONS = {
'amax': 'max_',
'amin': 'min_',
'angle': 'arg',
'arccos': 'acos',
'arccosh': 'acosh',
'arcsin': 'asin',
'arcsinh': 'asinh',
'arctan': 'atan',
'arctan2': 'atan2',
'arctanh': 'atanh',
'ceil': 'ceiling',
'e': 'E',
'imag': 'im',
'inf': 'oo',
'log': 'ln',
'matrix': 'Matrix',
'real': 're'}
def getDiff(independentVars, function_string, varsDiff):
"""
This function makes the analytical derivative
of a "function(independentVars, varsDiff)" over variable(s) "varsDiff"
Returns a list of strings
Example:
f(x,a, b) = a*x**2+b*x
independentVars = ["x"]
function = "a*x**2+b*x"
varsDiff = ["a", "b"]
return ["2*x", "x"]
"""
diffs = []
# There is a problem if variables are not a list
independentVars = list(independentVars)
varsDiff = list(varsDiff)
# Define all the variables as sympy.Symbols
for v in independentVars + varsDiff:
sympy.var(v)
# Define the function "f" and change it into a sympy expression
checkFunction = True
while checkFunction:
try:
exec "f = %s" % (function_string)
checkFunction = False
except NameError as inst:
# find the function to be changed into a sympy expression
# and check if the name is different from numpy
op = inst.message.split("'")[1]
if op in NUMPY_TRANSLATIONS:
opNew = "sympy."+NUMPY_TRANSLATIONS[op]
elif op in dir(sympy):
opNew = "sympy."+ op
else:
print("Warning: %s does not exist in sympy" % op)
print("No analytical derivatives are used")
return None
function_string = function_string.replace(op, opNew)
# Do the loop over the variables varsDiff
for variableToDiff in varsDiff:
exec "derivative = sympy.diff(f,%s)" % variableToDiff
derivative = str(derivative)
# We must check if the derivative is not a constant,
# as it can give problems with the jacobian
# i.e. must have the same lenght of 'x' data
for var in independentVars:
if var not in derivative:
derivative = "%s*%s/%s" % (derivative, var, var)
diffs.append(derivative)
return diffs
if __name__ == "__main__":
f = "b1*gamma(x/b4)+b2/x**b3"
derivList = "b1,b2,b3,b4".split(",")
derivs = getDiff("x",f, derivList)
for d in derivs:
print d