Commit f5e26d06 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Corrected mixed up definite/indefinite integral references

parent c409356f
......@@ -44,5 +44,3 @@
- Missed rewrite possibility:
(4x) / (2x ^ 2 - 2y ^ 2) -> (2x) / (x ^ 2 - y ^ 2)
- "indefinite" / "definite" are sometimes confused in messges, fix that...
......@@ -50,7 +50,7 @@ NARY_OPERATORS = [OP_ADD, OP_SUB, OP_MUL, OP_AND, OP_OR]
# N-ary (functions)
OP_INT = 11
OP_INT_INDEF = 12
OP_INT_DEF = 12
OP_COMMA = 13
OP_SQRT = 14
OP_DER = 15
......@@ -125,7 +125,7 @@ OP_MAP = {
}
OP_VALUE_MAP = dict([(v, k) for k, v in OP_MAP.iteritems()])
OP_VALUE_MAP[OP_INT_INDEF] = 'indef'
OP_VALUE_MAP[OP_INT_DEF] = 'indef'
OP_VALUE_MAP[OP_ABS] = '||'
OP_VALUE_MAP[OP_DXDER] = 'd/d'
OP_VALUE_MAP[OP_PARENS] = '()'
......@@ -363,13 +363,13 @@ class ExpressionNode(Node, ExpressionBase):
return self.value
def is_postfix(self):
return self.op in (OP_PRIME, OP_INT_INDEF)
return self.op in (OP_PRIME, OP_INT_DEF)
def __str__(self): # pragma: nocover
return generate_line(self)
def custom_line(self):
if self.op == OP_INT_INDEF:
if self.op == OP_INT_DEF:
Fx, a, b = self
return bounds_str(ExpressionNode(OP_BRACKETS, Fx), a, b)
......@@ -751,16 +751,17 @@ def der(f, x=None):
def integral(*args):
"""
Create an integral node.
Create an integral node (may be definite or indefinite, depending on
whether there are bounds in `args`).
"""
return ExpressionNode(OP_INT, *args)
def indef(*args):
def int_def(*args):
"""
Create an indefinite integral node.
Create a definite integral node (bracket notation).
"""
return ExpressionNode(OP_INT_INDEF, *args)
return ExpressionNode(OP_INT_DEF, *args)
def eq(left, right):
......
......@@ -31,7 +31,7 @@ from graph_drawing.line import pred
from node import ExpressionNode as Node, \
ExpressionLeaf as Leaf, OP_MAP, OP_DXDER, TOKEN_MAP, TYPE_OPERATOR, \
OP_COMMA, OP_MUL, OP_POW, OP_LOG, OP_ADD, Scope, E, OP_ABS, \
DEFAULT_LOGARITHM_BASE, SPECIAL_TOKENS, OP_INT, OP_INT_INDEF, \
DEFAULT_LOGARITHM_BASE, SPECIAL_TOKENS, OP_INT, OP_INT_DEF, \
INFINITY, OP_PRIME, OP_DIV
from rules.utils import find_variable
from rules.precedences import IMPLICIT_RULES
......@@ -683,7 +683,7 @@ class Parser(BisonParser):
lbnd.negated += len(values[1]) - 1
return Node(OP_INT_INDEF, values[0], lbnd, ubnd)
return Node(OP_INT_DEF, values[0], lbnd, ubnd)
raise BisonSyntaxError('Unsupported option %d in target "%s".'
% (option, target)) # pragma: nocover
......
......@@ -13,7 +13,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with TRS. If not, see <http://www.gnu.org/licenses/>.
from ..node import OP_ADD, OP_MUL, OP_DIV, OP_POW, OP_NEG, OP_SIN, OP_COS, \
OP_TAN, OP_DER, OP_LOG, OP_INT, OP_INT_INDEF, OP_EQ, OP_ABS, OP_SQRT, \
OP_TAN, OP_DER, OP_LOG, OP_INT, OP_INT_DEF, OP_EQ, OP_ABS, OP_SQRT, \
OP_AND, OP_OR, OP_DXDER, OP_PRIME
from .groups import match_combine_groups
from .factors import match_expand
......@@ -40,10 +40,10 @@ from .derivatives import match_zero_derivative, \
from .logarithmic import match_constant_logarithm, \
match_add_logarithms, match_raised_base, match_factor_out_exponent, \
match_factor_in_multiplicant, match_expand_terms
from .integrals import match_solve_indef, match_constant_integral, \
from .integrals import match_solve_definite, match_constant_integral, \
match_integrate_variable_power, match_factor_out_constant, \
match_division_integral, match_function_integral, \
match_sum_rule_integral, match_remove_indef_constant
match_sum_rule_integral, match_remove_definite_constant
from .lineq import match_move_term, match_multiple_equations, match_double_case
from .absolute import match_factor_out_abs_term
from .sqrt import match_reduce_sqrt
......@@ -82,7 +82,7 @@ RULES = {
OP_INT: [match_integrate_variable_power, match_constant_integral,
match_factor_out_constant, match_division_integral,
match_function_integral, match_sum_rule_integral],
OP_INT_INDEF: [match_remove_indef_constant, match_solve_indef],
OP_INT_DEF: [match_remove_definite_constant, match_solve_definite],
OP_EQ: [match_move_term],
OP_ABS: [match_factor_out_abs_term],
OP_SQRT: [match_reduce_sqrt],
......
......@@ -13,8 +13,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with TRS. If not, see <http://www.gnu.org/licenses/>.
from .utils import find_variables, substitute, find_variable
from ..node import ExpressionLeaf as L, OP_INT, OP_INT_INDEF, OP_MUL, OP_DIV, \
OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, indef, \
from ..node import ExpressionLeaf as L, OP_INT, OP_INT_DEF, OP_MUL, OP_DIV, \
OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, int_def, \
absolute, OP_ADD, negate
from ..possibilities import Possibility as P, MESSAGES
from ..translate import _
......@@ -43,10 +43,10 @@ def solve_integral(integral, F):
Solve an integral given its anti-derivative F:
- First, finish the anti-derivative by adding a constant.
- If no bounds are specified, return the anti-derivative.
- Given a lower bound a and upper bound b, the solution is the indefinite
- Given a lower bound a and upper bound b, the solution is the definite
integral [F(x)]_a^b. If F(x) contains multiple variables so that the 'x'
is not identified by 'find_variable(F)' (which is used by the indefinite
integral), skip the reduction of the indefinite integral and return the
is not identified by 'find_variable(F)' (which is used by the definite
integral), skip the reduction of the definite integral and return the
solution F(b) - F(a).
"""
F += choose_constant(integral)
......@@ -59,21 +59,21 @@ def solve_integral(integral, F):
if x != find_variable(F):
solution = substitute(F, x, ubnd) - substitute(F, x, lbnd)
else:
solution = indef(F, lbnd, ubnd)
solution = int_def(F, lbnd, ubnd)
return negate(solution, integral.negated)
def match_solve_indef(node):
def match_solve_definite(node):
"""
[F(x)]_a^b -> F(b) - F(a)
"""
assert node.is_op(OP_INT_INDEF)
assert node.is_op(OP_INT_DEF)
return [P(node, solve_indef)]
return [P(node, solve_definite)]
def solve_indef(root, args):
def solve_definite(root, args):
"""
[F(x)]_a^b -> F(b) - F(a)
"""
......@@ -83,12 +83,12 @@ def solve_indef(root, args):
return negate(substitute(Fx, x, b) - substitute(Fx, x, a), root.negated)
def solve_indef_msg(root, args): # pragma: nocover
return _('Solve indefinite integral {0} using substitution ' \
def solve_definite_msg(root, args): # pragma: nocover
return _('Solve definite integral {0} using substitution ' \
'of `%s` with {0[2]} and {0[1]}.' % find_variable(root[0]))
MESSAGES[solve_indef] = solve_indef_msg
MESSAGES[solve_definite] = solve_definite_msg
def match_integrate_variable_power(node):
......@@ -363,11 +363,11 @@ def sum_rule_integral(root, args):
MESSAGES[sum_rule_integral] = _('Apply the sum rule to {0}.')
def match_remove_indef_constant(node):
def match_remove_definite_constant(node):
"""
[f(x) + c]_a^b -> [f(x)]_a^b
"""
assert node.is_op(OP_INT_INDEF)
assert node.is_op(OP_INT_DEF)
if not node[0].is_op(OP_ADD):
return []
......@@ -376,10 +376,10 @@ def match_remove_indef_constant(node):
x = find_variable(node[0])
constants = [n for n in scope if not n.contains(x)]
return [P(node, remove_indef_constant, (scope, c)) for c in constants]
return [P(node, remove_definite_constant, (scope, c)) for c in constants]
def remove_indef_constant(root, args):
def remove_definite_constant(root, args):
"""
[f(x) + c]_a^b -> [f(x)]_a^b
"""
......@@ -388,8 +388,8 @@ def remove_indef_constant(root, args):
Fx = scope.as_nary_node()
a, b = root[1:]
return negate(indef(Fx, a, b), root.negated)
return negate(int_def(Fx, a, b), root.negated)
MESSAGES[remove_indef_constant] = \
_('Remove constant {2} from indefinite integral.')
MESSAGES[remove_definite_constant] = \
_('Remove constant {2} from definite integral.')
......@@ -14,7 +14,7 @@
# along with TRS. If not, see <http://www.gnu.org/licenses/>.
from src.node import ExpressionNode as N, ExpressionLeaf as L, Scope, \
nary_node, get_scope, OP_ADD, infinity, absolute, sin, cos, tan, log, \
ln, der, integral, indef, eq
ln, der, integral, int_def, eq
from tests.rulestestcase import RulesTestCase, tree
......@@ -259,7 +259,7 @@ class TestNode(RulesTestCase):
self.assertEqual(str(tree('int_(a-b)^(a+b) x ^ 2')),
'int_(a - b)^(a + b) x ^ 2 dx')
def test_construct_function_indef(self):
def test_construct_function_int_def(self):
self.assertEqual(str(tree('[x ^ 2]_a^b')), '[x ^ 2]_a^b')
self.assertEqual(str(tree('[x ^ 2]_(a-b)^(a+b)')),
'[x ^ 2]_(a - b)^(a + b)')
......@@ -318,9 +318,9 @@ class TestNode(RulesTestCase):
self.assertEqual(integral(x2, x, a, b), tree('int_a^b x^2 dx'))
self.assertEqual(integral(x2, y, a, b), tree('int_a^b x^2 dy'))
def test_indef(self):
def test_int_def(self):
x2, a, b, expect = tree('x ^ 2, a, b, [x ^ 2]_a^b')
self.assertEqual(indef(x2, a, b), expect)
self.assertEqual(int_def(x2, a, b), expect)
def test_eq(self):
x, a, b, expect = tree('x, a, b, x + a = b')
......
......@@ -15,7 +15,7 @@
# along with TRS. If not, see <http://www.gnu.org/licenses/>.
from src.parser import Parser, find_possibilities
from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf, \
SPECIAL_TOKENS, sin, cos, der, log, ln, integral, indef, absolute, \
SPECIAL_TOKENS, sin, cos, der, log, ln, integral, int_def, absolute, \
Scope
from src.possibilities import Possibility as P
from src.rules.numerics import add_numerics
......@@ -178,15 +178,15 @@ class TestParser(RulesTestCase):
self.assertEqual(tree('int_(-a)^b x dx'), integral(x, x, -a, b))
self.assertEqual(tree('int_-a^b x^2 dx'), integral(x ** 2, x, -a, b))
def test_indefinite_integral(self):
def test_int_definite_integral(self):
x2, a, b, oo, l2 = tree('x ^ 2, a, b, oo, 2')
self.assertEqual(tree('(x ^ 2)_a'), indef(x2, a, oo))
self.assertEqual(tree('(x ^ 2)_a^b'), indef(x2, a, b))
self.assertEqual(tree('(x ^ 2)_-a^b'), indef(x2, -a, b))
self.assertEqual(tree('(x ^ 2)_-a^-b'), indef(x2, -a, -b))
self.assertNotEqual(tree('(x ^ 2)_-2a^b'), indef(x2, -(l2 * a), b))
self.assertEqual(tree('(x ^ 2)_(-2a)^b'), indef(x2, -(l2 * a), b))
self.assertEqual(tree('(x ^ 2)_a'), int_def(x2, a, oo))
self.assertEqual(tree('(x ^ 2)_a^b'), int_def(x2, a, b))
self.assertEqual(tree('(x ^ 2)_-a^b'), int_def(x2, -a, b))
self.assertEqual(tree('(x ^ 2)_-a^-b'), int_def(x2, -a, -b))
self.assertNotEqual(tree('(x ^ 2)_-2a^b'), int_def(x2, -(l2 * a), b))
self.assertEqual(tree('(x ^ 2)_(-2a)^b'), int_def(x2, -(l2 * a), b))
def test_absolute_value(self):
x = tree('x')
......
......@@ -12,8 +12,8 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with TRS. If not, see <http://www.gnu.org/licenses/>.
from src.rules.integrals import indef, choose_constant, solve_integral, \
match_solve_indef, solve_indef, match_integrate_variable_power, \
from src.rules.integrals import choose_constant, solve_integral, \
match_solve_definite, solve_definite, match_integrate_variable_power, \
integrate_variable_root, integrate_variable_exponent, \
match_constant_integral, constant_integral, single_variable_integral, \
match_factor_out_constant, factor_out_integral_negation, \
......@@ -21,8 +21,8 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \
extend_division_integral, match_function_integral, \
logarithm_integral, sinus_integral, cosinus_integral, \
match_sum_rule_integral, sum_rule_integral, \
match_remove_indef_constant, remove_indef_constant
from src.node import Scope
match_remove_definite_constant, remove_definite_constant
from src.node import Scope, int_def
from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree
......@@ -35,26 +35,27 @@ class TestRulesIntegrals(RulesTestCase):
self.assertEqual(choose_constant(tree('int x ^ c')), a)
self.assertEqual(choose_constant(tree('int a ^ c da')), b)
def test_match_solve_indef(self):
def test_match_solve_definite(self):
root = tree('[x ^ 2]_a^b')
self.assertEqualPos(match_solve_indef(root), [P(root, solve_indef)])
self.assertEqualPos(match_solve_definite(root),
[P(root, solve_definite)])
def test_solve_integral(self):
root, F, Fc = tree('int x ^ 2 dx, 1 / 3 x ^ 3, 1 / 3 x ^ 3 + C')
self.assertEqual(solve_integral(root, F), Fc)
x2, x, a, b = root = tree('int_a^b x ^ 2 dx')
self.assertEqual(solve_integral(root, F), indef(Fc, a, b))
self.assertEqual(solve_integral(root, F), int_def(Fc, a, b))
def test_solve_integral_skip_indef(self):
def test_solve_integral_skip_definite(self):
root, x, C, l1 = tree('int_a^b y ^ x dy, x, C, 1')
F = tree('1 / (x + 1)y ^ (x + 1)')
y, a, b = root[1:4]
Fx = lambda y: l1 / (x + 1) * y ** (x + 1) + C
self.assertEqual(solve_integral(root, F), Fx(b) - Fx(a))
def test_solve_indef(self):
def test_solve_definite(self):
root, expect = tree('[x ^ 2]_a^b, b ^ 2 - a ^ 2')
self.assertEqual(solve_indef(root, ()), expect)
self.assertEqual(solve_definite(root, ()), expect)
def test_match_integrate_variable_power(self):
root = tree('int x ^ n')
......@@ -195,18 +196,18 @@ class TestRulesIntegrals(RulesTestCase):
self.assertEqual(sum_rule_integral(root, (Scope(root[0]), h)),
tree('int 4x dx + int (2x + 3x) dx'))
def test_match_remove_indef_constant(self):
def test_match_remove_definite_constant(self):
Fx, a, b = root = tree('[2x + C]_a^b')
self.assertEqualPos(match_remove_indef_constant(root),
[P(root, remove_indef_constant, (Scope(Fx), Fx[1]))])
self.assertEqualPos(match_remove_definite_constant(root),
[P(root, remove_definite_constant, (Scope(Fx), Fx[1]))])
Fx, a, b = root = tree('[2x + x]_a^b')
self.assertEqualPos(match_remove_indef_constant(root), [])
self.assertEqualPos(match_remove_definite_constant(root), [])
Fx, a, b = root = tree('[2x]_a^b')
self.assertEqualPos(match_remove_indef_constant(root), [])
self.assertEqualPos(match_remove_definite_constant(root), [])
def test_remove_indef_constant(self):
def test_remove_definite_constant(self):
root, e = tree('[2x + C]_a^b, [2x]_a^b')
Fx = root[0]
self.assertEqual(remove_indef_constant(root, (Scope(Fx), Fx[1])), e)
self.assertEqual(remove_definite_constant(root, (Scope(Fx), Fx[1])), e)
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