diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 0f2ea7121d1..a5f8d883cb2 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -46,11 +46,6 @@ class HasseDiagram(DiGraph): Hasse diagram of a poset containing 4 elements sage: TestSuite(H).run() """ - - # Hasse diagrams are immutable. This temporary hack enables the - # __hash__ method of DiGraph - _immutable = True - def _repr_(self): r""" TESTS:: diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 590cea342d3..2ac523be3a5 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -740,7 +740,7 @@ def __classcall__(cls, hasse_diagram, elements = None, category = None, facade = facade = hasse_diagram in Sets().Facades() hasse_diagram = hasse_diagram._hasse_diagram else: - hasse_diagram = HasseDiagram(hasse_diagram) + hasse_diagram = HasseDiagram(hasse_diagram, data_structure="static_sparse") if elements is None: elements = hasse_diagram.vertices() if facade is None: @@ -1490,7 +1490,6 @@ def to_graph(self): """ from sage.graphs.graph import Graph G = Graph(self.hasse_diagram()) - G._immutable = True return G def level_sets(self): diff --git a/src/sage/graphs/base/static_sparse_backend.pyx b/src/sage/graphs/base/static_sparse_backend.pyx index 9b5a8fe7d70..d5c87205447 100644 --- a/src/sage/graphs/base/static_sparse_backend.pyx +++ b/src/sage/graphs/base/static_sparse_backend.pyx @@ -40,6 +40,7 @@ from sage.graphs.base.static_sparse_graph cimport (init_short_digraph, from c_graph import CGraphBackend from sage.misc.bitset cimport FrozenBitset from libc.stdint cimport uint32_t +include 'sage/misc/bitset.pxi' cdef class StaticSparseCGraph(CGraph): """ @@ -64,10 +65,14 @@ cdef class StaticSparseCGraph(CGraph): has_labels = any(not l is None for _,_,l in G.edge_iterator()) self.directed = G.is_directed() - init_short_digraph(self.g,G, edge_labelled = has_labels) + init_short_digraph(self.g, G, edge_labelled = has_labels) if self.directed: init_reverse(self.g_rev,self.g) + # Defining the meaningless set of 'active' vertices. Because of CGraph. + bitset_init(self.active_vertices, self.g.n+1) + bitset_set_first_n(self.active_vertices, self.g.n) + def __dealloc__(self): r""" Freeing the memory @@ -77,6 +82,7 @@ cdef class StaticSparseCGraph(CGraph): sage: from sage.graphs.base.static_sparse_backend import StaticSparseCGraph sage: g = StaticSparseCGraph(graphs.PetersenGraph()) """ + bitset_free(self.active_vertices) free_short_digraph(self.g) if self.g_rev != NULL: free_short_digraph(self.g_rev) @@ -361,7 +367,9 @@ class StaticSparseBackend(CGraphBackend): """ cdef StaticSparseCGraph cg = StaticSparseCGraph(G) self._cg = cg - self._directed = cg.directed + + # .directed and not ._directed. Because of CGraph. + self.directed = cg.directed vertices = G.vertices() self._order = len(vertices) @@ -374,6 +382,12 @@ class StaticSparseBackend(CGraphBackend): self._vertex_to_labels = vertices self._vertex_to_int = {v:i for i,v in enumerate(vertices)} + # Needed by CGraph. The first one is just an alias, and the second is + # useless : accessing _vertex_to_labels (which is a list) is faster than + # vertex_labels (which is a dictionary) + self.vertex_ints = self._vertex_to_int + self.vertex_labels = {i:v for i,v in enumerate(vertices)} + def __reduce__(self): """ Return a tuple used for pickling this graph. @@ -383,7 +397,7 @@ class StaticSparseBackend(CGraphBackend): sage: G = Graph(graphs.PetersenGraph(), immutable=True) sage: _ = loads(dumps(G)) """ - if self._directed: + if self.directed: from sage.graphs.digraph import DiGraph as constructor else: from sage.graphs.graph import Graph as constructor @@ -556,6 +570,13 @@ class StaticSparseBackend(CGraphBackend): [(0, 1), (0, 4), (0, 5)] sage: list(g.iterator_in_edges([0],True)) [(0, 1, None), (0, 4, None), (0, 5, None)] + + :: + + sage: DiGraph(digraphs.Path(5),immutable=False).incoming_edges([2]) + [(1, 2, None)] + sage: DiGraph(digraphs.Path(5),immutable=True).incoming_edges([2]) + [(1, 2, None)] """ cdef StaticSparseCGraph cg = self._cg if not cg.directed: @@ -573,11 +594,11 @@ class StaticSparseBackend(CGraphBackend): vi = self._vertex_to_labels[i] for j in range(out_degree(cg.g_rev,i)): if labels: - yield (vi, - self._vertex_to_labels[cg.g_rev.neighbors[i][j]], + yield (self._vertex_to_labels[cg.g_rev.neighbors[i][j]], + vi, edge_label(cg.g_rev,cg.g_rev.neighbors[i]+j)) else: - yield vi,self._vertex_to_labels[cg.g_rev.neighbors[i][j]] + yield self._vertex_to_labels[cg.g_rev.neighbors[i][j]], vi def iterator_out_edges(self, object vertices, bint labels): """ @@ -597,6 +618,7 @@ class StaticSparseBackend(CGraphBackend): [(0, 1), (0, 4), (0, 5)] sage: list(g.iterator_out_edges([0],True)) [(0, 1, None), (0, 4, None), (0, 5, None)] + """ try: vertices = [self._vertex_to_int[x] for x in vertices] @@ -775,15 +797,21 @@ class StaticSparseBackend(CGraphBackend): (3, 4), (3, 8), (4, 9), (5, 7), (5, 8), (6, 8), (6, 9), (7, 9)] """ cdef FrozenBitset fb + cdef list vertices_int - if self._directed: + if self.directed: raise RuntimeError("This is not meant for directed graphs.") try: - vertices = FrozenBitset([self._vertex_to_int[x] for x in vertices]) + vertices_int = [self._vertex_to_int[x] for x in vertices] except KeyError: raise LookupError("One of the vertices does not belong to the graph") + if not vertices_int: + return + + vertices = FrozenBitset(vertices_int) + cdef StaticSparseCGraph cg = self._cg cdef int i,j,tmp diff --git a/src/sage/graphs/linearextensions.py b/src/sage/graphs/linearextensions.py index 3c6a4d15616..aff540431aa 100644 --- a/src/sage/graphs/linearextensions.py +++ b/src/sage/graphs/linearextensions.py @@ -79,8 +79,7 @@ def __init__(self, dag): ################ #Precomputation# ################ - from copy import copy - dag_copy = copy(dag) + dag_copy = dag.copy(immutable=False) le = [] a = [] b = []