Skip to content

Commit 93619a4

Browse files
author
Release Manager
committed
Trac #33959: some improvements in sandpile.py
We try to avoid as much as possible operations like `[g.vertices().index(v) for v in g.vertices()]`. A serious improvement would be to avoid using `.vertices()` and to accept any ordering of the vertices, but this requires extra changes in graph methods such as `.laplacian_matrix()`. URL: https://trac.sagemath.org/33959 Reported by: dcoudert Ticket author(s): David Coudert Reviewer(s): Frédéric Chapoton
2 parents d319478 + ddda2f4 commit 93619a4

File tree

1 file changed

+39
-42
lines changed

1 file changed

+39
-42
lines changed

src/sage/sandpiles/sandpile.py

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -616,21 +616,24 @@ def __init__(self, g, sink=None):
616616
h = g.to_dictionary(multiple_edges=True)
617617
g = {i: dict(Counter(h[i])) for i in h}
618618
else:
619-
vi = {v: g.vertices().index(v) for v in g.vertices()}
619+
vi = {v: i for i, v in enumerate(g.vertices())}
620620
ad = g.weighted_adjacency_matrix()
621-
g = {v: {w: ad[vi[v], vi[w]] for w in g.neighbors(v)}
622-
for v in g.vertices()}
621+
g = {v: {w: ad[vi[v], vi[w]] for w in g.neighbor_iterator(v)}
622+
for v in g}
623623
else:
624624
raise SyntaxError(g)
625625

626626
# create digraph and initialize some variables
627627
DiGraph.__init__(self, g, weighted=True)
628628
self._dict = deepcopy(g)
629+
vertices = self.vertices()
629630
if sink is None:
630-
sink = self.vertices()[0]
631-
self._sink = sink # key for sink
632-
self._sink_ind = self.vertices().index(sink)
633-
self._nonsink_vertices = deepcopy(self.vertices())
631+
self._sink = vertices[0]
632+
self._sink_ind = 0
633+
else:
634+
self._sink = sink # key for sink
635+
self._sink_ind = vertices.index(sink)
636+
self._nonsink_vertices = vertices
634637
del self._nonsink_vertices[self._sink_ind]
635638
# compute Laplacians:
636639
self._laplacian = self.laplacian_matrix(indegree=False)
@@ -1041,8 +1044,8 @@ def _set_in_degrees(self):
10411044
sage: '_in_degrees' in s.__dict__
10421045
True
10431046
"""
1044-
self._in_degrees = {v: 0 for v in self.vertices()}
1045-
for e in self.edges():
1047+
self._in_degrees = {v: 0 for v in self}
1048+
for e in self.edge_iterator():
10461049
self._in_degrees[e[1]] += e[2]
10471050

10481051
def in_degree(self, v=None):
@@ -1977,13 +1980,10 @@ def reorder_vertices(self):
19771980
sage: T.dict()
19781981
{0: {1: 1}, 1: {0: 1, 2: 1}, 2: {0: 1}}
19791982
"""
1980-
1981-
# first order the vertices according to their distance from the sink
1982-
verts = sorted(self.vertices(),
1983-
key=lambda v: self.distance(v, self._sink), reverse=True)
1984-
perm = {}
1985-
for i in range(len(verts)):
1986-
perm[verts[i]] = i
1983+
# first order the vertices according to their distance to the sink
1984+
distance_to_sink = self.reverse().shortest_path_lengths(self._sink)
1985+
verts = sorted(self, key=lambda v: distance_to_sink[v], reverse=True)
1986+
perm = {v: i for i, v in enumerate(verts)}
19871987
old = self.dict()
19881988
new = {}
19891989
for i in old:
@@ -2455,12 +2455,13 @@ def _set_ring(self):
24552455
sage: '_ring' in S.__dict__
24562456
True
24572457
"""
2458-
# first order the vertices according to their distance from the sink
2459-
verts = sorted(self.vertices(),
2460-
key=lambda v: self.distance(v, self._sink))
2458+
# first order the vertices according to their distance to the sink
2459+
distance_to_sink = self.reverse().shortest_path_lengths(self._sink)
2460+
verts = sorted(self, key=lambda v: distance_to_sink[v])
24612461

24622462
# variable i refers to the i-th vertex in self.vertices()
2463-
names = [self.vertices().index(v) for v in reversed(verts)]
2463+
vertex_to_int = {v: i for i, v in enumerate(self.vertices())}
2464+
names = [vertex_to_int[v] for v in reversed(verts)]
24642465

24652466
vars = ''
24662467
for i in names:
@@ -2471,11 +2472,11 @@ def _set_ring(self):
24712472
# create the ideal
24722473
gens = []
24732474
for i in self.nonsink_vertices():
2474-
new_gen = 'x' + str(self.vertices().index(i))
2475+
new_gen = 'x' + str(vertex_to_int[i])
24752476
new_gen += '^' + str(self.out_degree(i))
24762477
new_gen += '-'
24772478
for j in self._dict[i]:
2478-
new_gen += 'x' + str(self.vertices().index(j))
2479+
new_gen += 'x' + str(vertex_to_int[j])
24792480
new_gen += '^' + str(self._dict[i][j]) + '*'
24802481
new_gen = new_gen[:-1]
24812482
gens.append(new_gen)
@@ -3535,7 +3536,7 @@ def fire_vertex(self, v):
35353536
"""
35363537
c = dict(self)
35373538
c[v] -= self._sandpile.out_degree(v)
3538-
for e in self._sandpile.outgoing_edges(v):
3539+
for e in self._sandpile.outgoing_edge_iterator(v):
35393540
if e[1] != self._sandpile.sink():
35403541
c[e[1]] += e[2]
35413542
return SandpileConfig(self._sandpile,c)
@@ -3571,7 +3572,7 @@ def fire_script(self, sigma):
35713572
for i in range(len(sigma)):
35723573
v = self._vertices[i]
35733574
c[v] -= sigma[i]*self._sandpile.out_degree(v)
3574-
for e in self._sandpile.outgoing_edges(v):
3575+
for e in self._sandpile.outgoing_edge_iterator(v):
35753576
if e[1] != self._sandpile.sink():
35763577
c[e[1]] += sigma[i]*e[2]
35773578
return SandpileConfig(self._sandpile, c)
@@ -3612,7 +3613,7 @@ def fire_unstable(self):
36123613
c = dict(self)
36133614
for v in self.unstable():
36143615
c[v] -= self._sandpile.out_degree(v)
3615-
for e in self._sandpile.outgoing_edges(v):
3616+
for e in self._sandpile.outgoing_edge_iterator(v):
36163617
if e[1] != self._sandpile.sink():
36173618
c[e[1]] += e[2]
36183619
return SandpileConfig(self._sandpile,c)
@@ -3638,7 +3639,7 @@ def _set_stabilize(self):
36383639
dm = divmod(c[v],s.out_degree(v))
36393640
c[v] = dm[1]
36403641
firing_vector[v] += dm[0]
3641-
for e in s.outgoing_edges(v):
3642+
for e in s.outgoing_edge_iterator(v):
36423643
if e[1] != s.sink():
36433644
c[e[1]] += dm[0]* e[2]
36443645
unstable = c.unstable()
@@ -4156,8 +4157,8 @@ def show(self, sink=True, colors=True, heights=False, directed=None, **kwds):
41564157
T.delete_vertex(self.sandpile().sink())
41574158
if heights:
41584159
a = {}
4159-
for i in T.vertices():
4160-
if i==self.sandpile().sink():
4160+
for i in T:
4161+
if i == self.sandpile().sink():
41614162
a[i] = str(i)
41624163
else:
41634164
a[i] = str(i)+":"+str(self[i])
@@ -4272,12 +4273,10 @@ def __init__(self, S, D):
42724273
"""
42734274
if len(D) == S.num_verts():
42744275
if type(D) in [dict, SandpileDivisor, SandpileConfig]:
4275-
dict.__init__(self,dict(D))
4276+
dict.__init__(self, dict(D))
42764277
elif isinstance(D, list):
4277-
div = {}
4278-
for i in range(S.num_verts()):
4279-
div[S.vertices()[i]] = D[i]
4280-
dict.__init__(self,div)
4278+
div = {v: D[i] for i, v in enumerate(S.vertices())}
4279+
dict.__init__(self, div)
42814280
else:
42824281
raise SyntaxError(D)
42834282

@@ -4809,8 +4808,8 @@ def fire_vertex(self, v):
48094808
"""
48104809
D = dict(self)
48114810
D[v] -= self._sandpile.out_degree(v)
4812-
for e in self._sandpile.outgoing_edges(v):
4813-
D[e[1]]+=e[2]
4811+
for e in self._sandpile.outgoing_edge_iterator(v):
4812+
D[e[1]] += e[2]
48144813
return SandpileDivisor(self._sandpile,D)
48154814

48164815
def fire_script(self, sigma):
@@ -4844,8 +4843,8 @@ def fire_script(self, sigma):
48444843
for i in range(len(sigma)):
48454844
v = self._vertices[i]
48464845
D[v] -= sigma[i]*self._sandpile.out_degree(v)
4847-
for e in self._sandpile.outgoing_edges(v):
4848-
D[e[1]]+=sigma[i]*e[2]
4846+
for e in self._sandpile.outgoing_edge_iterator(v):
4847+
D[e[1]] += sigma[i] * e[2]
48494848
return SandpileDivisor(self._sandpile, D)
48504849

48514850
def unstable(self):
@@ -4884,8 +4883,8 @@ def fire_unstable(self):
48844883
D = dict(self)
48854884
for v in self.unstable():
48864885
D[v] -= self._sandpile.out_degree(v)
4887-
for e in self._sandpile.outgoing_edges(v):
4888-
D[e[1]]+=e[2]
4886+
for e in self._sandpile.outgoing_edge_iterator(v):
4887+
D[e[1]] += e[2]
48894888
return SandpileDivisor(self._sandpile,D)
48904889

48914890
def _set_q_reduced(self):
@@ -6052,9 +6051,7 @@ def show(self, heights=True, directed=None, **kwds):
60526051
T = Graph(self.sandpile())
60536052

60546053
if heights:
6055-
a = {}
6056-
for i in T.vertices():
6057-
a[i] = str(i) + ":" + str(T[i])
6054+
a = {i: str(i) + ":" + str(T[i]) for i in T}
60586055
T.relabel(a)
60596056
T.show(**kwds)
60606057

0 commit comments

Comments
 (0)