#13501: Fix two bugs in sage.misc.c3's implementation of the algorithm C3
-------------------------------------------+--------------------------------
Reporter: nthiery | Owner:
Type: defect | Status: needs_review
Priority: major | Milestone: sage-5.4
Component: categories | Resolution:
Keywords: method resolution order | Work issues:
Report Upstream: N/A | Reviewers: Simon King
Authors: Nicolas M. ThiƩry | Merged in:
Dependencies: #12895 | Stopgaps:
-------------------------------------------+--------------------------------
Comment (by SimonKing):
Using `<size_t><void *>` rather than the objects seems to work, speed-
wise! With your benchmark, I get
{{{
ncalls tottime percall cumtime percall filename:lineno(function)
7000/500 0.197 0.000 0.671 0.001 {sage.misc.c3.C3_algorithm}
}}}
using the following patch:
{{{
diff --git a/sage/misc/c3.pyx b/sage/misc/c3.pyx
--- a/sage/misc/c3.pyx
+++ b/sage/misc/c3.pyx
@@ -186,16 +186,20 @@
# ``tails'') . Each tail is stored reversed, so that we can use a
# cheap pop() in lieue of pop(0). A duplicate of the tail is
# stored as a set in ``tailsets`` for cheap membership testing.
+ # Since we actually want comparison by identity, not equality,
+ # what we store is the set of memory locations of objects
+ cdef object O, X
cdef list tails = [getattr(obj, attribute) for obj in args]
tails.append(args)
- tails = [list(reversed(tail)) for tail in tails]
- cdef list heads = [tail.pop() for tail in tails]
- cdef list tailsets = [set(tail) for tail in tails]
+ tails = [list(reversed(tail)) for tail in tails]
+ cdef list heads = [tail.pop() for tail in tails]
+ cdef list tailsets = [set([<size_t><void *>O for O in tail]) for tail
in tails]
cdef int i, j, nbheads
nbheads = len(heads)
- cdef object O, X
cdef bint next_item_found
+ cdef set tail_set
+ cdef list tail_list
while nbheads:
for i from 0 <= i < nbheads:
@@ -205,7 +209,8 @@
for j from 0 <= j < nbheads:
if j == i:
continue
- if O in tailsets[j]:
+ tail_set = tailsets[j]
+ if <size_t><void *>O in tail_set:
next_item_found = False
break
if next_item_found:
@@ -215,11 +220,13 @@
# j goes down so that ``del heads[j]`` does not screw up
the numbering
for j from nbheads > j >= 0:
if heads[j] is O:
- try:
- X = tails[j].pop()
+ tail_list = tails[j]
+ if tail_list:
+ X = tail_list.pop()
heads[j] = X
- tailsets[j].remove(X)
- except IndexError:
+ tail_set = tailsets[j]
+ tail_set.remove(<size_t><void *>X)
+ else:
del heads[j]
del tails[j]
del tailsets[j]
}}}
I am now running `make ptest` with that patch, and if it works, then I'll
post it here "officially", and we can start cross-reviewing.
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/13501#comment:20>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en.