Commit d3a8ad0a authored by Taddeus Kroes's avatar Taddeus Kroes

Moved all spreaded node creation functions to src/node.py.

parent dfbc16d4
...@@ -606,3 +606,76 @@ def negate(node, n=1): ...@@ -606,3 +606,76 @@ def negate(node, n=1):
new_node.negated = n new_node.negated = n
return new_node return new_node
def infinity():
"""
Return an infinity leaf node.
"""
return ExpressionLeaf(INFINITY)
def absolute(exp):
"""
Put an 'absolute value' operator on top of the given expression.
"""
return ExpressionNode(OP_ABS, exp)
def sin(*args):
"""
Create a sinus function node.
"""
return ExpressionNode(OP_SIN, *args)
def cos(*args):
"""
Create a cosinus function node.
"""
return ExpressionNode(OP_COS, *args)
def tan(*args):
"""
Create a tangens function node.
"""
return ExpressionNode(OP_TAN, *args)
def log(exponent, base=10):
"""
Create a logarithm function node (default base is 10).
"""
if not isinstance(base, ExpressionLeaf):
base = ExpressionLeaf(base)
return ExpressionNode(OP_LOG, exponent, base)
def ln(exponent):
"""
Create a natural logarithm node.
"""
return log(exponent, base=E)
def der(f, x=None):
"""
Create a derivative node.
"""
return ExpressionNode(OP_DER, f, x) if x else ExpressionNode(OP_DER, f)
def integral(*args):
"""
Create an integral node.
"""
return ExpressionNode(OP_INT, *args)
def indef(*args):
"""
Create an indefinite integral node.
"""
return ExpressionNode(OP_INT_INDEF, *args)
from .utils import find_variables, first_sorted_variable from .utils import find_variables, first_sorted_variable
from .logarithmic import ln from ..node import ExpressionLeaf as L, Scope, OP_DER, OP_MUL, OP_LOG, \
from .goniometry import sin, cos OP_SIN, OP_COS, OP_TAN, OP_ADD, OP_DIV, E, sin, cos, der, ln
from ..node import ExpressionNode as N, ExpressionLeaf as L, Scope, OP_DER, \
OP_MUL, OP_LOG, OP_SIN, OP_COS, OP_TAN, OP_ADD, OP_DIV, E
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def der(f, x=None):
return N(OP_DER, f, x) if x else N(OP_DER, f)
def second_arg(node): def second_arg(node):
""" """
Get the second child of a node if it exists, None otherwise. Get the second child of a node if it exists, None otherwise.
......
from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_ADD, OP_MUL, \ from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_ADD, OP_MUL, \
OP_DIV, OP_SIN, OP_COS, OP_TAN, OP_SQRT, PI, TYPE_OPERATOR OP_DIV, OP_SIN, OP_COS, OP_TAN, OP_SQRT, PI, TYPE_OPERATOR, sin, cos
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def sin(*args):
return N(OP_SIN, *args)
def cos(*args):
return N(OP_COS, *args)
def tan(*args):
return N(OP_TAN, *args)
def match_add_quadrants(node): def match_add_quadrants(node):
""" """
sin(t) ^ 2 + cos(t) ^ 2 -> 1 sin(t) ^ 2 + cos(t) ^ 2 -> 1
...@@ -26,9 +14,9 @@ def match_add_quadrants(node): ...@@ -26,9 +14,9 @@ def match_add_quadrants(node):
sin_q, cos_q = node sin_q, cos_q = node
if sin_q.is_power(2) and cos_q.is_power(2): if sin_q.is_power(2) and cos_q.is_power(2):
sin, cos = sin_q[0], cos_q[0] sinus, cosinus = sin_q[0], cos_q[0]
if sin.is_op(OP_SIN) and cos.is_op(OP_COS): if sinus.is_op(OP_SIN) and cosinus.is_op(OP_COS):
p.append(P(node, add_quadrants, ())) p.append(P(node, add_quadrants, ()))
return p return p
......
from .utils import find_variables, replace_variable, find_variable, absolute from .utils import find_variables, replace_variable, find_variable
from .logarithmic import ln from ..node import ExpressionLeaf as L, OP_INT, OP_INT_INDEF, OP_MUL, OP_DIV, \
from .goniometry import sin, cos OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, indef, absolute
from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_INT, \
OP_INT_INDEF, OP_MUL, OP_DIV, OP_LOG, OP_SIN, OP_COS, Scope
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def integral(*args):
"""
Create an integral node.
"""
return N(OP_INT, *args)
def indef(*args):
"""
Create an indefinite integral node.
"""
return N(OP_INT_INDEF, *args)
def choose_constant(integral): def choose_constant(integral):
""" """
Choose a constant to be added to the antiderivative. Choose a constant to be added to the antiderivative.
......
from itertools import combinations, product from itertools import combinations, product
from .utils import find_variables, partition from .utils import find_variables, partition
from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_LOG, E, \ from ..node import ExpressionLeaf as L, OP_LOG, OP_ADD, OP_MUL, OP_POW, \
OP_ADD, OP_MUL, OP_POW, Scope Scope, log
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def log(exponent, base=10):
if not isinstance(base, L):
base = L(base)
return N(OP_LOG, exponent, base)
def ln(exponent):
return log(exponent, base=E)
def match_constant_logarithm(node): def match_constant_logarithm(node):
""" """
log_1(a) -> # raise ValueError for base 1 log_1(a) -> # raise ValueError for base 1
......
from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_MUL, OP_DIV, \ from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_MUL, OP_DIV
INFINITY, OP_ABS
def greatest_common_divisor(a, b): def greatest_common_divisor(a, b):
...@@ -126,17 +125,3 @@ def replace_variable(f, x, replacement): ...@@ -126,17 +125,3 @@ def replace_variable(f, x, replacement):
children = map(lambda c: replace_variable(c, x, replacement), f) children = map(lambda c: replace_variable(c, x, replacement), f)
return N(f.op, *children) return N(f.op, *children)
def infinity():
"""
Return an infinity leaf node.
"""
return L(INFINITY)
def absolute(exp):
"""
Put an 'absolute value' operator on top of the given expression.
"""
return N(OP_ABS, exp)
from src.node import ExpressionNode as N, ExpressionLeaf as L, Scope, \ from src.node import ExpressionNode as N, ExpressionLeaf as L, Scope, \
nary_node, get_scope, OP_ADD nary_node, get_scope, OP_ADD, infinity, absolute, sin, cos, tan, log, \
ln, der, integral, indef
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
...@@ -249,3 +250,44 @@ class TestNode(RulesTestCase): ...@@ -249,3 +250,44 @@ class TestNode(RulesTestCase):
def test_construct_function_absolute_child(self): def test_construct_function_absolute_child(self):
self.assertEqual(str(tree('ln(|x|)')), 'ln|x|') self.assertEqual(str(tree('ln(|x|)')), 'ln|x|')
self.assertEqual(str(tree('sin(|x|)')), 'sin|x|') self.assertEqual(str(tree('sin(|x|)')), 'sin|x|')
def test_infinity(self):
self.assertEqual(infinity(), tree('oo'))
def test_absolute(self):
self.assertEqual(absolute(tree('x2')), tree('|x2|'))
def test_sin(self):
self.assertEqual(sin(tree('x')), tree('sin(x)'))
def test_cos(self):
self.assertEqual(cos(tree('x')), tree('cos(x)'))
def test_tan(self):
self.assertEqual(tan(tree('x')), tree('tan(x)'))
def test_log(self):
x = tree('x')
self.assertEqual(log(x, 'e'), tree('ln x'))
self.assertEqual(log(x, 2), tree('log_2 x'))
self.assertEqual(log(x), tree('log x'))
self.assertEqual(log(x, 10), tree('log x'))
def test_ln(self):
self.assertEqual(ln(tree('x')), tree('ln x'))
def test_der(self):
x2, x, y = tree('x ^ 2, x, y')
self.assertEqual(der(x2), tree('[x ^ 2]\''))
self.assertEqual(der(x2, x), tree('d/dx x ^ 2'))
self.assertEqual(der(x2, y), tree('d/dy x ^ 2'))
def test_integral(self):
x2, x, y, a, b = tree('x ^ 2, x, y, a, b')
self.assertEqual(integral(x2, x), tree('int x2 dx'))
self.assertEqual(integral(x2, x, a, b), tree('int_a^b x2 dx'))
self.assertEqual(integral(x2, y, a, b), tree('int_a^b x2 dy'))
def test_indef(self):
x2, a, b, expect = tree('x ^ 2, a, b, [x ^ 2]_a^b')
self.assertEqual(indef(x2, a, b), expect)
...@@ -3,14 +3,9 @@ import unittest ...@@ -3,14 +3,9 @@ import unittest
from src.parser import Parser from src.parser import Parser
from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf, \ from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf, \
SPECIAL_TOKENS SPECIAL_TOKENS, sin, cos, der, log, ln, integral, indef, absolute
from tests.parser import ParserWrapper, run_expressions, line, graph from tests.parser import ParserWrapper, run_expressions, line, graph
from tests.rulestestcase import tree from tests.rulestestcase import tree
from src.rules.goniometry import sin, cos
from src.rules.derivatives import der
from src.rules.logarithmic import log, ln
from src.rules.integrals import integral, indef
from src.rules.utils import absolute
class TestParser(unittest.TestCase): class TestParser(unittest.TestCase):
......
...@@ -6,9 +6,7 @@ from src.rules.derivatives import der, get_derivation_variable, \ ...@@ -6,9 +6,7 @@ from src.rules.derivatives import der, get_derivation_variable, \
logarithmic, match_goniometric, sinus, cosinus, tangens, \ logarithmic, match_goniometric, sinus, cosinus, tangens, \
match_sum_product_rule, sum_rule, product_rule, match_quotient_rule, \ match_sum_product_rule, sum_rule, product_rule, match_quotient_rule, \
quotient_rule, power_rule quotient_rule, power_rule
from src.rules.logarithmic import ln from src.node import Scope, sin, cos, ln
from src.rules.goniometry import sin, cos
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
......
# vim: set fileencoding=utf-8 : # vim: set fileencoding=utf-8 :
from src.rules.goniometry import sin, cos, tan, match_add_quadrants, \ from src.rules.goniometry import match_add_quadrants, add_quadrants, \
add_quadrants, match_negated_parameter, negated_sinus_parameter, \ match_negated_parameter, negated_sinus_parameter, is_pi_frac, \
negated_cosinus_parameter, match_standard_radian, standard_radian, \ negated_cosinus_parameter, match_standard_radian, standard_radian
is_pi_frac from src.node import PI, OP_SIN, OP_COS, OP_TAN, sin, cos, tan
from src.node import PI, OP_SIN, OP_COS, OP_TAN
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
from src.rules import goniometry from src.rules import goniometry
......
...@@ -6,8 +6,6 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \ ...@@ -6,8 +6,6 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \
match_division_integral, division_integral, extend_division_integral, \ match_division_integral, division_integral, extend_division_integral, \
match_function_integral, logarithm_integral, sinus_integral, \ match_function_integral, logarithm_integral, sinus_integral, \
cosinus_integral cosinus_integral
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
......
from src.rules.logarithmic import log, ln, match_constant_logarithm, \ from src.rules.logarithmic import log, match_constant_logarithm, \
base_equals_raised, logarithm_of_one, divide_same_base, \ base_equals_raised, logarithm_of_one, divide_same_base, \
match_add_logarithms, add_logarithms, expand_negations, \ match_add_logarithms, add_logarithms, expand_negations, \
subtract_logarithms, match_raised_base, raised_base, \ subtract_logarithms, match_raised_base, raised_base, \
......
from src.rules import utils from src.rules import utils
from src.rules.utils import least_common_multiple, is_fraction, partition, \ from src.rules.utils import least_common_multiple, is_fraction, partition, \
find_variables, first_sorted_variable, find_variable, \ find_variables, first_sorted_variable, find_variable, replace_variable
replace_variable, infinity
from tests.rulestestcase import tree, RulesTestCase from tests.rulestestcase import tree, RulesTestCase
...@@ -28,9 +27,6 @@ class TestRulesUtils(RulesTestCase): ...@@ -28,9 +27,6 @@ class TestRulesUtils(RulesTestCase):
self.assertEqual(partition(lambda x: x & 1, range(6)), self.assertEqual(partition(lambda x: x & 1, range(6)),
([1, 3, 5], [0, 2, 4])) ([1, 3, 5], [0, 2, 4]))
def test_infinity(self):
self.assertEqual(infinity(), tree('oo'))
def test_find_variables(self): def test_find_variables(self):
x, l2, add, mul0, mul1 = tree('x, 2, x + 2, 2x, xy') x, l2, add, mul0, mul1 = tree('x, 2, x + 2, 2x, xy')
self.assertSetEqual(find_variables(x), set(['x'])) self.assertSetEqual(find_variables(x), set(['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