Skip to content

Commit

Permalink
sagemathgh-38427: graphs: make init_short_digraph always sort neighbo…
Browse files Browse the repository at this point in the history
…rs but without the extra log complexity

    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

This PR improve the `init_short_digraph` function that is used to
initialize `StaticSparseCGraph` (used for immutable `Graph` and
`DiGraph`).

Before, a boolean parameter `sort_neighbors` was used to specify if we
wanted to sort the neighbors or not. It implied an extra `log` in the
complexity (as `qsort` was called).
With this PR, the neighbors are always sorted at no extra cost. It is
done by appending to the neighbors list the vertices in the correct
order so the call to `qsort` is not needed anymore.

This PR partly reverts sagemath#38198 and mostly reverts sagemath#37662

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [ ] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#38427
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
  • Loading branch information
Release Manager committed Sep 7, 2024
2 parents 6e24709 + d82009e commit c1fbf31
Show file tree
Hide file tree
Showing 28 changed files with 267 additions and 292 deletions.
15 changes: 8 additions & 7 deletions src/sage/algebras/lie_algebras/bgg_dual_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,16 @@ def degree_on_basis(self, m):
sage: M = g.verma_module(La[1] + La[4] - 1/3*La[5])
sage: Mc = M.dual()
sage: elt = Mc.an_element(); elt
f[-alpha[5]]^2*f[-alpha[4]]^2*f[-alpha[3]]^3*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^*
+ 2*f[-alpha[5]]*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^*
+ 3*f[-alpha[4]]*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^*
+ v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^*
f[-alpha[2]]^2*f[-alpha[5]]^2*f[-alpha[3]]^3*v[Lambda[1]
+ Lambda[4] - 1/3*Lambda[5]]^* + 2*f[-alpha[2]]*v[Lambda[1]
+ Lambda[4] - 1/3*Lambda[5]]^* + 3*f[-alpha[5]]*v[Lambda[1]
+ Lambda[4] - 1/3*Lambda[5]]^* + v[Lambda[1] + Lambda[4]
- 1/3*Lambda[5]]^*
sage: [M.degree_on_basis(m) for m in elt.support()]
[Lambda[1] + 3*Lambda[2] - 2*Lambda[3] - 4/3*Lambda[5],
[3*Lambda[1] - Lambda[2] - 2*Lambda[3] + 4*Lambda[4] - 4/3*Lambda[5],
Lambda[1] + Lambda[4] - 1/3*Lambda[5],
Lambda[1] + Lambda[3] + Lambda[4] - 7/3*Lambda[5],
Lambda[1] + Lambda[3] - Lambda[4] - 1/3*Lambda[5]]
2*Lambda[1] - 2*Lambda[2] + Lambda[3] + Lambda[4] - 1/3*Lambda[5],
Lambda[1] + Lambda[3] + Lambda[4] - 7/3*Lambda[5]]
"""
return self._module.degree_on_basis(m)

Expand Down
4 changes: 2 additions & 2 deletions src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,8 @@ def _transpose_on_basis(self, m):
sage: f1, f2, f3, f4, f5, f6 = U.f()
sage: e1, e2, e3, e4, e5, e6 = U.e()
sage: elt = e1 * e4^2 * f1 * f2^3
sage: U._transpose_on_basis(elt.support()[0])
PBW[alpha[2]]^3*PBW[alpha[1]]*PBW[-alpha[4]]^2*PBW[-alpha[1]]
sage: U._transpose_on_basis(elt.support()[0]) == e2^3*e1*f1*f4^2
True
"""
I = self._indices
basis_mapping = self._g._transpose_basis_mapping
Expand Down
12 changes: 6 additions & 6 deletions src/sage/categories/regular_crystals.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,13 +838,13 @@ def dual_equivalence_class(self, index_set=None):
([[1, 3], [2, 4]], [[1, 2], [3, 4]], 3)]
sage: T = crystals.Tableaux(['A',4], shape=[3,2])
sage: G = T(2,1,4,3,5).dual_equivalence_class()
sage: G.edges(sort=True)
[([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 3),
sage: G.edges(sort=True,sort_vertices=True)
[([[1, 3, 4], [2, 5]], [[1, 3, 5], [2, 4]], 4),
([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 4)]
([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 2),
([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 3),
([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 3),
([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 4)]
"""
if index_set is None:
index_set = self.index_set()
Expand Down
6 changes: 3 additions & 3 deletions src/sage/combinat/growth.py
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,7 @@ def _check_duality(self, n):
...
ValueError: D U - U D differs from 1 I for vertex [2]:
D U = [[2]]
U D + 1 I = [[1, 1], [2], [2]]
U D + 1 I = [[2], [1, 1], [2]]
"""
if self.has_multiple_edges:
def check_vertex(w, P, Q):
Expand Down Expand Up @@ -1841,8 +1841,8 @@ def Q_graph(self, n):
sage: Q = Domino.Q_graph(3); Q
Finite poset containing 8 elements
sage: Q.upper_covers(Partition([1,1]))
[[1, 1, 1, 1], [3, 1], [2, 2]]
sage: sorted(Q.upper_covers(Partition([1,1])))
[[1, 1, 1, 1], [2, 2], [3, 1]]
"""
if self.has_multiple_edges:
D = DiGraph([(x, y, e) for k in range(n - 1)
Expand Down
8 changes: 4 additions & 4 deletions src/sage/combinat/permutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4785,12 +4785,12 @@ def permutation_poset(self):
EXAMPLES::
sage: # needs sage.combinat sage.graphs
sage: Permutation([3,1,5,4,2]).permutation_poset().cover_relations()
[[(2, 1), (5, 2)],
sage: sorted(Permutation([3,1,5,4,2]).permutation_poset().cover_relations())
[[(1, 3), (3, 5)],
[(1, 3), (4, 4)],
[(2, 1), (3, 5)],
[(2, 1), (4, 4)],
[(1, 3), (3, 5)],
[(1, 3), (4, 4)]]
[(2, 1), (5, 2)]]
sage: Permutation([]).permutation_poset().cover_relations()
[]
sage: Permutation([1,3,2]).permutation_poset().cover_relations()
Expand Down
6 changes: 3 additions & 3 deletions src/sage/combinat/posets/hasse_diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,9 +1074,9 @@ def moebius_function_matrix(self, algorithm='cython'):
True
sage: H = posets.TamariLattice(3)._hasse_diagram
sage: M = H.moebius_function_matrix('matrix'); M
[ 1 -1 -1 0 1]
[ 0 1 0 0 -1]
[ 0 0 1 -1 0]
[ 1 -1 0 -1 1]
[ 0 1 -1 0 0]
[ 0 0 1 0 -1]
[ 0 0 0 1 -1]
[ 0 0 0 0 1]
sage: _ = H.__dict__.pop('_moebius_function_matrix')
Expand Down
8 changes: 4 additions & 4 deletions src/sage/combinat/posets/lattices.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ def submeetsemilattice(self, elms):
sage: L = posets.DivisorLattice(1000)
sage: L_ = L.submeetsemilattice([200, 250, 125]); L_
Finite meet-semilattice containing 5 elements
sage: L_.list()
[25, 50, 200, 125, 250]
sage: sorted(L_.list())
[25, 50, 125, 200, 250]
.. SEEALSO::
Expand Down Expand Up @@ -3159,8 +3159,8 @@ def sublattice(self, elms):
EXAMPLES::
sage: L = LatticePoset(([], [[1,2],[1,17],[1,8],[2,3],[2,22],[2,5],[2,7],[17,22],[17,13],[8,7],[8,13],[3,16],[3,9],[22,16],[22,18],[22,10],[5,18],[5,14],[7,9],[7,14],[7,10],[13,10],[16,6],[16,19],[9,19],[18,6],[18,33],[14,33],[10,19],[10,33],[6,4],[19,4],[33,4]]))
sage: L.sublattice([14, 13, 22]).list()
[1, 2, 8, 7, 14, 17, 13, 22, 10, 33]
sage: sorted(L.sublattice([14, 13, 22]).list())
[1, 2, 7, 8, 10, 13, 14, 17, 22, 33]
sage: L = posets.BooleanLattice(3)
sage: L.sublattice([3,5,6,7])
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/posets/poset_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,7 @@ def YoungsLattice(n):
sage: P = posets.YoungsLattice(3); P
Finite meet-semilattice containing 7 elements
sage: P.cover_relations()
sage: sorted(P.cover_relations())
[[[], [1]],
[[1], [1, 1]],
[[1], [2]],
Expand Down
18 changes: 9 additions & 9 deletions src/sage/combinat/posets/posets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6335,8 +6335,8 @@ def graphviz_string(self, graph_string='graph', edge_string='--'):
sage: P = Poset({'a':['b'],'b':['d'],'c':['d'],'d':['f'],'e':['f'],'f':[]})
sage: print(P.graphviz_string())
graph {
"f";"d";"b";"a";"c";"e";
"f"--"e";"d"--"c";"b"--"a";"d"--"b";"f"--"d";
"f";"e";"d";"c";"b";"a";
"b"--"a";"d"--"b";"d"--"c";"f"--"d";"f"--"e";
}
"""
s = '%s {\n' % graph_string
Expand All @@ -6359,8 +6359,8 @@ def subposet(self, elements):
....: 'd': ['f'], 'e': ['f']})
sage: Q = P.subposet(['a', 'b', 'f']); Q
Finite poset containing 3 elements
sage: Q.cover_relations()
[['b', 'f'], ['a', 'f']]
sage: sorted(Q.cover_relations())
[['a', 'f'], ['b', 'f']]
A subposet of a non-facade poset is again a non-facade poset::
Expand Down Expand Up @@ -6640,8 +6640,8 @@ def order_filter(self, elements):
EXAMPLES::
sage: P = Poset((divisors(1000), attrcall("divides")))
sage: P.order_filter([20, 25])
[20, 40, 25, 50, 100, 200, 125, 250, 500, 1000]
sage: sorted(P.order_filter([20, 25]))
[20, 25, 40, 50, 100, 125, 200, 250, 500, 1000]
.. SEEALSO::
Expand Down Expand Up @@ -6672,7 +6672,7 @@ def order_ideal(self, elements):
EXAMPLES::
sage: P = Poset((divisors(1000), attrcall("divides")))
sage: P.order_ideal([20, 25])
sage: sorted(P.order_ideal([20, 25]))
[1, 2, 4, 5, 10, 20, 25]
.. SEEALSO::
Expand Down Expand Up @@ -6778,7 +6778,7 @@ def closed_interval(self, x, y):
EXAMPLES::
sage: P = Poset((divisors(1000), attrcall("divides")))
sage: P.closed_interval(2, 100)
sage: sorted(P.closed_interval(2, 100))
[2, 4, 10, 20, 50, 100]
.. SEEALSO::
Expand Down Expand Up @@ -6806,7 +6806,7 @@ def open_interval(self, x, y):
EXAMPLES::
sage: P = Poset((divisors(1000), attrcall("divides")))
sage: P.open_interval(2, 100)
sage: sorted(P.open_interval(2, 100))
[4, 10, 20, 50]
.. SEEALSO::
Expand Down
45 changes: 30 additions & 15 deletions src/sage/combinat/skew_tableau.py
Original file line number Diff line number Diff line change
Expand Up @@ -2116,8 +2116,14 @@ def __iter__(self):
sage: [next(it) for x in range(10)]
[[],
[[1]],
[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]],
[[1, 2, 3]], [[1, 2], [3]], [[1, 3], [2]], [[None, 2, 3], [1]]]
[[1, 2]],
[[1], [2]],
[[None, 1], [2]],
[[None, 2], [1]],
[[1, 2, 3]],
[[1, 2], [3]],
[[1, 3], [2]],
[[None, 2, 3], [1]]]
"""
n = 0
while True:
Expand Down Expand Up @@ -2181,23 +2187,32 @@ def __iter__(self):
sage: # needs sage.graphs sage.modules
sage: StandardSkewTableaux(2).list()
[[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]]]
[[[1, 2]], [[1], [2]], [[None, 1], [2]], [[None, 2], [1]]]
sage: StandardSkewTableaux(3).list()
[[[1, 2, 3]],
[[1, 2], [3]], [[1, 3], [2]],
[[None, 2, 3], [1]], [[None, 1, 2], [3]], [[None, 1, 3], [2]],
[[None, 2], [1, 3]], [[None, 1], [2, 3]],
[[None, None, 2], [1, 3]], [[None, None, 3], [1, 2]],
[[1, 2], [3]],
[[1, 3], [2]],
[[None, 2, 3], [1]],
[[None, 1, 2], [3]],
[[None, 1, 3], [2]],
[[None, 1], [2, 3]],
[[None, 2], [1, 3]],
[[None, None, 1], [2, 3]],
[[1], [2], [3]], [[None, 2], [None, 3], [1]],
[[None, 1], [None, 2], [3]], [[None, 1], [None, 3], [2]],
[[None, 2], [1], [3]], [[None, 3], [1], [2]],
[[None, 1], [2], [3]], [[None, None, 3], [None, 2], [1]],
[[None, None, 2], [None, 3], [1]],
[[None, None, 1], [None, 3], [2]],
[[None, None, 3], [1, 2]],
[[None, None, 2], [1, 3]],
[[1], [2], [3]],
[[None, 2], [None, 3], [1]],
[[None, 1], [None, 2], [3]],
[[None, 1], [None, 3], [2]],
[[None, 1], [2], [3]],
[[None, 3], [1], [2]],
[[None, 2], [1], [3]],
[[None, None, 1], [None, 2], [3]],
[[None, None, 2], [None, 1], [3]],
[[None, None, 3], [None, 1], [2]]]
[[None, None, 1], [None, 3], [2]],
[[None, None, 2], [None, 3], [1]],
[[None, None, 3], [None, 2], [1]],
[[None, None, 3], [None, 1], [2]],
[[None, None, 2], [None, 1], [3]]]
"""
for skp in SkewPartitions(self.n):
for sst in StandardSkewTableaux_shape(skp):
Expand Down
4 changes: 2 additions & 2 deletions src/sage/geometry/polyhedron/base4.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,8 @@ def face_lattice(self):
sage: square = polytopes.hypercube(2)
sage: fl = square.face_lattice();fl
Finite lattice containing 10 elements
sage: list(f.ambient_V_indices() for f in fl)
[(), (0,), (1,), (0, 1), (2,), (1, 2), (3,), (0, 3), (2, 3), (0, 1, 2, 3)]
sage: list(f.ambient_V_indices() for f in sorted(fl))
[(), (0,), (0, 1), (0, 1, 2, 3), (0, 3), (1,), (1, 2), (2,), (2, 3), (3,)]
sage: poset_element = fl[5]
sage: a_face = poset_element
sage: a_face
Expand Down
28 changes: 13 additions & 15 deletions src/sage/geometry/polyhedron/face.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,19 +389,18 @@ def ambient_Hrepresentation(self, index=None):
EXAMPLES::
sage: square = polytopes.hypercube(2)
sage: for face in square.face_lattice(): # needs sage.combinat
sage: for face in sorted(square.face_lattice()): # needs sage.combinat
....: print(face.ambient_Hrepresentation())
(An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0,
An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
(An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
(An inequality (-1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
(An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
(An inequality (-1, 0) x + 1 >= 0,)
(An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0)
(An inequality (0, -1) x + 1 >= 0,)
(An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
()
(An inequality (0, 1) x + 1 >= 0,)
(An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
(An inequality (0, -1) x + 1 >= 0,)
(An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0)
(An inequality (1, 0) x + 1 >= 0,)
()
(An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
"""
if index is None:
return self._ambient_Hrepresentation
Expand Down Expand Up @@ -429,19 +428,18 @@ def ambient_Vrepresentation(self, index=None):
EXAMPLES::
sage: square = polytopes.hypercube(2)
sage: for fl in square.face_lattice(): # needs sage.combinat
sage: for fl in sorted(square.face_lattice()): # needs sage.combinat
....: print(fl.ambient_Vrepresentation())
()
(A vertex at (1, -1),)
(A vertex at (1, 1),)
(A vertex at (1, -1), A vertex at (1, 1))
(A vertex at (-1, 1),)
(A vertex at (1, 1), A vertex at (-1, 1))
(A vertex at (-1, -1),)
(A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1), A vertex at (-1, -1))
(A vertex at (1, -1), A vertex at (-1, -1))
(A vertex at (1, 1),)
(A vertex at (1, 1), A vertex at (-1, 1))
(A vertex at (-1, 1),)
(A vertex at (-1, 1), A vertex at (-1, -1))
(A vertex at (1, -1), A vertex at (1, 1),
A vertex at (-1, 1), A vertex at (-1, -1))
(A vertex at (-1, -1),)
"""
if index is None:
return self._ambient_Vrepresentation
Expand Down
3 changes: 1 addition & 2 deletions src/sage/graphs/asteroidal_triples.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ def is_asteroidal_triple_free(G, certificate=False):
# module sage.graphs.base.static_sparse_graph
cdef list int_to_vertex = list(G)
cdef short_digraph sd
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex,
sort_neighbors=False)
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)

cdef bitset_t seen
bitset_init(seen, n)
Expand Down
4 changes: 0 additions & 4 deletions src/sage/graphs/base/static_sparse_backend.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -511,10 +511,6 @@ cdef class StaticSparseBackend(CGraphBackend):
True
"""
vertices = list(G)
try:
vertices.sort()
except TypeError:
pass
cdef StaticSparseCGraph cg = <StaticSparseCGraph> StaticSparseCGraph(G, vertices)
self._cg = cg

Expand Down
10 changes: 1 addition & 9 deletions src/sage/graphs/base/static_sparse_graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,19 @@ ctypedef unsigned int uint

cdef extern from "stdlib.h":
ctypedef void const_void "const void"
void qsort(void *base, int nmemb, int size,
int(*compar)(const_void *, const_void *)) nogil

void *bsearch(const_void *key, const_void *base, size_t nmemb,
size_t size, int(*compar)(const_void *, const_void *)) nogil

cdef extern from "search.h":
void *lfind(const_void *key, const_void *base, size_t *nmemb,
size_t size, int(*compar)(const_void *, const_void *)) nogil

ctypedef struct short_digraph_s:
uint32_t * edges
uint32_t ** neighbors
PyObject * edge_labels
int m
int n
bint sorted_neighbors

ctypedef short_digraph_s short_digraph[1]

cdef int init_short_digraph(short_digraph g, G, edge_labelled=?, vertex_list=?, sort_neighbors=?) except -1
cdef int init_short_digraph(short_digraph g, G, edge_labelled=?, vertex_list=?) except -1
cdef void free_short_digraph(short_digraph g) noexcept
cdef int init_reverse(short_digraph dst, short_digraph src) except -1
cdef int out_degree(short_digraph g, int u) noexcept
Expand Down
Loading

0 comments on commit c1fbf31

Please sign in to comment.