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
cbd37711
Commit
cbd37711
authored
Mar 24, 2012
by
Taddeus Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented integral notation, still produces one shift/reduce conflict.
parent
b05101ae
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
126 additions
and
73 deletions
+126
-73
src/node.py
src/node.py
+5
-4
src/parser.py
src/parser.py
+69
-50
src/rules/integrals.py
src/rules/integrals.py
+17
-6
src/rules/utils.py
src/rules/utils.py
+9
-0
tests/test_parser.py
tests/test_parser.py
+15
-2
tests/test_rules_integrals.py
tests/test_rules_integrals.py
+11
-11
No files found.
src/node.py
View file @
cbd37711
...
@@ -207,8 +207,8 @@ class ExpressionBase(object):
...
@@ -207,8 +207,8 @@ class ExpressionBase(object):
return
ExpressionNode
(
OP_ADD
,
self
,
to_expression
(
other
))
return
ExpressionNode
(
OP_ADD
,
self
,
to_expression
(
other
))
def
__sub__
(
self
,
other
):
def
__sub__
(
self
,
other
):
#FIXME:
return ExpressionNode(OP_ADD, self, -to_expression(other))
return
ExpressionNode
(
OP_ADD
,
self
,
-
to_expression
(
other
))
return
ExpressionNode
(
OP_SUB
,
self
,
to_expression
(
other
))
#FIXME:
return ExpressionNode(OP_SUB, self, to_expression(other))
def
__mul__
(
self
,
other
):
def
__mul__
(
self
,
other
):
return
ExpressionNode
(
OP_MUL
,
self
,
to_expression
(
other
))
return
ExpressionNode
(
OP_MUL
,
self
,
to_expression
(
other
))
...
@@ -428,7 +428,7 @@ class ExpressionLeaf(Leaf, ExpressionBase):
...
@@ -428,7 +428,7 @@ class ExpressionLeaf(Leaf, ExpressionBase):
other_type
=
type
(
other
)
other_type
=
type
(
other
)
if
other_type
in
TYPE_MAP
:
if
other_type
in
TYPE_MAP
:
return
TYPE_MAP
[
other_type
]
==
self
.
type
\
return
self
.
type
==
TYPE_MAP
[
other_type
]
\
and
self
.
actual_value
()
==
other
and
self
.
actual_value
()
==
other
return
self
.
negated
==
other
.
negated
and
self
.
type
==
other
.
type
\
return
self
.
negated
==
other
.
negated
and
self
.
type
==
other
.
type
\
...
@@ -466,7 +466,8 @@ class ExpressionLeaf(Leaf, ExpressionBase):
...
@@ -466,7 +466,8 @@ class ExpressionLeaf(Leaf, ExpressionBase):
return
(
ExpressionLeaf
(
1
),
self
,
ExpressionLeaf
(
1
))
return
(
ExpressionLeaf
(
1
),
self
,
ExpressionLeaf
(
1
))
def
actual_value
(
self
):
def
actual_value
(
self
):
assert
self
.
is_numeric
()
if
self
.
type
==
TYPE_IDENTIFIER
:
return
self
.
value
return
(
1
-
2
*
(
self
.
negated
&
1
))
*
self
.
value
return
(
1
-
2
*
(
self
.
negated
&
1
))
*
self
.
value
...
...
src/parser.py
View file @
cbd37711
...
@@ -14,11 +14,13 @@ sys.path.insert(1, EXTERNAL_MODS)
...
@@ -14,11 +14,13 @@ sys.path.insert(1, EXTERNAL_MODS)
from
pybison
import
BisonParser
,
BisonSyntaxError
from
pybison
import
BisonParser
,
BisonSyntaxError
from
graph_drawing.graph
import
generate_graph
from
graph_drawing.graph
import
generate_graph
from
node
import
ExpressionNode
as
Node
,
ExpressionLeaf
as
Leaf
,
OP_MAP
,
\
from
node
import
ExpressionBase
,
ExpressionNode
as
Node
,
\
OP_DER
,
TOKEN_MAP
,
TYPE_OPERATOR
,
OP_COMMA
,
OP_NEG
,
OP_MUL
,
OP_DIV
,
\
ExpressionLeaf
as
Leaf
,
OP_MAP
,
OP_DER
,
TOKEN_MAP
,
TYPE_OPERATOR
,
\
OP_LOG
,
OP_ADD
,
Scope
,
E
,
DEFAULT_LOGARITHM_BASE
,
OP_VALUE_MAP
,
\
OP_COMMA
,
OP_NEG
,
OP_MUL
,
OP_DIV
,
OP_POW
,
OP_LOG
,
OP_ADD
,
Scope
,
E
,
\
SPECIAL_TOKENS
,
OP_INT
,
OP_INT_INDEF
DEFAULT_LOGARITHM_BASE
,
OP_VALUE_MAP
,
SPECIAL_TOKENS
,
OP_INT
,
\
OP_INT_INDEF
from
rules
import
RULES
from
rules
import
RULES
from
rules.utils
import
find_variable
from
strategy
import
pick_suggestion
from
strategy
import
pick_suggestion
from
possibilities
import
filter_duplicates
,
apply_suggestion
from
possibilities
import
filter_duplicates
,
apply_suggestion
...
@@ -43,16 +45,17 @@ def combine(op, op_type, *nodes):
...
@@ -43,16 +45,17 @@ def combine(op, op_type, *nodes):
def
find_integration_variable
(
exp
):
def
find_integration_variable
(
exp
):
if
not
exp
.
is_op
(
OP_MUL
):
if
not
exp
.
is_op
(
OP_MUL
):
return
exp
return
exp
,
find_variable
(
exp
)
scope
=
Scope
(
exp
)
scope
=
Scope
(
exp
)
if
len
(
scope
)
<
3
or
scope
[
-
2
]
!=
'd'
or
not
scope
[
-
1
].
is_identifier
():
if
len
(
scope
)
>
2
and
scope
[
-
2
]
==
'd'
and
scope
[
-
1
].
is_identifier
():
return
exp
x
=
scope
[
-
1
]
scope
.
nodes
=
scope
[:
-
2
]
scope
.
nodes
=
scope
[:
-
2
]
return
scope
.
as_nary_node
(),
x
return
scope
.
as_nary_node
(
)
return
exp
,
find_variable
(
exp
)
class
Parser
(
BisonParser
):
class
Parser
(
BisonParser
):
...
@@ -62,8 +65,8 @@ class Parser(BisonParser):
...
@@ -62,8 +65,8 @@ class Parser(BisonParser):
"""
"""
# Words to be ignored by preprocessor
# Words to be ignored by preprocessor
words
=
tuple
(
filter
(
lambda
w
:
len
(
w
)
>
1
,
OP_MAP
.
iterkeys
()))
\
words
=
tuple
(
filter
(
lambda
w
:
w
.
isalpha
()
,
OP_MAP
.
iterkeys
()))
\
+
(
'raise'
,
'graph'
)
+
tuple
(
SPECIAL_TOKENS
)
+
(
'raise'
,
'graph'
)
+
tuple
(
SPECIAL_TOKENS
)
# Output directory of generated pybison files, including a trailing slash.
# Output directory of generated pybison files, including a trailing slash.
buildDirectory
=
PYBISON_BUILD
+
'/'
buildDirectory
=
PYBISON_BUILD
+
'/'
...
@@ -75,7 +78,7 @@ class Parser(BisonParser):
...
@@ -75,7 +78,7 @@ class Parser(BisonParser):
# of tokens of the lex script.
# of tokens of the lex script.
tokens
=
[
'NUMBER'
,
'IDENTIFIER'
,
'NEWLINE'
,
'QUIT'
,
'RAISE'
,
'GRAPH'
,
tokens
=
[
'NUMBER'
,
'IDENTIFIER'
,
'NEWLINE'
,
'QUIT'
,
'RAISE'
,
'GRAPH'
,
'LPAREN'
,
'RPAREN'
,
'FUNCTION'
,
'FUNCTION_LPAREN'
,
'LBRACKET'
,
'LPAREN'
,
'RPAREN'
,
'FUNCTION'
,
'FUNCTION_LPAREN'
,
'LBRACKET'
,
'RBRACKET'
,
'
APOSTROPH
'
,
'DERIVATIVE'
,
'SUB'
]
\
'RBRACKET'
,
'
PRIME
'
,
'DERIVATIVE'
,
'SUB'
]
\
+
filter
(
lambda
t
:
t
!=
'FUNCTION'
,
TOKEN_MAP
.
values
())
+
filter
(
lambda
t
:
t
!=
'FUNCTION'
,
TOKEN_MAP
.
values
())
# ------------------------------
# ------------------------------
...
@@ -83,12 +86,14 @@ class Parser(BisonParser):
...
@@ -83,12 +86,14 @@ class Parser(BisonParser):
# ------------------------------
# ------------------------------
precedences
=
(
precedences
=
(
(
'left'
,
(
'COMMA'
,
)),
(
'left'
,
(
'COMMA'
,
)),
(
'right'
,
(
'INTEGRAL'
,
'DERIVATIVE'
)),
(
'left'
,
(
'MINUS'
,
'PLUS'
)),
(
'left'
,
(
'MINUS'
,
'PLUS'
)),
(
'left'
,
(
'TIMES'
,
'DIVIDE'
)),
(
'left'
,
(
'TIMES'
,
'DIVIDE'
)),
(
'right'
,
(
'FUNCTION'
,
'DERIVATIVE'
)),
(
'right'
,
(
'FUNCTION'
,
)),
(
'left'
,
(
'EQ'
,
)),
(
'left'
,
(
'EQ'
,
)),
(
'left'
,
(
'NEG'
,
)),
(
'left'
,
(
'NEG'
,
)),
(
'right'
,
(
'POW'
,
'SUB'
)),
(
'right'
,
(
'POW'
,
)),
(
'right'
,
(
'SUB'
,
)),
(
'right'
,
(
'FUNCTION_LPAREN'
,
)),
(
'right'
,
(
'FUNCTION_LPAREN'
,
)),
)
)
...
@@ -228,7 +233,8 @@ class Parser(BisonParser):
...
@@ -228,7 +233,8 @@ class Parser(BisonParser):
return
data
return
data
def
hook_handler
(
self
,
target
,
option
,
names
,
values
,
retval
):
def
hook_handler
(
self
,
target
,
option
,
names
,
values
,
retval
):
if
target
in
[
'exp'
,
'line'
,
'input'
]
or
not
retval
:
if
target
in
[
'exp'
,
'line'
,
'input'
]
\
or
not
isinstance
(
retval
,
ExpressionBase
):
return
retval
return
retval
if
not
retval
.
negated
and
retval
.
type
!=
TYPE_OPERATOR
:
if
not
retval
.
negated
and
retval
.
type
!=
TYPE_OPERATOR
:
...
@@ -390,7 +396,8 @@ class Parser(BisonParser):
...
@@ -390,7 +396,8 @@ class Parser(BisonParser):
| FUNCTION exp
| FUNCTION exp
| DERIVATIVE exp
| DERIVATIVE exp
| bracket_derivative
| bracket_derivative
| integral
| INTEGRAL exp
| INTEGRAL bounds exp %prec INTEGRAL
"""
"""
if
option
==
0
:
# rule: NEG exp
if
option
==
0
:
# rule: NEG exp
...
@@ -407,6 +414,11 @@ class Parser(BisonParser):
...
@@ -407,6 +414,11 @@ class Parser(BisonParser):
if
option
in
(
1
,
2
):
# rule: FUNCTION_LPAREN exp RPAREN | FUNCTION exp
if
option
in
(
1
,
2
):
# rule: FUNCTION_LPAREN exp RPAREN | FUNCTION exp
op
=
values
[
0
].
split
(
' '
,
1
)[
0
]
op
=
values
[
0
].
split
(
' '
,
1
)[
0
]
if
op
==
'int'
:
fx
,
x
=
find_integration_variable
(
values
[
1
])
return
Node
(
OP_INT
,
fx
,
x
)
if
op
==
'ln'
:
if
op
==
'ln'
:
return
Node
(
OP_LOG
,
values
[
1
],
Leaf
(
E
))
return
Node
(
OP_LOG
,
values
[
1
],
Leaf
(
E
))
...
@@ -432,54 +444,57 @@ class Parser(BisonParser):
...
@@ -432,54 +444,57 @@ class Parser(BisonParser):
# DERIVATIVE looks like 'd/d*x*' -> extract the 'x'
# DERIVATIVE looks like 'd/d*x*' -> extract the 'x'
return
Node
(
OP_DER
,
values
[
1
],
Leaf
(
values
[
0
][
-
2
]))
return
Node
(
OP_DER
,
values
[
1
],
Leaf
(
values
[
0
][
-
2
]))
if
option
in
(
4
,
5
):
# rule: bracket_derivative | integral
if
option
==
4
:
# rule: bracket_derivative
return
values
[
0
]
return
values
[
0
]
if
option
==
5
:
# rule: INTEGRAL exp
fx
,
x
=
find_integration_variable
(
values
[
1
])
return
Node
(
OP_INT
,
fx
,
x
)
if
option
==
6
:
# rule: INTEGRAL bounds exp
lbnd
,
ubnd
=
values
[
1
]
fx
,
x
=
find_integration_variable
(
values
[
2
])
return
Node
(
OP_INT
,
fx
,
x
,
lbnd
,
ubnd
)
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
%
(
option
,
target
))
# pragma: nocover
def
on_b
racket_derivative
(
self
,
target
,
option
,
names
,
values
):
def
on_b
ounds
(
self
,
target
,
option
,
names
,
values
):
"""
"""
bracket_derivative : LBRACKET exp RBRACKET APOSTROPH
bounds : SUB power TIMES
| bracket_derivative APOSTROPH
"""
"""
if
option
==
0
:
# rule: LBRACKET exp RBRACKET APOSTROPH
if
option
==
0
:
# rule: SUB power
return
Node
(
OP_DER
,
values
[
1
])
return
values
[
1
]
if
option
==
1
:
# rule: bracket_derivative APOSTROPH
return
Node
(
OP_DER
,
values
[
0
])
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
%
(
option
,
target
))
# pragma: nocover
def
on_
integral
(
self
,
target
,
option
,
names
,
values
):
def
on_
power
(
self
,
target
,
option
,
names
,
values
):
"""
"""
integral : INTEGRAL
exp
power : exp POW
exp
"""
"""
#| INTEGRAL SUB exp exp
#| LBRACKET exp RBRACKET SUB exp exp
if
option
==
0
:
# rule: INTEGRAL exp
if
option
==
0
:
# rule: exp POW exp
fx
,
x
=
find_integration_variable
(
values
[
1
])
return
values
[
0
],
values
[
2
]
return
N
(
OP_INT
,
fx
,
x
)
if
option
==
1
:
# rule: INTEGRAL SUB exp exp
if
not
values
[
2
].
is_power
():
# pragma: nocover
raise
BisonSyntaxError
(
'No upper bound specified in "%s".'
%
values
[
2
])
lbnd
,
ubnd
=
values
[
2
]
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
fx
,
x
=
find_integration_variable
(
values
[
3
])
%
(
option
,
target
))
# pragma: nocover
return
N
(
OP_INT
,
fx
,
x
,
lbnd
,
ubnd
)
def
on_bracket_derivative
(
self
,
target
,
option
,
names
,
values
):
"""
bracket_derivative : LBRACKET exp RBRACKET PRIME
| bracket_derivative PRIME
"""
if
option
==
2
:
# rule: LBRACKET exp RBRACKET SUB exp POWER exp
if
option
==
0
:
# rule: LBRACKET exp RBRACKET PRIME
exp
=
values
[
1
]
return
Node
(
OP_DER
,
values
[
1
])
fx
,
x
=
find_integration_variable
(
values
[
1
])
return
N
(
OP_INT_INDEF
,
fx
,
x
,
values
[
4
],
values
[
6
])
if
option
==
1
:
# rule: bracket_derivative PRIME
return
Node
(
OP_DER
,
values
[
0
])
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
%
(
option
,
target
))
# pragma: nocover
...
@@ -489,15 +504,15 @@ class Parser(BisonParser):
...
@@ -489,15 +504,15 @@ class Parser(BisonParser):
binary : exp PLUS exp
binary : exp PLUS exp
| exp TIMES exp
| exp TIMES exp
| exp DIVIDE exp
| exp DIVIDE exp
| exp POW exp
| exp EQ exp
| exp EQ exp
| exp MINUS exp
| exp MINUS exp
| power
"""
"""
if
0
<=
option
<
5
:
# rule: exp {PLUS,TIMES,DIVIDES,POW
,EQ} exp
if
0
<=
option
<
4
:
# rule: exp {PLUS,TIMES,DIVIDE
,EQ} exp
return
Node
(
values
[
1
],
values
[
0
],
values
[
2
])
return
Node
(
values
[
1
],
values
[
0
],
values
[
2
])
if
option
==
5
:
# rule: exp MINUS exp
if
option
==
4
:
# rule: exp MINUS exp
node
=
values
[
2
]
node
=
values
[
2
]
# Add negation to the left-most child
# Add negation to the left-most child
...
@@ -508,10 +523,13 @@ class Parser(BisonParser):
...
@@ -508,10 +523,13 @@ class Parser(BisonParser):
node
.
negated
+=
1
node
.
negated
+=
1
# Explicit call the hook handler on the created unary negation.
# Explicit call the hook handler on the created unary negation.
node
=
self
.
hook_handler
(
'binary'
,
4
,
names
,
values
,
node
)
self
.
hook_handler
(
'binary'
,
3
,
names
,
values
,
node
)
return
Node
(
OP_ADD
,
values
[
0
],
values
[
2
])
return
Node
(
OP_ADD
,
values
[
0
],
values
[
2
])
if
option
==
5
:
# rule: power
return
Node
(
OP_POW
,
*
values
[
0
])
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
%
(
option
,
target
))
# pragma: nocover
...
@@ -591,7 +609,7 @@ class Parser(BisonParser):
...
@@ -591,7 +609,7 @@ class Parser(BisonParser):
")" { returntoken(RPAREN); }
")" { returntoken(RPAREN); }
"[" { returntoken(LBRACKET); }
"[" { returntoken(LBRACKET); }
"]" { returntoken(RBRACKET); }
"]" { returntoken(RBRACKET); }
"'" { returntoken(
APOSTROPH
); }
"'" { returntoken(
PRIME
); }
log_([0-9]+|[a-zA-Z])"*(" { returntoken(FUNCTION_LPAREN); }
log_([0-9]+|[a-zA-Z])"*(" { returntoken(FUNCTION_LPAREN); }
log_([0-9]+|[a-zA-Z])"*" { returntoken(FUNCTION); }
log_([0-9]+|[a-zA-Z])"*" { returntoken(FUNCTION); }
"""
+
operators
+
r"""
"""
+
operators
+
r"""
...
@@ -607,3 +625,4 @@ class Parser(BisonParser):
...
@@ -607,3 +625,4 @@ class Parser(BisonParser):
yywrap() { return(1); }
yywrap() { return(1); }
"""
"""
#int[ ]*"(" { returntoken(FUNCTION_LPAREN); }
src/rules/integrals.py
View file @
cbd37711
...
@@ -2,16 +2,27 @@ from .utils import find_variables, first_sorted_variable, infinity, \
...
@@ -2,16 +2,27 @@ from .utils import find_variables, first_sorted_variable, infinity, \
replace_variable
replace_variable
from
.logarithmic
import
ln
from
.logarithmic
import
ln
#from .goniometry import sin, cos
#from .goniometry import sin, cos
from
..node
import
ExpressionLeaf
as
L
,
OP_INT
from
..node
import
Expression
Node
as
N
,
Expression
Leaf
as
L
,
OP_INT
from
..possibilities
import
Possibility
as
P
,
MESSAGES
from
..possibilities
import
Possibility
as
P
,
MESSAGES
from
..translate
import
_
from
..translate
import
_
#def ader(f, x=None):
def
integral
(
f
,
x
=
None
,
lbnd
=
None
,
ubnd
=
None
):
# """
"""
# Anti-derivative.
Anti-derivative.
# """
"""
# return N(OP_INT, f, x)
params
=
[
f
]
if
x
:
params
.
append
(
x
)
if
lbnd
:
params
.
append
(
lbnd
)
if
ubnd
:
params
.
append
(
ubnd
)
return
N
(
OP_INT
,
*
params
)
def
integral_params
(
integral
):
def
integral_params
(
integral
):
...
...
src/rules/utils.py
View file @
cbd37711
...
@@ -98,6 +98,15 @@ def first_sorted_variable(variables):
...
@@ -98,6 +98,15 @@ def first_sorted_variable(variables):
return
sorted
(
variables
)[
0
]
return
sorted
(
variables
)[
0
]
def
find_variable
(
exp
):
variables
=
find_variables
(
exp
)
if
not
len
(
variables
):
variables
.
add
(
'x'
)
return
L
(
first_sorted_variable
(
variables
))
def
infinity
():
def
infinity
():
return
L
(
INFINITY
)
return
L
(
INFINITY
)
...
...
tests/test_parser.py
View file @
cbd37711
...
@@ -9,6 +9,7 @@ from tests.rulestestcase import tree
...
@@ -9,6 +9,7 @@ from tests.rulestestcase import tree
from
src.rules.goniometry
import
sin
,
cos
from
src.rules.goniometry
import
sin
,
cos
from
src.rules.derivatives
import
der
from
src.rules.derivatives
import
der
from
src.rules.logarithmic
import
log
,
ln
from
src.rules.logarithmic
import
log
,
ln
from
src.rules.integrals
import
integral
class
TestParser
(
unittest
.
TestCase
):
class
TestParser
(
unittest
.
TestCase
):
...
@@ -73,8 +74,8 @@ class TestParser(unittest.TestCase):
...
@@ -73,8 +74,8 @@ class TestParser(unittest.TestCase):
self
.
assertEqual
(
tree
(
'd/dx x ^ 2'
),
der
(
exp
,
x
))
self
.
assertEqual
(
tree
(
'd/dx x ^ 2'
),
der
(
exp
,
x
))
self
.
assertEqual
(
tree
(
'd / dx x ^ 2'
),
der
(
exp
,
x
))
self
.
assertEqual
(
tree
(
'd / dx x ^ 2'
),
der
(
exp
,
x
))
self
.
assertEqual
(
tree
(
'd/dx x ^ 2 + x'
),
der
(
exp
,
x
)
+
x
)
self
.
assertEqual
(
tree
(
'd/dx x ^ 2 + x'
),
der
(
exp
+
x
,
x
)
)
self
.
assertEqual
(
tree
(
'
d/dx (x ^ 2 + x)'
),
der
(
exp
+
x
,
x
)
)
self
.
assertEqual
(
tree
(
'
(d/dx x ^ 2) + x'
),
der
(
exp
,
x
)
+
x
)
self
.
assertEqual
(
tree
(
'd/d'
),
d
/
d
)
self
.
assertEqual
(
tree
(
'd/d'
),
d
/
d
)
# FIXME: self.assertEqual(tree('d(x ^ 2)/dx'), der(exp, x))
# FIXME: self.assertEqual(tree('d(x ^ 2)/dx'), der(exp, x))
...
@@ -97,3 +98,15 @@ class TestParser(unittest.TestCase):
...
@@ -97,3 +98,15 @@ class TestParser(unittest.TestCase):
a
,
t
=
Leaf
(
'a'
),
Leaf
(
token
)
a
,
t
=
Leaf
(
'a'
),
Leaf
(
token
)
self
.
assertEqual
(
tree
(
'a'
+
token
),
a
*
t
)
self
.
assertEqual
(
tree
(
'a'
+
token
),
a
*
t
)
# FIXME: self.assertEqual(tree('a' + token + 'a'), a * t * a)
# FIXME: self.assertEqual(tree('a' + token + 'a'), a * t * a)
def
test_integral
(
self
):
x
,
y
,
dx
,
a
,
b
=
tree
(
'x, y, dx, a, b'
)
self
.
assertEqual
(
tree
(
'int x'
),
integral
(
x
,
x
))
self
.
assertEqual
(
tree
(
'int x2'
),
integral
(
x
**
2
,
x
))
self
.
assertEqual
(
tree
(
'int x2 dx'
),
integral
(
x
**
2
,
x
))
self
.
assertEqual
(
tree
(
'int x2 dy'
),
integral
(
x
**
2
,
y
))
self
.
assertEqual
(
tree
(
'int_a^b x2 dy'
),
integral
(
x
**
2
,
y
,
a
,
b
))
self
.
assertEqual
(
tree
(
'int_(a-b)^(a+b) x2'
),
integral
(
x
**
2
,
x
,
a
-
b
,
a
+
b
))
tests/test_rules_integrals.py
View file @
cbd37711
...
@@ -10,36 +10,36 @@ from tests.rulestestcase import RulesTestCase, tree
...
@@ -10,36 +10,36 @@ from tests.rulestestcase import RulesTestCase, tree
class
TestRulesIntegrals
(
RulesTestCase
):
class
TestRulesIntegrals
(
RulesTestCase
):
def
test_integral_params
(
self
):
def
test_integral_params
(
self
):
f
,
x
=
root
=
tree
(
'int
(fx, x)
'
)
f
,
x
=
root
=
tree
(
'int
fx dx
'
)
self
.
assertEqual
(
integral_params
(
root
),
(
f
,
x
))
self
.
assertEqual
(
integral_params
(
root
),
(
f
,
x
))
root
=
tree
(
'int
(fx)
'
)
root
=
tree
(
'int
fx
'
)
self
.
assertEqual
(
integral_params
(
root
),
(
f
,
x
))
self
.
assertEqual
(
integral_params
(
root
),
(
f
,
x
))
root
=
tree
(
'int
(3)
'
)
root
=
tree
(
'int
3
'
)
self
.
assertEqual
(
integral_params
(
root
),
(
3
,
None
))
self
.
assertEqual
(
integral_params
(
root
),
(
3
,
x
))
def
test_choose_constant
(
self
):
def
test_choose_constant
(
self
):
a
,
b
,
c
=
tree
(
'a, b, c'
)
a
,
b
,
c
=
tree
(
'a, b, c'
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
(x ^ n, x)
'
)),
c
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
x ^ n
'
)),
c
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
(x ^ c, x)
'
)),
a
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
x ^ c
'
)),
a
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
(a ^ c, a)
'
)),
b
)
self
.
assertEqual
(
choose_constant
(
tree
(
'int
a ^ c da
'
)),
b
)
def
test_match_integrate_variable_power
(
self
):
def
test_match_integrate_variable_power
(
self
):
for
root
in
tree
(
'int
(x ^ n, x), int(x ^ n)
'
):
for
root
in
tree
(
'int
x ^ n, int x ^ n
'
):
self
.
assertEqualPos
(
match_integrate_variable_power
(
root
),
self
.
assertEqualPos
(
match_integrate_variable_power
(
root
),
[
P
(
root
,
integrate_variable_root
)])
[
P
(
root
,
integrate_variable_root
)])
for
root
in
tree
(
'int
(g ^ x, x), int(g ^ x)
'
):
for
root
in
tree
(
'int
g ^ x, int g ^ x
'
):
self
.
assertEqualPos
(
match_integrate_variable_power
(
root
),
self
.
assertEqualPos
(
match_integrate_variable_power
(
root
),
[
P
(
root
,
integrate_variable_exponent
)])
[
P
(
root
,
integrate_variable_exponent
)])
def
test_integrate_variable_root
(
self
):
def
test_integrate_variable_root
(
self
):
((
x
,
n
),
),
c
=
root
,
c
=
tree
(
'int(x ^ n)
, c'
)
((
x
,
n
),
x
),
c
=
root
,
c
=
tree
(
'int x ^ n
, c'
)
self
.
assertEqual
(
integrate_variable_root
(
root
,
()),
self
.
assertEqual
(
integrate_variable_root
(
root
,
()),
x
**
(
n
+
1
)
/
(
n
+
1
)
+
c
)
x
**
(
n
+
1
)
/
(
n
+
1
)
+
c
)
def
test_integrate_variable_exponent
(
self
):
def
test_integrate_variable_exponent
(
self
):
((
g
,
x
),
),
c
=
root
,
c
=
tree
(
'int(g ^ x)
, c'
)
((
g
,
x
),
x
),
c
=
root
,
c
=
tree
(
'int g ^ x
, c'
)
self
.
assertEqual
(
integrate_variable_exponent
(
root
,
()),
self
.
assertEqual
(
integrate_variable_exponent
(
root
,
()),
g
**
x
/
ln
(
g
)
+
c
)
g
**
x
/
ln
(
g
)
+
c
)
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