derivative-utils 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- derivative_utils-0.1.0/PKG-INFO +10 -0
- derivative_utils-0.1.0/README.md +3 -0
- derivative_utils-0.1.0/pyproject.toml +7 -0
- derivative_utils-0.1.0/setup.cfg +4 -0
- derivative_utils-0.1.0/src/__init__.py +28 -0
- derivative_utils-0.1.0/src/const.py +2 -0
- derivative_utils-0.1.0/src/dat.py +16 -0
- derivative_utils-0.1.0/src/derivative_utils.egg-info/PKG-INFO +10 -0
- derivative_utils-0.1.0/src/derivative_utils.egg-info/SOURCES.txt +13 -0
- derivative_utils-0.1.0/src/derivative_utils.egg-info/dependency_links.txt +1 -0
- derivative_utils-0.1.0/src/derivative_utils.egg-info/top_level.txt +7 -0
- derivative_utils-0.1.0/src/exceptions.py +2 -0
- derivative_utils-0.1.0/src/expressions.py +152 -0
- derivative_utils-0.1.0/src/func.py +47 -0
- derivative_utils-0.1.0/src/util.py +14 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: derivative-utils
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: [alpha] Tools for computing and working with derivatives of functions.
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# derivative-utils [alpha]
|
|
9
|
+
A simple package for working with derivatives.
|
|
10
|
+
This is in alpha, and may not work as intended.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from expressions import *
|
|
2
|
+
from dat import *
|
|
3
|
+
def differentiate(func):
|
|
4
|
+
if type(func) == MainVariable: return Number(1)
|
|
5
|
+
elif type(func) == Quotient:
|
|
6
|
+
return Quotient(Difference(Product(differentiate(func.a), func.b),Product(differentiate(func.b), func.a)),Exponent(func.b,2))
|
|
7
|
+
elif type(func) == Product:
|
|
8
|
+
if type(func.a) != Number and type(func.a) != Number: return Sum(Product(differentiate(func.a), func.b),Product(differentiate(func.b), func.a))
|
|
9
|
+
elif type(func.a) != Number: return Product(differentiate(func.a), func.b)
|
|
10
|
+
elif type(func.b) != Number: return Product(differentiate(func.b), func.a)
|
|
11
|
+
elif type(func) == Sum: return Sum(differentiate(func.a), differentiate(func.b))
|
|
12
|
+
elif type(func) == Difference: return Difference(differentiate(func.a), differentiate(func.b))
|
|
13
|
+
elif type(func) == Exponent:
|
|
14
|
+
if type(func.x) != Number and type(func.exp) != Number:
|
|
15
|
+
return differentiate(Exponent())
|
|
16
|
+
elif type(func.x) != Number: return simplify(Product(differentiate(func.x), Product(func.exp, Exponent(func.x, func.exp - 1))))
|
|
17
|
+
elif type(func.exp) != Number: return simplify(Product(StdFunction("ln").eval(func.x), Product(differentiate(func.exp), func)))
|
|
18
|
+
else: return Number(0)
|
|
19
|
+
elif type(func) == StdFunction:
|
|
20
|
+
return simplify(Product(differentiate(func.val), func.derivative(func.val)))
|
|
21
|
+
elif type(func) == MainVariable:
|
|
22
|
+
return Number(1)
|
|
23
|
+
elif type(func) == Number: return Number(0)
|
|
24
|
+
elif type(func) == Polynomial:
|
|
25
|
+
coeff = func.coeff[:]
|
|
26
|
+
coeff.pop()
|
|
27
|
+
coeff = [c*(len(coeff)-i) for i,c in enumerate(coeff)]
|
|
28
|
+
return Polynomial(coeff)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import json
|
|
2
|
+
class Table:
|
|
3
|
+
def __init__(self, x, y):
|
|
4
|
+
self.x = x
|
|
5
|
+
self.y = y
|
|
6
|
+
def display(self):
|
|
7
|
+
pass
|
|
8
|
+
def json(self):
|
|
9
|
+
return json.dumps({"x":self.x, "y": self.y})
|
|
10
|
+
def obj(self):
|
|
11
|
+
return {"x":self.x, "y": self.y}
|
|
12
|
+
def table(expression, xL:list):
|
|
13
|
+
yL = []
|
|
14
|
+
for x in xL:
|
|
15
|
+
yL.append(expression.eval(x))
|
|
16
|
+
return Table(xL, yL)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: derivative-utils
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: [alpha] Tools for computing and working with derivatives of functions.
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# derivative-utils [alpha]
|
|
9
|
+
A simple package for working with derivatives.
|
|
10
|
+
This is in alpha, and may not work as intended.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/__init__.py
|
|
4
|
+
src/const.py
|
|
5
|
+
src/dat.py
|
|
6
|
+
src/exceptions.py
|
|
7
|
+
src/expressions.py
|
|
8
|
+
src/func.py
|
|
9
|
+
src/util.py
|
|
10
|
+
src/derivative_utils.egg-info/PKG-INFO
|
|
11
|
+
src/derivative_utils.egg-info/SOURCES.txt
|
|
12
|
+
src/derivative_utils.egg-info/dependency_links.txt
|
|
13
|
+
src/derivative_utils.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
import exceptions
|
|
3
|
+
from func import *
|
|
4
|
+
class MathExpression:
|
|
5
|
+
def __init__(self, value):
|
|
6
|
+
self.value = value
|
|
7
|
+
def __str__(self):
|
|
8
|
+
return str(self.value)
|
|
9
|
+
def eval(self, val):
|
|
10
|
+
if type(val) != Number:
|
|
11
|
+
val = Number(val)
|
|
12
|
+
return self.value.eval(val)
|
|
13
|
+
class Number:
|
|
14
|
+
def __init__(self, value):
|
|
15
|
+
if type(value) != Decimal: value = Decimal(value)
|
|
16
|
+
self.value = value
|
|
17
|
+
def __str__(self):
|
|
18
|
+
return str(self.value)
|
|
19
|
+
def __sub__(self, n):
|
|
20
|
+
return Number(self.value-n)
|
|
21
|
+
def __add__(self, n):
|
|
22
|
+
return Number(self.value+n)
|
|
23
|
+
def eval(self, val=0):
|
|
24
|
+
return self.value
|
|
25
|
+
class Product:
|
|
26
|
+
def __init__(self, a, b):
|
|
27
|
+
if type(a) == int or type(a) == float or type(a) == Decimal:
|
|
28
|
+
a = Number(a)
|
|
29
|
+
if type(b) == int or type(b) == float or type(b) == Decimal:
|
|
30
|
+
b = Number(b)
|
|
31
|
+
if (a == None): self.a = Number(1)
|
|
32
|
+
if (b == None): self.b = Number(1)
|
|
33
|
+
self.a = a
|
|
34
|
+
self.b = b
|
|
35
|
+
def __str__(self): return f"{self.a}*{self.b}"
|
|
36
|
+
def eval(self, val):
|
|
37
|
+
if type(val) != Number: val = Number(val)
|
|
38
|
+
return self.a.eval(val) * self.b.eval(val)
|
|
39
|
+
class Quotient:
|
|
40
|
+
def __init__(self, a, b):
|
|
41
|
+
if type(a) == int or type(a) == float or type(a) == Decimal:
|
|
42
|
+
a = Number(a)
|
|
43
|
+
if type(b) == int or type(b) == float or type(b) == Decimal:
|
|
44
|
+
b = Number(b)
|
|
45
|
+
self.a = a
|
|
46
|
+
self.b = b
|
|
47
|
+
def __str__(self): return f"{self.a}/{self.b}"
|
|
48
|
+
def eval(self, val):
|
|
49
|
+
if type(val) != Number:
|
|
50
|
+
val = Number(val)
|
|
51
|
+
return self.a.eval(val) / self.b.eval(val)
|
|
52
|
+
class Sum:
|
|
53
|
+
def __init__(self, a, b):
|
|
54
|
+
if type(a) == int or type(a) == float or type(a) == Decimal:
|
|
55
|
+
a = Number(a)
|
|
56
|
+
if type(b) == int or type(b) == float or type(b) == Decimal:
|
|
57
|
+
b = Number(b)
|
|
58
|
+
self.a = a
|
|
59
|
+
self.b = b
|
|
60
|
+
def __str__(self): return f"({self.a}+{self.b})"
|
|
61
|
+
def eval(self, val):
|
|
62
|
+
if type(val) != Number:
|
|
63
|
+
val = Number(val)
|
|
64
|
+
return self.a.eval(val) + self.b.eval(val)
|
|
65
|
+
class Exponent:
|
|
66
|
+
def __init__(self, x, exp):
|
|
67
|
+
if type(x) == int or type(x) == float or type(x) == Decimal:
|
|
68
|
+
x = Number(x)
|
|
69
|
+
if type(exp) == int or type(exp) == float or type(exp) == Decimal:
|
|
70
|
+
exp = Number(exp)
|
|
71
|
+
self.x = x
|
|
72
|
+
self.exp = exp
|
|
73
|
+
def __str__(self): return f"({self.x})^({self.exp})"
|
|
74
|
+
def eval(self, val):
|
|
75
|
+
if type(val) != Number:
|
|
76
|
+
val = Number(val)
|
|
77
|
+
return self.x.eval(val) ** self.exp.eval(val)
|
|
78
|
+
class MainVariable:
|
|
79
|
+
def eval(self, val):
|
|
80
|
+
if type(val) != Number:
|
|
81
|
+
val = Number(val)
|
|
82
|
+
return val.eval()
|
|
83
|
+
def __str__(self): return "x"
|
|
84
|
+
class Polynomial(MathExpression):
|
|
85
|
+
def __init__(self, coefficients):
|
|
86
|
+
self.coeff = coefficients
|
|
87
|
+
def eval(self, x):
|
|
88
|
+
return sum([self.coeff[i]*x**(len(self.coeff-1-i)) for i in range(len(self.coeff))])
|
|
89
|
+
def __str__(self):
|
|
90
|
+
"+".join([f"{c}x^{len(self.coeff)-i-1}"] for i, c in enumerate(self.coeff))
|
|
91
|
+
class Difference:
|
|
92
|
+
def __init__(self, a, b):
|
|
93
|
+
if type(a) == int or type(a) == float or type(a) == Decimal:
|
|
94
|
+
a = Number(a)
|
|
95
|
+
if type(b) == int or type(b) == float or type(b) == Decimal:
|
|
96
|
+
b = Number(b)
|
|
97
|
+
self.a = a
|
|
98
|
+
self.b = b
|
|
99
|
+
def __str__(self): return f"({self.a}-{self.b})"
|
|
100
|
+
def eval(self, val):
|
|
101
|
+
if type(val) != Number:
|
|
102
|
+
val = Number(val)
|
|
103
|
+
return self.a.eval(val) - self.b.eval(val)
|
|
104
|
+
class StdFunction():
|
|
105
|
+
def __init__(self, ftype, val):
|
|
106
|
+
self.ftype = ftype
|
|
107
|
+
self.val = val
|
|
108
|
+
if ftype == "cos":
|
|
109
|
+
self.derivative = lambda argument: Product(-1, StdFunction("sin", argument, False))
|
|
110
|
+
elif ftype == "sin":
|
|
111
|
+
self.derivative = lambda argument: StdFunction("cos", argument, False)
|
|
112
|
+
elif ftype == "tan":
|
|
113
|
+
self.derivative = lambda argument: Quotient(1, Exponent(StdFunction("cos", argument, False), 2)) #replace with sec^2
|
|
114
|
+
elif ftype == "arccos":
|
|
115
|
+
self.derivative = lambda argument: Quotient(-1, Exponent(Difference(1,Exponent(argument,2)),Number(1/2)))
|
|
116
|
+
elif ftype == "arcsin":
|
|
117
|
+
self.derivative = lambda argument: Quotient(-1, Exponent(Difference(1, Exponent(argument,2)),Number(1/2)))
|
|
118
|
+
elif ftype == "arctan":
|
|
119
|
+
self.derivative = lambda argument: Quotient(1, Sum(1, Exponent(argument,2)))
|
|
120
|
+
elif ftype == "ln":
|
|
121
|
+
self.derivative = lambda argument: Exponent(argument, -1)
|
|
122
|
+
else:
|
|
123
|
+
raise(exceptions.UnknownStdFunc)
|
|
124
|
+
def __str__(self):
|
|
125
|
+
return f"{self.ftype}({self.val})"
|
|
126
|
+
def eval(self, x):
|
|
127
|
+
if self.ftype == "cos":
|
|
128
|
+
return cos(x)
|
|
129
|
+
elif self.ftype == "sin":
|
|
130
|
+
return sin(x)
|
|
131
|
+
elif self.ftype == "tan":
|
|
132
|
+
return tan(x)
|
|
133
|
+
elif self.ftype == "sec":
|
|
134
|
+
return sec(x)
|
|
135
|
+
elif self.ftype == "csc":
|
|
136
|
+
return csc(x)
|
|
137
|
+
elif self.ftype == "cot":
|
|
138
|
+
return cot(x)
|
|
139
|
+
elif self.ftype == "ln":
|
|
140
|
+
return ln(x)
|
|
141
|
+
def simplify(exp):
|
|
142
|
+
if type(exp) == MathExpression: return simplify(exp.value)
|
|
143
|
+
elif type(exp) == Product:
|
|
144
|
+
if type(exp.a) == Number and exp.a.value == 1: return simplify(exp.b) #fix this
|
|
145
|
+
elif type(exp.b) == Number and exp.b.value == 1: return simplify(exp.a)
|
|
146
|
+
elif type(exp.a) == Number and exp.a.value == 0: return Number(0)
|
|
147
|
+
elif type(exp.b) == Number and exp.b.value == 0: return Number(0)
|
|
148
|
+
elif type(exp) == Quotient:
|
|
149
|
+
if exp.b == Number(1): return simplify(exp.a)
|
|
150
|
+
elif type(exp.b) == Quotient:
|
|
151
|
+
exp = Product(exp.a, Quotient(exp.b.b, exp.b.a))
|
|
152
|
+
return exp
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from util import *
|
|
2
|
+
from const import *
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from expressions import *
|
|
5
|
+
def cos(x, terms=100, places=12):
|
|
6
|
+
o = 0
|
|
7
|
+
x = x % (2*pi)
|
|
8
|
+
multiplier = 1
|
|
9
|
+
if x > pi:
|
|
10
|
+
x = x - pi
|
|
11
|
+
multiplier = -1
|
|
12
|
+
for i in range(terms):
|
|
13
|
+
c = [1, 0, -1, 0][i % 4]
|
|
14
|
+
o += Decimal(c*x**i)/Decimal(factorial(i))
|
|
15
|
+
return round(multiplier*o,places)
|
|
16
|
+
def sin(x, terms=100, places=12):
|
|
17
|
+
o = 0
|
|
18
|
+
x = (x + pi/2) % (2*pi) - pi/2
|
|
19
|
+
for i in range(terms):
|
|
20
|
+
c = [0, 1, 0, -1][i % 4]
|
|
21
|
+
o += (c*x**i)/factorial(i)
|
|
22
|
+
return round(o,places)
|
|
23
|
+
def tan(x, terms=100):
|
|
24
|
+
try: return sin(x, terms)/cos(x, terms)
|
|
25
|
+
except ZeroDivisionError: pass
|
|
26
|
+
def sec(x, terms=100):
|
|
27
|
+
v = cos(x, terms)
|
|
28
|
+
if v == 0: return
|
|
29
|
+
else: return 1/v
|
|
30
|
+
def csc(x, terms=100):
|
|
31
|
+
v = sin(x, terms)
|
|
32
|
+
if v == 0: return
|
|
33
|
+
else: return 1/v
|
|
34
|
+
def cot(x, terms=100):
|
|
35
|
+
try: return cos(x, terms)/sin(x, terms)
|
|
36
|
+
except ZeroDivisionError: pass
|
|
37
|
+
def exp(x, terms=100):
|
|
38
|
+
o = 0
|
|
39
|
+
if type(x) == Number: x = x.eval()
|
|
40
|
+
for i in range(terms):
|
|
41
|
+
o += x**i/factorial(i)
|
|
42
|
+
return o
|
|
43
|
+
def ln(x, prec=0.000001):
|
|
44
|
+
guess = 0
|
|
45
|
+
while abs(exp(guess) - x) > prec:
|
|
46
|
+
guess -= (exp(guess) - x)/exp(guess)
|
|
47
|
+
return guess
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from expressions import *
|
|
2
|
+
from __init__ import differentiate
|
|
3
|
+
def factorial(n):
|
|
4
|
+
o = 1
|
|
5
|
+
if n == 0:
|
|
6
|
+
return o
|
|
7
|
+
for i in [t+1 for t in range(n)]:
|
|
8
|
+
o*= i
|
|
9
|
+
return o
|
|
10
|
+
def newtonMethod(function:MathExpression, prec=0.01, maxTries=1000):
|
|
11
|
+
guess = 0
|
|
12
|
+
tries = 0
|
|
13
|
+
while abs(function.eval(guess)) > prec and tries < maxTries:
|
|
14
|
+
guess -= function.eval(guess)/differentiate(function).eval(guess)
|