Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
trs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
trs
Commits
5cf274a2
Commit
5cf274a2
authored
Mar 15, 2012
by
Taddeus Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented sum rule, product rule and quotient rule.
parent
0f16cb2c
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
190 additions
and
18 deletions
+190
-18
src/rules/__init__.py
src/rules/__init__.py
+3
-2
src/rules/derivatives.py
src/rules/derivatives.py
+116
-15
tests/test_rules_derivatives.py
tests/test_rules_derivatives.py
+71
-1
No files found.
src/rules/__init__.py
View file @
5cf274a2
...
@@ -20,7 +20,7 @@ from .goniometry import match_add_quadrants, match_negated_parameter, \
...
@@ -20,7 +20,7 @@ from .goniometry import match_add_quadrants, match_negated_parameter, \
from
src.rules.derivatives
import
match_zero_derivative
,
\
from
src.rules.derivatives
import
match_zero_derivative
,
\
match_one_derivative
,
match_variable_power
,
\
match_one_derivative
,
match_variable_power
,
\
match_const_deriv_multiplication
,
match_logarithmic
,
\
match_const_deriv_multiplication
,
match_logarithmic
,
\
match_goniometric
match_goniometric
,
match_sum_product_rule
,
match_quotient_rule
RULES
=
{
RULES
=
{
OP_ADD
:
[
match_add_numerics
,
match_add_constant_fractions
,
OP_ADD
:
[
match_add_numerics
,
match_add_constant_fractions
,
...
@@ -44,5 +44,6 @@ RULES = {
...
@@ -44,5 +44,6 @@ RULES = {
OP_TAN
:
[
match_standard_radian
],
OP_TAN
:
[
match_standard_radian
],
OP_DER
:
[
match_zero_derivative
,
match_one_derivative
,
OP_DER
:
[
match_zero_derivative
,
match_one_derivative
,
match_variable_power
,
match_const_deriv_multiplication
,
match_variable_power
,
match_const_deriv_multiplication
,
match_logarithmic
,
match_goniometric
],
match_logarithmic
,
match_goniometric
,
match_sum_product_rule
,
match_quotient_rule
],
}
}
src/rules/derivatives.py
View file @
5cf274a2
...
@@ -4,7 +4,7 @@ from .utils import find_variables
...
@@ -4,7 +4,7 @@ from .utils import find_variables
from
.logarithmic
import
ln
from
.logarithmic
import
ln
from
.goniometry
import
sin
,
cos
from
.goniometry
import
sin
,
cos
from
..node
import
ExpressionNode
as
N
,
ExpressionLeaf
as
L
,
Scope
,
OP_DER
,
\
from
..node
import
ExpressionNode
as
N
,
ExpressionLeaf
as
L
,
Scope
,
OP_DER
,
\
OP_MUL
,
OP_LOG
,
OP_SIN
,
OP_COS
,
OP_TAN
OP_MUL
,
OP_LOG
,
OP_SIN
,
OP_COS
,
OP_TAN
,
OP_ADD
,
OP_DIV
from
..possibilities
import
Possibility
as
P
,
MESSAGES
from
..possibilities
import
Possibility
as
P
,
MESSAGES
from
..translate
import
_
from
..translate
import
_
...
@@ -13,6 +13,13 @@ def der(f, x=None):
...
@@ -13,6 +13,13 @@ def der(f, x=None):
return
N
(
'der'
,
f
,
x
)
if
x
else
N
(
'der'
,
f
)
return
N
(
'der'
,
f
,
x
)
if
x
else
N
(
'der'
,
f
)
def
second_arg
(
node
):
"""
Get the second child of a node if it exists, None otherwise.
"""
return
node
[
1
]
if
len
(
node
)
>
1
else
None
def
get_derivation_variable
(
node
,
variables
=
None
):
def
get_derivation_variable
(
node
,
variables
=
None
):
"""
"""
Find the variable to derive over.
Find the variable to derive over.
...
@@ -70,6 +77,17 @@ def match_zero_derivative(node):
...
@@ -70,6 +77,17 @@ def match_zero_derivative(node):
return
[]
return
[]
def
zero_derivative
(
root
,
args
):
"""
der(x, y) -> 0
der(n) -> 0
"""
return
L
(
0
)
MESSAGES
[
zero_derivative
]
=
_
(
'Constant {0[0]} has derivative 0.'
)
def
match_one_derivative
(
node
):
def
match_one_derivative
(
node
):
"""
"""
der(x) -> 1 # Implicit x
der(x) -> 1 # Implicit x
...
@@ -96,17 +114,6 @@ def one_derivative(root, args):
...
@@ -96,17 +114,6 @@ def one_derivative(root, args):
MESSAGES
[
one_derivative
]
=
_
(
'Variable {0[0]} has derivative 1.'
)
MESSAGES
[
one_derivative
]
=
_
(
'Variable {0[0]} has derivative 1.'
)
def
zero_derivative
(
root
,
args
):
"""
der(x, y) -> 0
der(n) -> 0
"""
return
L
(
0
)
MESSAGES
[
zero_derivative
]
=
_
(
'Constant {0[0]} has derivative 0.'
)
def
match_const_deriv_multiplication
(
node
):
def
match_const_deriv_multiplication
(
node
):
"""
"""
der(c * f(x), x) -> c * der(f(x), x)
der(c * f(x), x) -> c * der(f(x), x)
...
@@ -293,11 +300,105 @@ def tangens(root, args):
...
@@ -293,11 +300,105 @@ def tangens(root, args):
"""
"""
der(tan(x), x) -> der(sin(x) / cos(x), x)
der(tan(x), x) -> der(sin(x) / cos(x), x)
"""
"""
f
=
root
[
0
][
0
]
x
=
root
[
0
][
0
]
x
=
root
[
1
]
if
len
(
root
)
>
1
else
None
return
der
(
sin
(
f
)
/
cos
(
f
),
x
)
return
der
(
sin
(
x
)
/
cos
(
x
),
second_arg
(
root
)
)
MESSAGES
[
tangens
]
=
\
MESSAGES
[
tangens
]
=
\
_
(
'Convert the tanges to a division and apply the product rule.'
)
_
(
'Convert the tanges to a division and apply the product rule.'
)
def
match_sum_product_rule
(
node
):
"""
[f(x) + g(x)]' -> f'(x) + g'(x)
[f(x) * g(x)]' -> f'(x) * g(x) + f(x) * g'(x)
"""
assert
node
.
is_op
(
OP_DER
)
x
=
get_derivation_variable
(
node
)
if
not
x
or
node
[
0
].
is_leaf
or
node
[
0
].
op
not
in
(
OP_ADD
,
OP_MUL
):
return
[]
scope
=
Scope
(
node
[
0
])
x
=
L
(
x
)
functions
=
[
n
for
n
in
scope
if
n
.
contains
(
x
)]
if
len
(
functions
)
<
2
:
return
[]
p
=
[]
handler
=
sum_rule
if
node
[
0
].
op
==
OP_ADD
else
product_rule
for
f
in
functions
:
p
.
append
(
P
(
node
,
handler
,
(
scope
,
f
)))
return
p
def
sum_rule
(
root
,
args
):
"""
[f(x) + g(x)]' -> f'(x) + g'(x)
"""
scope
,
f
=
args
x
=
second_arg
(
root
)
scope
.
remove
(
f
)
return
der
(
f
,
x
)
+
der
(
scope
.
as_nary_node
(),
x
)
MESSAGES
[
sum_rule
]
=
_
(
'Apply the sum rule to {0}.'
)
def
product_rule
(
root
,
args
):
"""
[f(x) * g(x)]' -> f'(x) * g(x) + f(x) * g'(x)
Note that implicitely:
[f(x) * g(x) * h(x)]' -> f'(x) * (g(x) * h(x)) + f(x) * [g(x) * h(x)]'
"""
scope
,
f
=
args
x
=
second_arg
(
root
)
scope
.
remove
(
f
)
gh
=
scope
.
as_nary_node
()
return
der
(
f
,
x
)
*
gh
+
f
*
der
(
gh
,
x
)
MESSAGES
[
product_rule
]
=
_
(
'Apply the product rule to {0}.'
)
def
match_quotient_rule
(
node
):
"""
[f(x) / g(x)]' -> (f'(x) * g(x) - f(x) * g'(x)) / g(x) ^ 2
"""
assert
node
.
is_op
(
OP_DER
)
x
=
get_derivation_variable
(
node
)
if
not
x
or
not
node
[
0
].
is_op
(
OP_DIV
):
return
[]
f
,
g
=
node
[
0
]
x
=
L
(
x
)
if
f
.
contains
(
x
)
and
g
.
contains
(
x
):
return
[
P
(
node
,
quotient_rule
)]
return
[]
def
quotient_rule
(
root
,
args
):
"""
[f(x) / g(x)]' -> (f'(x) * g(x) - f(x) * g'(x)) / g(x) ^ 2
"""
f
,
g
=
root
[
0
]
x
=
second_arg
(
root
)
return
(
der
(
f
,
x
)
*
g
-
f
*
der
(
g
,
x
))
/
g
**
2
MESSAGES
[
quotient_rule
]
=
_
(
'Apply the quotient rule to {0}.'
)
tests/test_rules_derivatives.py
View file @
5cf274a2
...
@@ -3,7 +3,9 @@ from src.rules.derivatives import der, get_derivation_variable, \
...
@@ -3,7 +3,9 @@ from src.rules.derivatives import der, get_derivation_variable, \
zero_derivative
,
match_variable_power
,
variable_root
,
\
zero_derivative
,
match_variable_power
,
variable_root
,
\
variable_exponent
,
match_const_deriv_multiplication
,
\
variable_exponent
,
match_const_deriv_multiplication
,
\
const_deriv_multiplication
,
chain_rule
,
match_logarithmic
,
\
const_deriv_multiplication
,
chain_rule
,
match_logarithmic
,
\
logarithmic
,
match_goniometric
,
sinus
,
cosinus
,
tangens
logarithmic
,
match_goniometric
,
sinus
,
cosinus
,
tangens
,
\
match_sum_product_rule
,
sum_rule
,
product_rule
,
match_quotient_rule
,
\
quotient_rule
from
src.rules.logarithmic
import
ln
from
src.rules.logarithmic
import
ln
from
src.rules.goniometry
import
sin
,
cos
from
src.rules.goniometry
import
sin
,
cos
from
src.node
import
Scope
from
src.node
import
Scope
...
@@ -158,3 +160,71 @@ class TestRulesDerivatives(RulesTestCase):
...
@@ -158,3 +160,71 @@ class TestRulesDerivatives(RulesTestCase):
root
=
tree
(
'der(tan(x))'
)
root
=
tree
(
'der(tan(x))'
)
self
.
assertEqual
(
tangens
(
root
,
()),
der
(
sin
(
x
)
/
cos
(
x
)))
self
.
assertEqual
(
tangens
(
root
,
()),
der
(
sin
(
x
)
/
cos
(
x
)))
def
test_match_sum_product_rule_sum
(
self
):
root
=
tree
(
'der(x ^ 2 + x)'
)
x2
,
x
=
f
=
root
[
0
]
self
.
assertEqualPos
(
match_sum_product_rule
(
root
),
[
P
(
root
,
sum_rule
,
(
Scope
(
f
),
x2
)),
P
(
root
,
sum_rule
,
(
Scope
(
f
),
x
))])
root
=
tree
(
'der(x ^ 2 + 3 + x)'
)
self
.
assertEqualPos
(
match_sum_product_rule
(
root
),
[
P
(
root
,
sum_rule
,
(
Scope
(
root
[
0
]),
x2
)),
P
(
root
,
sum_rule
,
(
Scope
(
root
[
0
]),
x
))])
def
test_match_sum_product_rule_product
(
self
):
root
=
tree
(
'der(x ^ 2 * x)'
)
x2
,
x
=
f
=
root
[
0
]
self
.
assertEqualPos
(
match_sum_product_rule
(
root
),
[
P
(
root
,
product_rule
,
(
Scope
(
f
),
x2
)),
P
(
root
,
product_rule
,
(
Scope
(
f
),
x
))])
def
test_match_sum_product_rule_none
(
self
):
root
=
tree
(
'der(x ^ 2 + 2)'
)
self
.
assertEqualPos
(
match_sum_product_rule
(
root
),
[])
root
=
tree
(
'der(x ^ 2 * 2)'
)
self
.
assertEqualPos
(
match_sum_product_rule
(
root
),
[])
def
test_sum_rule
(
self
):
root
=
tree
(
'der(x ^ 2 + x)'
)
x2
,
x
=
f
=
root
[
0
]
self
.
assertEqual
(
sum_rule
(
root
,
(
Scope
(
f
),
x2
)),
der
(
x2
)
+
der
(
x
))
self
.
assertEqual
(
sum_rule
(
root
,
(
Scope
(
f
),
x
)),
der
(
x
)
+
der
(
x2
))
root
=
tree
(
'der(x ^ 2 + 3 + x)'
)
(
x2
,
l3
),
x
=
f
=
root
[
0
]
self
.
assertEqual
(
sum_rule
(
root
,
(
Scope
(
f
),
x2
)),
der
(
x2
)
+
der
(
l3
+
x
))
self
.
assertEqual
(
sum_rule
(
root
,
(
Scope
(
f
),
x
)),
der
(
x
)
+
der
(
x2
+
l3
))
def
test_product_rule
(
self
):
root
=
tree
(
'der(x ^ 2 * x)'
)
x2
,
x
=
f
=
root
[
0
]
self
.
assertEqual
(
product_rule
(
root
,
(
Scope
(
f
),
x2
)),
der
(
x2
)
*
x
+
x2
*
der
(
x
))
self
.
assertEqual
(
product_rule
(
root
,
(
Scope
(
f
),
x
)),
der
(
x
)
*
x2
+
x
*
der
(
x2
))
root
=
tree
(
'der(x ^ 2 * x * x ^ 3)'
)
(
x2
,
x
),
x3
=
f
=
root
[
0
]
self
.
assertEqual
(
product_rule
(
root
,
(
Scope
(
f
),
x2
)),
der
(
x2
)
*
(
x
*
x3
)
+
x2
*
der
(
x
*
x3
))
self
.
assertEqual
(
product_rule
(
root
,
(
Scope
(
f
),
x
)),
der
(
x
)
*
(
x2
*
x3
)
+
x
*
der
(
x2
*
x3
))
self
.
assertEqual
(
product_rule
(
root
,
(
Scope
(
f
),
x3
)),
der
(
x3
)
*
(
x2
*
x
)
+
x3
*
der
(
x2
*
x
))
def
test_match_quotient_rule
(
self
):
root
=
tree
(
'der(x ^ 2 / x)'
)
self
.
assertEqualPos
(
match_quotient_rule
(
root
),
[
P
(
root
,
quotient_rule
)])
root
=
tree
(
'der(x ^ 2 / 2)'
)
self
.
assertEqualPos
(
match_quotient_rule
(
root
),
[])
def
test_quotient_rule
(
self
):
root
=
tree
(
'der(x ^ 2 / x)'
)
f
,
g
=
root
[
0
]
self
.
assertEqual
(
quotient_rule
(
root
,
()),
(
der
(
f
)
*
g
-
f
*
der
(
g
))
/
g
**
2
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment