Ticket #14535: trac14535-immutable_graphs.patch

File trac14535-immutable_graphs.patch, 14.1 KB (added by SimonKing, 8 years ago)
  • sage/combinat/posets/hasse_diagram.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1367834112 -7200
    # Node ID f860e66db9cfcf8e519c09f7e108436280943ff8
    # Parent  c2c82f01b133adc84830765b2bb7499223c95b30
    Mutability for graphs
    
    diff --git a/sage/combinat/posets/hasse_diagram.py b/sage/combinat/posets/hasse_diagram.py
    a b  
    4646        Hasse diagram of a poset containing 4 elements
    4747        sage: TestSuite(H).run()
    4848    """
     49    def __init__(self, *args, **kwds):
     50        """
     51        Hasse diagrams are immutable digraphs, which is made sure here.
    4952
    50     # Hasse diagrams are immutable. This temporary hack enables the
    51     # __hash__ method of DiGraph
    52     _immutable = True
     53        EXAMPLES::
     54
     55            sage: from sage.combinat.posets.hasse_diagram import HasseDiagram
     56            sage: H = HasseDiagram({0:[1,2],1:[3],2:[3],3:[]})
     57            sage: D = {H:1}  # indirect doctest
     58            sage: D
     59            {Hasse diagram of a poset containing 4 elements: 1}
     60
     61        """
     62        DiGraph.__init__(self, *args, **kwds)
     63        # Hasse diagrams are immutable.
     64        self.set_immutable()
    5365
    5466    def _repr_(self):
    5567        r"""
    5668        TESTS::
     69
    5770            sage: from sage.combinat.posets.hasse_diagram import HasseDiagram
    5871            sage: H = HasseDiagram({0:[1,2],1:[3],2:[3],3:[]})
    5972            sage: H._repr_()
  • sage/graphs/base/c_graph.pxd

    diff --git a/sage/graphs/base/c_graph.pxd b/sage/graphs/base/c_graph.pxd
    a b  
    1212    cdef int num_arcs
    1313    cdef int *in_degrees
    1414    cdef int *out_degrees
     15    cdef public bint _is_immutable
    1516
    1617    cdef int add_arc_unsafe(self, int, int)
    1718    cdef int has_arc_unsafe(self, int, int)
     
    4344cdef object vertex_label(int u_int, dict vertex_ints, dict vertex_labels, CGraph G)
    4445cdef int check_vertex(object u, dict vertex_ints, dict vertex_labels, CGraph G, CGraph G_revx, bint reverse) except ? -1
    4546# TODO: edge functions!
    46 
    47 
  • sage/graphs/base/c_graph.pyx

    diff --git a/sage/graphs/base/c_graph.pyx b/sage/graphs/base/c_graph.pyx
    a b  
    4646    """
    4747    Compiled sparse and dense graphs.
    4848    """
     49    # mutability
     50    def set_immutable(self):
     51        """
     52        Make this graph unchangeable.
     53
     54        EXAMPLES::
     55
     56            sage: from sage.graphs.base.sparse_graph import SparseGraph
     57            sage: S = SparseGraph(nverts=10, expected_degree=3, extra_vertices=10)
     58            sage: S.add_vertex(15)
     59            15
     60            sage: S.has_vertex(15)
     61            True
     62            sage: S.set_immutable()
     63            sage: S.add_vertex(25)
     64            Traceback (most recent call last):
     65            ...
     66            ValueError: This <CGraph> is immutable. Please change a copy instead
     67
     68        """
     69        self._is_immutable = True
     70    def set_mutable(self):
     71        """
     72        Make this graph changeable.
     73
     74        EXAMPLES::
     75
     76            sage: from sage.graphs.base.sparse_graph import SparseGraph
     77            sage: S = SparseGraph(nverts=10, expected_degree=3, extra_vertices=10)
     78            sage: S.add_vertex(15)
     79            15
     80            sage: S.has_vertex(15)
     81            True
     82            sage: S.set_immutable()
     83            sage: S.add_vertex(25)
     84            Traceback (most recent call last):
     85            ...
     86            ValueError: This <CGraph> is immutable. Please change a copy instead
     87            sage: S.set_mutable()
     88            sage: S.add_vertex(25)
     89            25
     90            sage: S.has_vertex(25)
     91            True
     92
     93        """
     94        self._is_immutable = False
     95    def is_immutable(self):
     96        return self._is_immutable
     97    def is_mutable(self):
     98        return not self._is_immutable
    4999
    50100    ###################################
    51101    # Vertex Functions
     
    309359            ...
    310360            RuntimeError: Requested vertex is past twice the allocated range: use realloc.
    311361        """
     362        if self._is_immutable:
     363            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    312364        if k >= (2 * self.active_vertices.size):
    313365            raise RuntimeError(
    314366                "Requested vertex is past twice the allocated range: "
     
    368420            sage: D.verts()
    369421            [0, 1, 2, 3, 4, 5, 9]
    370422        """
     423        if self._is_immutable:
     424            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    371425        cdef int v
    372426        cdef int nones = 0
    373427        for v in verts:
     
    514568            sage: G.verts()
    515569            [0, 1, 2, 3, 4]
    516570        """
     571        if self._is_immutable:
     572            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    517573        if self.has_vertex(v):
    518574            self.del_vertex_unsafe(v)
    519575
  • sage/graphs/base/dense_graph.pyx

    diff --git a/sage/graphs/base/dense_graph.pyx b/sage/graphs/base/dense_graph.pyx
    a b  
    385385            True
    386386       
    387387        """
     388        if self._is_immutable:
     389            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    388390        self.check_vertex(u)
    389391        self.check_vertex(v)
    390392        self.add_arc_unsafe(u,v)
     
    437439            u, v -- non-negative integers, must be in self
    438440       
    439441        """
     442        if self._is_immutable:
     443            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    440444        cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)
    441445        cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)
    442446        if self.edges[place] & word:
     
    468472            False
    469473
    470474        """
     475        if self._is_immutable:
     476            raise ValueError("This <CGraph> is immutable. Please change a copy instead")
    471477        self.check_vertex(u)
    472478        self.check_vertex(v)
    473479        self.del_arc_unsafe(u,v)
  • sage/graphs/bipartite_graph.py

    diff --git a/sage/graphs/bipartite_graph.py b/sage/graphs/bipartite_graph.py
    a b  
    3333#*****************************************************************************
    3434
    3535from graph import Graph
     36from sage.structure.mutability import require_mutable
    3637
    3738class BipartiteGraph(Graph):
    3839    r"""
     
    420421        else:
    421422            return "".join(["Bipartite ", s])
    422423
     424    @require_mutable
    423425    def add_vertex(self, name=None, left=False, right=False):
    424426        """
    425427        Creates an isolated vertex. If the vertex already exists, then
     
    515517
    516518        return retval
    517519
     520    @require_mutable
    518521    def add_vertices(self, vertices, left=False, right=False):
    519522        """
    520523        Add vertices to the bipartite graph from an iterable container of
     
    608611
    609612        return
    610613
     614    @require_mutable
    611615    def delete_vertex(self, vertex, in_order=False):
    612616        """
    613617        Deletes vertex, removing all incident edges. Deleting a non-existent
     
    677681                raise RuntimeError(
    678682                    "Vertex (%s) not found in partitions" % vertex)
    679683
     684    @require_mutable
    680685    def delete_vertices(self, vertices):
    681686        """
    682687        Remove vertices from the bipartite graph taken from an iterable
     
    721726                    raise RuntimeError(
    722727                        "Vertex (%s) not found in partitions" % vertex)
    723728
     729    @require_mutable
    724730    def add_edge(self, u, v=None, label=None):
    725731        """
    726732        Adds an edge from ``u`` and ``v``.
  • sage/graphs/generic_graph.py

    diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
    a b  
    311311from generic_graph_pyx import GenericGraph_pyx, spring_layout_fast
    312312from sage.graphs.dot2tex_utils import assert_have_dot2tex
    313313from sage.misc.superseded import deprecated_function_alias
     314from sage.structure.mutability import require_mutable
    314315
    315316class GenericGraph(GenericGraph_pyx):
    316317    """
     
    462463                    if sorted(edges1) != sorted(edges2) and self._weighted and other._weighted:
    463464                        return False
    464465            return True
    465 
    466     def __hash__(self):
    467         """
    468         Since graphs are mutable, they should not be hashable, so we return
    469         a type error.
    470        
    471         EXAMPLES::
    472        
    473             sage: hash(Graph())
    474             Traceback (most recent call last):
    475             ...
    476             TypeError: graphs are mutable, and thus not hashable
    477         """
    478         if getattr(self, "_immutable", False):
    479             return hash((tuple(self.vertices()), tuple(self.edges())))
    480         raise TypeError, "graphs are mutable, and thus not hashable"
    481466       
    482467    def __mul__(self, n):
    483468        """
     
    74907475   
    74917476
    74927477    ### Vertex handlers
    7493 
     7478    @require_mutable
    74947479    def add_vertex(self, name=None):
    74957480        """
    74967481        Creates an isolated vertex. If the vertex already exists, then
     
    75267511        """
    75277512        return self._backend.add_vertex(name)
    75287513
     7514    @require_mutable
    75297515    def add_vertices(self, vertices):
    75307516        """
    75317517        Add vertices to the (di)graph from an iterable container of
     
    75637549        """
    75647550        return self._backend.add_vertices(vertices)
    75657551
     7552    @require_mutable
    75667553    def delete_vertex(self, vertex, in_order=False):
    75677554        """
    75687555        Deletes vertex, removing all incident edges. Deleting a
     
    76257612       
    76267613        self._backend.del_vertex(vertex)
    76277614
     7615    @require_mutable
    76287616    def delete_vertices(self, vertices):
    76297617        """
    76307618        Remove vertices from the (di)graph taken from an iterable container
     
    81908178
    81918179
    81928180    ### Edge handlers
    8193    
     8181    @require_mutable
    81948182    def add_edge(self, u, v=None, label=None):
    81958183        """
    81968184        Adds an edge from u and v.
     
    84448432        for e in edges:
    84458433            self.subdivide_edge(e, k)
    84468434
     8435    @require_mutable
    84478436    def delete_edge(self, u, v=None, label=None):
    84488437        r"""
    84498438        Delete the edge from u to v, returning silently if vertices or edge
     
    85968585        else:
    85978586            self.delete_edge(u, v)
    85988587
     8588    @require_mutable
    85998589    def set_edge_label(self, u, v, l):
    86008590        """
    86018591        Set the edge label of a given edge.
  • sage/graphs/generic_graph_pyx.pxd

    diff --git a/sage/graphs/generic_graph_pyx.pxd b/sage/graphs/generic_graph_pyx.pxd
    a b  
    55cdef run_spring(int, int, double*, int*, int, bint)
    66
    77cdef class GenericGraph_pyx(SageObject):
    8     pass
    9 
    10 
     8    cdef public bint _is_immutable
    119
    1210cdef class SubgraphSearch:
    1311    cdef int ng
  • sage/graphs/generic_graph_pyx.pyx

    diff --git a/sage/graphs/generic_graph_pyx.pyx b/sage/graphs/generic_graph_pyx.pyx
    a b  
    2929    double sqrt(double)
    3030
    3131cdef class GenericGraph_pyx(SageObject):
    32     pass
     32    def set_immutable(self):
     33        """
     34        Make sure that this graph can't be changed.
     35
     36        EXAMPLES::
     37
     38            sage: G = Graph()
     39            sage: G.is_mutable()
     40            True
     41            sage: G.add_edge((1,2), label='alpha')
     42            sage: G.set_immutable()
     43            sage: G.add_edge((3,1), label='beta')
     44            Traceback (most recent call last):
     45            ...
     46            ValueError: <class 'sage.graphs.graph.Graph'> instance is immutable, <function add_edge at ...> must not be called
     47        """
     48        self._is_immutable = True
     49    def set_mutable(self):
     50        """
     51        Make sure that this graph can be changed.
     52
     53        EXAMPLES::
     54
     55            sage: G = Graph()
     56            sage: G.is_mutable()
     57            True
     58            sage: G.add_edge((1,2), label='alpha')
     59            sage: G.set_immutable()
     60            sage: G.add_edge((3,1), label='beta')
     61            Traceback (most recent call last):
     62            ...
     63            ValueError: <class 'sage.graphs.graph.Graph'> instance is immutable, <function add_edge at ...> must not be called
     64            sage: hash(G)
     65            -1658152282454010151
     66            sage: G.set_mutable()
     67            sage: hash(G)
     68            Traceback (most recent call last):
     69            ...
     70            TypeError: This graph is mutable, and thus not hashable
     71            sage: G.add_edge((3,1), label='beta')
     72            sage: G.edges()
     73            [(1, 2, 'alpha'), (1, 3, 'beta')]
     74
     75        """
     76        self._is_immutable = False
     77    def is_immutable(self):
     78        """
     79        Test whether this graph is immutable.
     80
     81        EXAMPLES::
     82
     83            sage: G = Graph()
     84            sage: G.is_immutable()
     85            False
     86            sage: G.add_edge((1,2), label='alpha')
     87            sage: G.set_immutable()
     88            sage: G.is_immutable()
     89            True
     90        """
     91        return self._is_immutable
     92    def is_mutable(self):
     93        """
     94        Test whether this graph can be changed.
     95
     96        EXAMPLES::
     97
     98            sage: G = Graph()
     99            sage: G.is_mutable()
     100            True
     101            sage: G.add_edge((1,2), label='alpha')
     102            sage: G.set_immutable()
     103            sage: G.is_mutable()
     104            False
     105        """
     106        return not self._is_immutable
     107    def __hash__(self):
     108        """
     109        Since graphs are mutable, they should not be hashable, so we return
     110        a type error.
     111       
     112        EXAMPLES::
     113       
     114            sage: G = Graph()
     115            sage: hash(G)
     116            Traceback (most recent call last):
     117            ...
     118            TypeError: This graph is mutable, and thus not hashable
     119            sage: G.set_immutable()
     120            sage: hash(G)
     121            107815166986306181
     122
     123        """
     124        if self._is_immutable:
     125            return hash((tuple(self.vertices()), tuple(self.edges())))
     126        raise TypeError, "This graph is mutable, and thus not hashable"
    33127
    34128def spring_layout_fast_split(G, **options):
    35129    """
  • sage/graphs/linearextensions.py

    diff --git a/sage/graphs/linearextensions.py b/sage/graphs/linearextensions.py
    a b  
    8181        ################
    8282        from copy import copy
    8383        dag_copy = copy(dag)
     84        dag_copy.set_mutable()
    8485        le = []
    8586        a  = []
    8687        b  = []