Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
trac #15623: Immutable graph backend for Posets
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanncohen committed Jan 2, 2014
1 parent 0f57805 commit b6ed038
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 17 deletions.
5 changes: 0 additions & 5 deletions src/sage/combinat/posets/hasse_diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand Down
3 changes: 1 addition & 2 deletions src/sage/combinat/posets/posets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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):
Expand Down
44 changes: 36 additions & 8 deletions src/sage/graphs/base/static_sparse_backend.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -361,7 +367,9 @@ class StaticSparseBackend(CGraphBackend):
"""
cdef StaticSparseCGraph cg = <StaticSparseCGraph> 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)
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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):
"""
Expand All @@ -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]
Expand Down Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions src/sage/graphs/linearextensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down

0 comments on commit b6ed038

Please sign in to comment.