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
0d06e0ae
Commit
0d06e0ae
authored
Dec 12, 2011
by
Taddeus Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented retrieval possibilities successfully.
parent
206246be
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
155 additions
and
101 deletions
+155
-101
src/node.py
src/node.py
+23
-15
src/possibilities.py
src/possibilities.py
+6
-1
src/rules/poly.py
src/rules/poly.py
+66
-75
tests/test_node.py
tests/test_node.py
+10
-10
tests/test_rules_poly.py
tests/test_rules_poly.py
+50
-0
No files found.
src/node.py
View file @
0d06e0ae
...
...
@@ -93,25 +93,29 @@ class ExpressionNode(Node, ExpressionBase):
node
.
parent
=
self
.
parent
self
.
parent
=
None
def
get_order
(
self
):
if
self
.
is_power
()
and
self
[
0
].
is_identifier
()
and
self
[
1
].
is_leaf
():
# a ^ 3
return
(
self
[
0
].
value
,
self
[
1
].
value
,
1
)
if
not
self
.
op
&
OP_MUL
:
def
get_polynome
(
self
):
"""
Identifier nodes of all polynomes, tuple format is:
(identifier, exponent, coefficient, literal_exponent)
"""
if
self
.
is_power
():
# a ^ e
return
(
self
[
0
],
self
[
1
],
ExpressionLeaf
(
1
),
True
)
if
self
.
op
!=
OP_MUL
:
return
for
n0
,
n1
in
[(
0
,
1
),
(
1
,
0
)]:
if
self
[
n0
].
is_numeric
():
if
self
[
n1
].
is_identifier
():
#
2
* a
return
(
self
[
n1
]
.
value
,
1
,
self
[
n0
].
valu
e
)
#
c
* a
return
(
self
[
n1
]
,
ExpressionLeaf
(
1
),
self
[
n0
],
Fals
e
)
elif
self
[
n1
].
is_power
():
#
2 * a ^ 3
#
c * a ^ e
coeff
,
power
=
self
root
,
exponent
=
power
if
power
[
0
].
is_identifier
()
and
power
[
1
].
is_leaf
():
return
(
power
[
0
].
value
,
power
[
1
].
value
,
coeff
.
value
)
return
(
root
,
exponent
,
coeff
,
True
)
def
get_scope
(
self
):
""""""
...
...
@@ -119,7 +123,7 @@ class ExpressionNode(Node, ExpressionBase):
#op = OP_ADD | OP_SUB if self.op & (OP_ADD | OP_SUB) else self.op
for
child
in
self
:
if
not
child
.
is_leaf
()
and
child
.
op
&
self
.
op
:
if
not
child
.
is_leaf
()
and
child
.
op
==
self
.
op
:
scope
+=
child
.
get_scope
()
else
:
scope
.
append
(
child
)
...
...
@@ -133,9 +137,13 @@ class ExpressionLeaf(Leaf, ExpressionBase):
self
.
type
=
TYPE_MAP
[
type
(
args
[
0
])]
def
get_order
(
self
):
if
self
.
is_identifier
():
return
(
self
.
value
,
1
,
1
)
def
get_polynome
(
self
):
"""
Identifier nodes of all polynomes, tuple format is:
(identifier, exponent, coefficient, literal_exponent)
"""
# a = 1 * a ^ 1
return
(
self
,
ExpressionLeaf
(
1
),
ExpressionLeaf
(
1
),
False
)
def
replace
(
self
,
node
):
if
not
hasattr
(
self
,
'parent'
):
...
...
src/possibilities.py
View file @
0d06e0ae
...
...
@@ -11,9 +11,14 @@ class Possibility(object):
def
__repr__
(
self
):
return
str
(
self
)
# TODO: Add unit tests
def
__eq__
(
self
,
other
):
self_arg0
,
self_arg1
=
zip
(
*
self
.
args
)
other_arg0
,
other_arg1
=
zip
(
*
other
.
args
)
return
self
.
handler
==
other
.
handler
\
and
map
(
hash
,
self
.
args
)
==
map
(
hash
,
other
.
args
)
and
self_arg1
==
other_arg1
\
and
map
(
hash
,
self_arg0
)
==
map
(
hash
,
other_arg0
)
def
filter_duplicates
(
items
):
...
...
src/rules/poly.py
View file @
0d06e0ae
...
...
@@ -11,28 +11,25 @@ def match_expand(node):
a * (b + c) -> ab + ac
"""
assert
node
.
type
==
TYPE_OPERATOR
assert
node
.
op
&
OP_MUL
assert
node
.
op
==
OP_MUL
# TODO: fix!
return
[]
p
=
[]
# 'a' parts
left
=
[]
# '(b + c)' parts
right
=
[]
p
=
[]
a
=
[]
bc
=
[]
for
n
in
node
.
get_scope
():
if
node
.
type
==
TYPE_OPERATOR
:
if
n
.
op
&
OP_ADD
:
right
.
append
(
n
)
else
:
left
.
append
(
n
)
if
n
.
is_leaf
():
a
.
append
(
n
)
elif
n
.
op
==
OP_ADD
:
bc
.
append
(
n
)
if
len
(
left
)
and
len
(
right
)
:
for
l
in
left
:
for
r
in
right
:
p
.
append
(
P
(
node
,
expand_single
,
l
,
r
))
if
a
and
bc
:
for
a_node
in
a
:
for
bc_node
in
bc
:
p
.
append
(
P
(
node
,
expand_single
,
a_node
,
bc_node
))
return
p
...
...
@@ -64,83 +61,77 @@ def match_combine_factors(node):
k0 * v ^ n + exp + k1 * v ^ n -> exp + (k0 + k1) * v ^ n
"""
assert
node
.
type
==
TYPE_OPERATOR
assert
node
.
op
&
OP_ADD
assert
node
.
op
==
OP_ADD
p
=
[]
# Collect all nodes that can be combined
# Numeric leaves
numerics
=
[]
# Identifier leaves of all orders, tuple format is;
# (identifier, exponent, coefficient)
orders
=
[]
# Collect all nodes that can be combined:
# a ^ e = 1 * a ^ e
# c * a = c * a ^ 1
# c * a ^ e
# a = 1 * a ^ 1
#
# Identifier nodes of all polynomes, tuple format is:
# (identifier, exponent, coefficient, literal_coefficient)
polys
=
[]
for
n
in
node
.
get_scope
():
if
not
n
.
is_leaf
():
order
=
n
.
get_order
()
if
order
:
orders
.
append
(
order
)
elif
n
.
is_numeric
():
numerics
.
append
(
n
)
elif
n
.
is_identifier
():
orders
.
append
((
n
.
value
,
1
,
1
))
if
len
(
numerics
)
>
1
:
for
num0
,
num1
in
combinations
(
numerics
,
2
):
p
.
append
(
P
(
node
,
combine_numerics
,
(
num0
,
num1
)))
if
len
(
orders
)
>
1
:
for
order0
,
order1
in
combinations
(
orders
,
2
):
id0
,
exponent0
,
coeff0
=
order0
id1
,
exponent1
,
coeff1
=
order1
if
id0
==
id1
and
exponent0
==
exponent1
:
# Same identifier and exponent -> combine coefficients
args
=
order0
+
(
coeff1
,)
p
.
append
(
P
(
node
,
combine_orders
,
args
))
return
p
polynome
=
n
.
get_polynome
()
if
polynome
:
polys
.
append
((
n
,
polynome
))
def
combine_numerics
(
root
,
args
):
"""
Combine two numeric leaves in an n-ary plus.
# Each combination of powers of the same value and polynome can be added
if
len
(
polys
)
>=
2
:
for
left
,
right
in
combinations
(
polys
,
2
):
r0
,
e0
,
c0
=
left
[
1
][:
3
]
r1
,
e1
,
c1
=
right
[
1
][:
3
]
Example:
>>> 3 + 4 -> 7
"""
others
=
list
(
set
(
root
.
get_scope
())
-
set
(
args
))
value
=
sum
([
n
.
value
for
n
in
args
])
if
(
r0
.
is_numeric
()
and
r1
.
is_numeric
()
and
e0
==
e1
==
Leaf
(
1
))
\
or
(
r0
==
r1
and
e0
==
e1
):
# Both numeric and same exponent -> combine coefficients and
# roots, or:
# Same identifier and exponent -> combine coefficients
p
.
append
(
P
(
node
,
combine_polynomes
,
(
left
,
right
)))
return
nary_node
(
'+'
,
others
+
[
Leaf
(
value
)])
return
p
def
combine_
order
s
(
root
,
args
):
def
combine_
polynome
s
(
root
,
args
):
"""
Combine two identifier multiplications of any
order
in an n-ary plus.
Combine two identifier multiplications of any
polynome
in an n-ary plus.
Example:
3x + 4x -> 7x
c * a ^ b + d * a ^ b -> (c + d) * a ^ b
"""
identifier
,
exponent
,
coeff0
,
coeff1
,
others
=
args
left
,
right
=
args
nl
,
pl
=
left
nr
,
pr
=
right
c0
,
r0
,
e0
=
pl
c1
,
r1
,
e1
=
pr
coeff
=
coeff0
+
coeff1
scope
=
root
.
get_scope
()
if
not
exponent
:
# a ^ 0 -> 1
ident
=
Leaf
(
1
)
elif
exponent
==
1
:
# a ^ 1 -> a
ident
=
Leaf
(
identifier
)
if
r0
.
is_numeric
()
and
r1
.
is_numeric
()
and
e0
==
e1
==
1
:
new_root
=
Leaf
(
r0
.
value
+
r1
.
value
)
else
:
# a ^ n -> a ^ n
ident
=
Node
(
'^'
,
Leaf
(
identifier
),
Leaf
(
exponent
))
new_root
=
r0
if
coeff
==
1
:
combined
=
ident
if
pl
[
3
]
or
pr
[
3
]:
# literal a ^ 1 -> a ^ 1
power
=
Node
(
'^'
,
pl
[
0
],
pl
[
1
])
else
:
combined
=
Node
(
'*'
,
Leaf
(
coeff
),
ident
)
# nonliteral a ^ 1 -> a
power
=
pl
[
0
]
# replacement: (c + d) * a ^ b
# a, b and c are from 'left', d is from 'right'.
replacement
=
Node
(
'*'
,
Node
(
'+'
,
pl
[
2
],
pr
[
2
]),
power
)
# Replace the left node with the new expression
scope
[
scope
.
index
(
nl
)]
=
replacement
# Remove the right node
scope
.
remove
(
nr
)
return
nary_node
(
'+'
,
others
+
[
combined
]
)
return
nary_node
(
'+'
,
scope
)
tests/test_node.py
View file @
0d06e0ae
...
...
@@ -51,23 +51,23 @@ class TestNode(unittest.TestCase):
self
.
assertTrue
(
L
(
1.5
).
is_numeric
())
self
.
assertFalse
(
L
(
'a'
).
is_numeric
())
def
test_get_
order
_identifier
(
self
):
self
.
assertEqual
(
L
(
'a'
).
get_
order
(),
(
'a'
,
1
,
1
))
def
test_get_
polynome
_identifier
(
self
):
self
.
assertEqual
(
L
(
'a'
).
get_
polynome
(),
(
L
(
'a'
),
L
(
1
),
L
(
1
),
False
))
def
test_get_
order
_None
(
self
):
self
.
assertIsNone
(
L
(
1
).
get_order
())
def
test_get_
polynome
_None
(
self
):
self
.
assertIsNone
(
N
(
'+'
).
get_polynome
())
def
test_get_
order
_power
(
self
):
def
test_get_
polynome
_power
(
self
):
power
=
N
(
'^'
,
L
(
'a'
),
L
(
2
))
self
.
assertEqual
(
power
.
get_
order
(),
(
'a'
,
2
,
1
))
self
.
assertEqual
(
power
.
get_
polynome
(),
(
L
(
'a'
),
L
(
2
),
L
(
1
),
True
))
def
test_get_
order
_coefficient_exponent_int
(
self
):
def
test_get_
polynome
_coefficient_exponent_int
(
self
):
times
=
N
(
'*'
,
L
(
3
),
N
(
'^'
,
L
(
'a'
),
L
(
2
)))
self
.
assertEqual
(
times
.
get_
order
(),
(
'a'
,
2
,
3
))
self
.
assertEqual
(
times
.
get_
polynome
(),
(
L
(
'a'
),
L
(
2
),
L
(
3
),
True
))
def
test_get_
order
_coefficient_exponent_id
(
self
):
def
test_get_
polynome
_coefficient_exponent_id
(
self
):
times
=
N
(
'*'
,
L
(
3
),
N
(
'^'
,
L
(
'a'
),
L
(
'b'
)))
self
.
assertEqual
(
times
.
get_
order
(),
(
'a'
,
'b'
,
3
))
self
.
assertEqual
(
times
.
get_
polynome
(),
(
L
(
'a'
),
L
(
'b'
),
L
(
3
),
True
))
def
test_get_scope_binary
(
self
):
plus
=
N
(
'+'
,
*
self
.
l
[:
2
])
...
...
tests/test_rules_poly.py
0 → 100644
View file @
0d06e0ae
import
unittest
from
src.node
import
ExpressionNode
as
N
,
ExpressionLeaf
as
L
from
src.rules.poly
import
match_combine_factors
,
combine_polynomes
from
src.possibilities
import
Possibility
as
P
from
src.parser
import
Parser
from
tests.parser
import
ParserWrapper
def
tree
(
exp
,
**
kwargs
):
return
ParserWrapper
(
Parser
,
**
kwargs
).
run
([
exp
])
class
TestRulesPoly
(
unittest
.
TestCase
):
#def test_match_combine_factors_numeric_combinations(self):
# l0, l1, l2 = L(1), L(2), L(2)
# plus = N('+', N('+', l0, l1), l2)
# p = match_combine_factors(plus)
# self.assertEqualPos(p, [P(plus, combine_polynomes, (l0, l1)),
# P(plus, combine_polynomes, (l0, l2)),
# P(plus, combine_polynomes, (l1, l2))])
def
assertEqualPos
(
self
,
possibilities
,
expected
):
self
.
assertEqual
(
len
(
possibilities
),
len
(
expected
))
for
p
,
e
in
zip
(
possibilities
,
expected
):
self
.
assertEqual
(
p
.
root
,
e
.
root
)
self
.
assertEqual
(
p
,
e
)
def
test_numeric
(
self
):
l1
,
l2
=
root
=
tree
(
'1+2'
)
self
.
assertEqualPos
(
match_combine_factors
(
root
),
[
P
(
root
,
combine_polynomes
,
((
l1
,
(
l1
,
l1
,
l1
,
False
)),
(
l2
,
(
l2
,
l1
,
l1
,
False
))))])
a1
,
a2
=
root
=
tree
(
'a+a'
)
self
.
assertEqualPos
(
match_combine_factors
(
root
),
[
P
(
root
,
combine_polynomes
,
((
a1
,
(
a1
,
l1
,
l1
,
False
)),
(
a2
,
(
a2
,
l1
,
l1
,
False
))))])
a1
,
a2
=
root
=
tree
(
'a+2a'
)
self
.
assertEqualPos
(
match_combine_factors
(
root
),
[
P
(
root
,
combine_polynomes
,
((
a1
,
(
a1
,
l1
,
l1
,
False
)),
(
a2
,
(
a2
[
1
],
l1
,
l2
,
False
))))])
a1
,
a2
=
root
=
tree
(
'a2+a2'
)
self
.
assertEqualPos
(
match_combine_factors
(
root
),
[
P
(
root
,
combine_polynomes
,
((
a1
,
(
a1
[
0
],
l2
,
l1
,
True
)),
(
a2
,
(
a2
[
0
],
l2
,
l1
,
True
))))])
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