Commit 0f16cb2c authored by Taddeus Kroes's avatar Taddeus Kroes

Implemented last of the standard derivatives.

parent 48a85822
...@@ -19,7 +19,8 @@ from .goniometry import match_add_quadrants, match_negated_parameter, \ ...@@ -19,7 +19,8 @@ from .goniometry import match_add_quadrants, match_negated_parameter, \
match_half_pi_subtraction, match_standard_radian match_half_pi_subtraction, match_standard_radian
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_logarithm match_const_deriv_multiplication, match_logarithmic, \
match_goniometric
RULES = { RULES = {
OP_ADD: [match_add_numerics, match_add_constant_fractions, OP_ADD: [match_add_numerics, match_add_constant_fractions,
...@@ -43,5 +44,5 @@ RULES = { ...@@ -43,5 +44,5 @@ 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_logarithm], match_logarithmic, match_goniometric],
} }
...@@ -2,8 +2,9 @@ from itertools import combinations ...@@ -2,8 +2,9 @@ from itertools import combinations
from .utils import find_variables from .utils import find_variables
from .logarithmic import ln from .logarithmic import ln
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_MUL, OP_LOG, OP_SIN, OP_COS, OP_TAN
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
...@@ -201,7 +202,7 @@ MESSAGES[variable_exponent] = \ ...@@ -201,7 +202,7 @@ MESSAGES[variable_exponent] = \
_('Apply standard derivative d/dx g ^ x = g ^ x * ln g.') _('Apply standard derivative d/dx g ^ x = g ^ x * ln g.')
def match_logarithm(node): def match_logarithmic(node):
""" """
der(log(x, g), x) -> 1 / (x * ln(g)) der(log(x, g), x) -> 1 / (x * ln(g))
der(log(f(x), g), x) -> 1 / (f(x) * ln(g)) * der(f(x), x) der(log(f(x), g), x) -> 1 / (f(x) * ln(g)) * der(f(x), x)
...@@ -215,15 +216,15 @@ def match_logarithm(node): ...@@ -215,15 +216,15 @@ def match_logarithm(node):
x = L(x) x = L(x)
if f == x: if f == x:
return [P(node, logarithm, ())] return [P(node, logarithmic, ())]
if f.contains(x): if f.contains(x):
return [P(node, chain_rule, (f, logarithm, ()))] return [P(node, chain_rule, (f, logarithmic, ()))]
return [] return []
def logarithm(root, args): def logarithmic(root, args):
""" """
der(log(x, g), x) -> 1 / (x * ln(g)) der(log(x, g), x) -> 1 / (x * ln(g))
""" """
...@@ -232,5 +233,71 @@ def logarithm(root, args): ...@@ -232,5 +233,71 @@ def logarithm(root, args):
return L(1) / (x * ln(g)) return L(1) / (x * ln(g))
MESSAGES[logarithm] = \ MESSAGES[logarithmic] = \
_('Apply standard derivative d/dx log(x, g) = 1 / (x * ln(g)).') _('Apply standard derivative d/dx log(x, g) = 1 / (x * ln(g)).')
def match_goniometric(node):
"""
der(sin(x), x) -> cos(x)
der(sin(f(x)), x) -> cos(f(x)) * der(f(x), x)
der(cos(x), x) -> -sin(x)
der(cos(f(x)), x) -> -sin(f(x)) * der(f(x), x)
der(tan(x), x) -> der(sin(x) / cos(x), x)
"""
assert node.is_op(OP_DER)
x = get_derivation_variable(node)
if x and not node[0].is_leaf:
op = node[0].op
if op in (OP_SIN, OP_COS):
f = node[0][0]
x = L(x)
handler = sinus if op == OP_SIN else cosinus
if f == x:
return [P(node, handler)]
if f.contains(x):
return [P(node, chain_rule, (f, handler, ()))]
if op == OP_TAN:
return [P(node, tangens)]
return []
def sinus(root, args):
"""
der(sin(x), x) -> cos(x)
"""
return cos(root[0][0])
MESSAGES[sinus] = _('Apply standard derivative d/dx sin(x) = cos(x).')
def cosinus(root, args):
"""
der(cos(x), x) -> -sin(x)
"""
return -sin(root[0][0])
MESSAGES[cosinus] = _('Apply standard derivative d/dx cos(x) = -sin(x).')
def tangens(root, args):
"""
der(tan(x), x) -> der(sin(x) / cos(x), x)
"""
f = root[0][0]
x = root[1] if len(root) > 1 else None
return der(sin(f) / cos(f), x)
MESSAGES[tangens] = \
_('Convert the tanges to a division and apply the product rule.')
...@@ -2,8 +2,10 @@ from src.rules.derivatives import der, get_derivation_variable, \ ...@@ -2,8 +2,10 @@ from src.rules.derivatives import der, get_derivation_variable, \
match_zero_derivative, match_one_derivative, one_derivative, \ match_zero_derivative, match_one_derivative, one_derivative, \
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_logarithm, logarithm const_deriv_multiplication, chain_rule, match_logarithmic, \
logarithmic, match_goniometric, sinus, cosinus, tangens
from src.rules.logarithmic import ln from src.rules.logarithmic import ln
from src.rules.goniometry import sin, cos
from src.node import Scope from src.node import Scope
from src.possibilities import Possibility as P from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
...@@ -110,15 +112,49 @@ class TestRulesDerivatives(RulesTestCase): ...@@ -110,15 +112,49 @@ class TestRulesDerivatives(RulesTestCase):
self.assertEqual(chain_rule(root, (x3, variable_exponent, ())), self.assertEqual(chain_rule(root, (x3, variable_exponent, ())),
l2 ** x3 * ln(l2) * der(x3)) l2 ** x3 * ln(l2) * der(x3))
def test_match_logarithm(self): def test_match_logarithmic(self):
root = tree('der(log(x))') root = tree('der(log(x))')
self.assertEqualPos(match_logarithm(root), [P(root, logarithm)]) self.assertEqualPos(match_logarithmic(root), [P(root, logarithmic)])
def test_match_logarithm_chain_rule(self): def test_match_logarithmic_chain_rule(self):
root, f = tree('der(log(x ^ 2)), x ^ 2') root, f = tree('der(log(x ^ 2)), x ^ 2')
self.assertEqualPos(match_logarithm(root), self.assertEqualPos(match_logarithmic(root),
[P(root, chain_rule, (f, logarithm, ()))]) [P(root, chain_rule, (f, logarithmic, ()))])
def test_logarithm(self): def test_logarithmic(self):
root, x, l1, l10 = tree('der(log(x)), x, 1, 10') root, x, l1, l10 = tree('der(log(x)), x, 1, 10')
self.assertEqual(logarithm(root, ()), l1 / (x * ln(l10))) self.assertEqual(logarithmic(root, ()), l1 / (x * ln(l10)))
def test_match_goniometric(self):
root = tree('der(sin(x))')
self.assertEqualPos(match_goniometric(root), [P(root, sinus)])
root = tree('der(cos(x))')
self.assertEqualPos(match_goniometric(root), [P(root, cosinus)])
root = tree('der(tan(x))')
self.assertEqualPos(match_goniometric(root), [P(root, tangens)])
def test_match_goniometric_chain_rule(self):
root, x2 = tree('der(sin(x ^ 2)), x ^ 2')
self.assertEqualPos(match_goniometric(root),
[P(root, chain_rule, (x2, sinus, ()))])
root = tree('der(cos(x ^ 2))')
self.assertEqualPos(match_goniometric(root),
[P(root, chain_rule, (x2, cosinus, ()))])
def test_sinus(self):
root, x = tree('der(sin(x)), x')
self.assertEqual(sinus(root, ()), cos(x))
def test_cosinus(self):
root, x = tree('der(cos(x)), x')
self.assertEqual(cosinus(root, ()), -sin(x))
def test_tangens(self):
root, x = tree('der(tan(x), x), x')
self.assertEqual(tangens(root, ()), der(sin(x) / cos(x), x))
root = tree('der(tan(x))')
self.assertEqual(tangens(root, ()), der(sin(x) / cos(x)))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment