Path: blob/master/src/sage/graphs/base/dense_graph.pyx
8815 views
r"""1Fast dense graphs23Usage Introduction4------------------56::78sage: from sage.graphs.base.dense_graph import DenseGraph910Dense graphs are initialized as follows::1112sage: D = DenseGraph(nverts = 10, extra_vertices = 10)1314This example initializes a dense graph with room for twenty vertices, the first15ten of which are in the graph. In general, the first ``nverts`` are "active."16For example, see that 9 is already in the graph::1718sage: D._num_verts()191020sage: D.add_vertex(9)21922sage: D._num_verts()23102425But 10 is not, until we add it::2627sage: D._num_verts()281029sage: D.add_vertex(10)301031sage: D._num_verts()32113334You can begin working right away as follows::3536sage: D.add_arc(0,1)37sage: D.add_arc(1,2)38sage: D.add_arc(1,0)39sage: D.has_arc(7,3)40False41sage: D.has_arc(0,1)42True43sage: D.in_neighbors(1)44[0]45sage: D.out_neighbors(1)46[0, 2]47sage: D.del_all_arcs(0,1)48sage: D.has_arc(0,1)49False50sage: D.has_arc(1,2)51True52sage: D.del_vertex(7)53sage: D.has_arc(7,3)54False55sage: D._num_verts()561057sage: D._num_arcs()5825960Dense graphs do not support multiple or labeled edges.6162::6364sage: T = DenseGraph(nverts = 3, extra_vertices = 2)65sage: T.add_arc(0,1)66sage: T.add_arc(1,2)67sage: T.add_arc(2,0)68sage: T.has_arc(0,1)69True7071::7273sage: for _ in range(10): D.add_arc(5,4)74sage: D.has_arc(5,4)75True7677Dense graphs are by their nature directed. As of this writing, you need to do78operations in pairs to treat the undirected case (or use a backend or a Sage79graph)::8081sage: T.has_arc(1,0)82False8384The curious developer is encouraged to check out the ``unsafe`` functions,85which do not check input but which run in pure C.8687Underlying Data Structure88-------------------------8990The class ``DenseGraph`` contains the following variables which are inherited91from ``CGraph`` (for explanation, refer to the documentation there)::9293cdef int num_verts94cdef int num_arcs95cdef int *in_degrees96cdef int *out_degrees97cdef bitset_t active_vertices9899It also contains the following variables::100101cdef int radix_div_shift102cdef int radix_mod_mask103cdef int num_longs104cdef unsigned long *edges105106The array ``edges`` is a series of bits which are turned on or off, and due to107this, dense graphs only support graphs without edge labels and with no multiple108edges. The ints ``radix_div_shift`` and ``radix_mod_mask`` are simply for doing109efficient division by powers of two, and ``num_longs`` stores the length of the110``edges`` array. Recall that this length reflects the number of available111vertices, not the number of "actual" vertices. For more details about this,112refer to the documentation for ``CGraph``.113"""114115#*******************************************************************************116# Copyright (C) 2008-9 Robert L. Miller <[email protected]>117#118# Distributed under the terms of the GNU General Public License (GPL)119# http://www.gnu.org/licenses/120#*******************************************************************************121122include 'sage/misc/bitset.pxi'123124cdef class DenseGraph(CGraph):125"""126Compiled dense graphs.127128::129130sage: from sage.graphs.base.dense_graph import DenseGraph131132Dense graphs are initialized as follows::133134sage: D = DenseGraph(nverts = 10, extra_vertices = 10)135136INPUT:137138- ``nverts`` - non-negative integer, the number of vertices.139- ``extra_vertices`` - non-negative integer (default: 0), how many extra140vertices to allocate.141- ``verts`` - optional list of vertices to add142- ``arcs`` - optional list of arcs to add143144The first ``nverts`` are created as vertices of the graph, and the next145``extra_vertices`` can be freely added without reallocation. See top level146documentation for more details. The input ``verts`` and ``arcs`` are mainly147for use in pickling.148149"""150151def __cinit__(self, int nverts, int extra_vertices = 10, verts = None, arcs = None):152"""153Allocation and initialization happen in one place.154155Memory usage is156157O( (nverts + extra_vertices)^2 ).158159EXAMPLE::160161sage: from sage.graphs.base.dense_graph import DenseGraph162sage: D = DenseGraph(nverts = 10, extra_vertices = 10)163"""164if nverts == 0 and extra_vertices == 0:165raise RuntimeError('Dense graphs must allocate space for vertices!')166cdef int radix = sizeof(unsigned long) << 3167self.radix_mod_mask = radix - 1168cdef int i = 0169while ((<unsigned long>1)<<i) & self.radix_mod_mask:170i += 1171self.radix_div_shift = i172self.num_verts = nverts173cdef int total_verts = nverts + extra_vertices174self.num_arcs = 0175176i = total_verts >> self.radix_div_shift177if total_verts & self.radix_mod_mask:178i += 1179self.num_longs = i180181self.edges = <unsigned long *> sage_malloc(total_verts * self.num_longs * sizeof(unsigned long))182self.in_degrees = <int *> sage_malloc(total_verts * sizeof(int))183self.out_degrees = <int *> sage_malloc(total_verts * sizeof(int))184185if not self.edges or not self.in_degrees or not self.out_degrees:186if self.edges: sage_free(self.edges)187if self.in_degrees: sage_free(self.in_degrees)188if self.out_degrees: sage_free(self.out_degrees)189raise MemoryError190for i from 0 <= i < self.num_longs * total_verts:191self.edges[i] = 0192for i from 0 <= i < total_verts:193self.in_degrees[i] = 0194self.out_degrees[i] = 0195bitset_init(self.active_vertices, total_verts)196bitset_set_first_n(self.active_vertices, self.num_verts)197198if verts is not None:199self.add_vertices(verts)200201if arcs is not None:202for u,v in arcs:203self.add_arc(u,v)204205def __dealloc__(self):206"""207New and dealloc are both tested at class level.208"""209sage_free(self.edges)210sage_free(self.in_degrees)211sage_free(self.out_degrees)212bitset_free(self.active_vertices)213214def __reduce__(self):215"""216Return a tuple used for pickling this graph.217218TESTS::219220sage: from sage.graphs.base.dense_graph import DenseGraph221sage: D = DenseGraph(nverts = 10, extra_vertices = 10)222sage: D.add_arc(0,1)223sage: D.has_arc(0,1)2241225sage: D.has_arc(1,2)2260227sage: LD = loads(dumps(D))228sage: LD.has_arc(0,1)2291230sage: LD.has_arc(1,2)2310232233"""234from sage.graphs.all import DiGraph235D = DiGraph(implementation='c_graph', sparse=False)236D._backend._cg = self237cdef int i238D._backend.vertex_labels = {}239for i from 0 <= i < self.active_vertices.size:240if bitset_in(self.active_vertices, i):241D._backend.vertex_labels[i] = i242D._backend.vertex_ints = D._backend.vertex_labels243return (DenseGraph, (0, self.active_vertices.size, self.verts(), D.edges(labels=False)))244245cpdef realloc(self, int total_verts):246"""247Reallocate the number of vertices to use, without actually adding any.248249INPUT:250251- ``total`` - integer, the total size to make the array252253Returns -1 and fails if reallocation would destroy any active vertices.254255EXAMPLES::256257sage: from sage.graphs.base.dense_graph import DenseGraph258sage: D = DenseGraph(nverts=4, extra_vertices=4)259sage: D.current_allocation()2608261sage: D.add_vertex(6)2626263sage: D.current_allocation()2648265sage: D.add_vertex(10)26610267sage: D.current_allocation()26816269sage: D.add_vertex(40)270Traceback (most recent call last):271...272RuntimeError: Requested vertex is past twice the allocated range: use realloc.273sage: D.realloc(50)274sage: D.add_vertex(40)27540276sage: D.current_allocation()27750278sage: D.realloc(30)279-1280sage: D.current_allocation()28150282sage: D.del_vertex(40)283sage: D.realloc(30)284sage: D.current_allocation()28530286287"""288cdef int i, j289if total_verts == 0:290raise RuntimeError('Dense graphs must allocate space for vertices!')291cdef bitset_t bits292cdef int min_verts, min_longs, old_longs = self.num_longs293if total_verts < self.active_vertices.size:294min_verts = total_verts295min_longs = -1296bitset_init(bits, self.active_vertices.size)297bitset_set_first_n(bits, total_verts)298if not bitset_issubset(self.active_vertices, bits):299bitset_free(bits)300return -1301bitset_free(bits)302else:303min_verts = self.active_vertices.size304min_longs = self.num_longs305306i = total_verts >> self.radix_div_shift307if total_verts & self.radix_mod_mask:308i += 1309self.num_longs = i310if min_longs == -1: min_longs = self.num_longs311312cdef unsigned long *new_edges = <unsigned long *> sage_malloc(total_verts * self.num_longs * sizeof(unsigned long))313314for i from 0 <= i < min_verts:315for j from 0 <= j < min_longs:316new_edges[i*self.num_longs + j] = self.edges[i*old_longs + j]317for j from min_longs <= j < self.num_longs:318new_edges[i*self.num_longs + j] = 0319for i from min_verts <= i < total_verts:320for j from 0 <= j < self.num_longs:321new_edges[i*self.num_longs + j] = 0322sage_free(self.edges)323self.edges = new_edges324325self.in_degrees = <int *> sage_realloc(self.in_degrees, total_verts * sizeof(int))326self.out_degrees = <int *> sage_realloc(self.out_degrees, total_verts * sizeof(int))327328cdef int first_limb329cdef unsigned long zero_gate330if total_verts > self.active_vertices.size:331first_limb = (self.active_vertices.size >> self.radix_div_shift)332zero_gate = (<unsigned long>1) << (self.active_vertices.size & self.radix_mod_mask)333zero_gate -= 1334for i from 0 <= i < total_verts:335self.edges[first_limb] &= zero_gate336for j from first_limb < j < self.num_longs:337self.edges[j] = 0338339for i from self.active_vertices.size <= i < total_verts:340self.in_degrees[i] = 0341self.out_degrees[i] = 0342bitset_realloc(self.active_vertices, total_verts)343344###################################345# Unlabeled arc functions346###################################347348cdef int add_arc_unsafe(self, int u, int v):349"""350Adds arc (u, v) to the graph.351352INPUT:353u, v -- non-negative integers354355"""356cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)357cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)358if not self.edges[place] & word:359self.in_degrees[v] += 1360self.out_degrees[u] += 1361self.num_arcs += 1362self.edges[place] |= word363364cpdef add_arc(self, int u, int v):365"""366Adds arc ``(u, v)`` to the graph.367368INPUT:369370- ``u, v`` -- non-negative integers, must be in self371372EXAMPLE::373374sage: from sage.graphs.base.dense_graph import DenseGraph375sage: G = DenseGraph(5)376sage: G.add_arc(0,1)377sage: G.add_arc(4,7)378Traceback (most recent call last):379...380LookupError: Vertex (7) is not a vertex of the graph.381sage: G.has_arc(1,0)382False383sage: G.has_arc(0,1)384True385386"""387self.check_vertex(u)388self.check_vertex(v)389self.add_arc_unsafe(u,v)390391cdef int has_arc_unsafe(self, int u, int v):392"""393Checks whether arc (u, v) is in the graph.394395INPUT:396u, v -- non-negative integers, must be in self397398OUTPUT:3990 -- False4001 -- True401402"""403cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)404cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)405return (self.edges[place] & word) >> (v & self.radix_mod_mask)406407cpdef bint has_arc(self, int u, int v):408"""409Checks whether arc ``(u, v)`` is in the graph.410411INPUT:412u, v -- integers413414EXAMPLE::415416sage: from sage.graphs.base.dense_graph import DenseGraph417sage: G = DenseGraph(5)418sage: G.add_arc(0,1)419sage: G.has_arc(1,0)420False421sage: G.has_arc(0,1)422True423424"""425if u < 0 or u >= self.active_vertices.size or not bitset_in(self.active_vertices, u):426return False427if v < 0 or v >= self.active_vertices.size or not bitset_in(self.active_vertices, v):428return False429return self.has_arc_unsafe(u,v) == 1430431cdef int del_arc_unsafe(self, int u, int v):432"""433Deletes the arc from u to v, if it exists.434435INPUT:436u, v -- non-negative integers, must be in self437438"""439cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)440cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)441if self.edges[place] & word:442self.in_degrees[v] -= 1443self.out_degrees[u] -= 1444self.num_arcs -= 1445self.edges[place] &= ~word446447cpdef del_all_arcs(self, int u, int v):448"""449Deletes the arc from ``u`` to ``v``.450451INPUT:452- ``u, v`` - integers453454NOTE:455The naming of this function is for consistency with ``SparseGraph``. Of456course, there can be at most one arc for a ``DenseGraph``.457458EXAMPLE::459460sage: from sage.graphs.base.dense_graph import DenseGraph461sage: G = DenseGraph(5)462sage: G.add_arc(0,1)463sage: G.has_arc(0,1)464True465sage: G.del_all_arcs(0,1)466sage: G.has_arc(0,1)467False468469"""470self.check_vertex(u)471self.check_vertex(v)472self.del_arc_unsafe(u,v)473474###################################475# Neighbor functions476###################################477478cdef int out_neighbors_unsafe(self, int u, int *neighbors, int size):479"""480Gives all v such that (u, v) is an arc of the graph.481482INPUT:483u -- non-negative integer, must be in self484neighbors -- must be a pointer to an (allocated) integer array485size -- the length of the array486487OUTPUT:488nonnegative integer -- the number of v such that (u, v) is an arc489-1 -- indicates that the array has been filled with neighbors, but490there were more491492"""493cdef int place = (u * self.num_longs), num_nbrs = 0494cdef int i, v = 0495cdef unsigned long word, data496for i from 0 <= i < self.num_longs:497data = self.edges[place + i]498word = 1499while word:500if word & data:501if num_nbrs == size:502return -1503neighbors[num_nbrs] = v504num_nbrs += 1505word = word << 1506v += 1507return num_nbrs508509cpdef list out_neighbors(self, int u):510"""511Gives all ``v`` such that ``(u, v)`` is an arc of the graph.512513INPUT:514- ``u`` - integer515516EXAMPLES::517518sage: from sage.graphs.base.dense_graph import DenseGraph519sage: G = DenseGraph(5)520sage: G.add_arc(0,1)521sage: G.add_arc(1,2)522sage: G.add_arc(1,3)523sage: G.out_neighbors(0)524[1]525sage: G.out_neighbors(1)526[2, 3]527528"""529cdef int i, num_nbrs530self.check_vertex(u)531if self.out_degrees[u] == 0:532return []533cdef int size = self.out_degrees[u]534cdef int *neighbors = <int *> sage_malloc(size * sizeof(int))535if not neighbors:536raise MemoryError537num_nbrs = self.out_neighbors_unsafe(u, neighbors, size)538output = [neighbors[i] for i from 0 <= i < num_nbrs]539sage_free(neighbors)540return output541542cdef int in_neighbors_unsafe(self, int v, int *neighbors, int size):543"""544Gives all u such that (u, v) is an arc of the graph.545546INPUT:547v -- non-negative integer, must be in self548neighbors -- must be a pointer to an (allocated) integer array549size -- the length of the array550551OUTPUT:552nonnegative integer -- the number of u such that (u, v) is an arc553-1 -- indicates that the array has been filled with neighbors, but554there were more555556"""557cdef int place = v >> self.radix_div_shift558cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)559cdef int i, num_nbrs = 0560for i from 0 <= i < self.active_vertices.size:561if self.edges[place + i*self.num_longs] & word:562if num_nbrs == size:563return -1564neighbors[num_nbrs] = i565num_nbrs += 1566return num_nbrs567568cpdef list in_neighbors(self, int v):569"""570Gives all ``u`` such that ``(u, v)`` is an arc of the graph.571572INPUT:573- ``v`` - integer574575EXAMPLES::576577sage: from sage.graphs.base.dense_graph import DenseGraph578sage: G = DenseGraph(5)579sage: G.add_arc(0,1)580sage: G.add_arc(3,1)581sage: G.add_arc(1,3)582sage: G.in_neighbors(1)583[0, 3]584sage: G.in_neighbors(3)585[1]586587"""588cdef int i, num_nbrs589self.check_vertex(v)590if self.in_degrees[v] == 0:591return []592cdef int size = self.in_degrees[v]593cdef int *neighbors = <int *> sage_malloc(size * sizeof(int))594if not neighbors:595raise MemoryError596num_nbrs = self.in_neighbors_unsafe(v, neighbors, size)597output = [neighbors[i] for i from 0 <= i < num_nbrs]598sage_free(neighbors)599return output600601##############################602# Further tests. Unit tests for methods, functions, classes defined with cdef.603##############################604605def random_stress():606"""607Randomly search for mistakes in the code.608609DOCTEST (No output indicates that no errors were found)::610611sage: from sage.graphs.base.dense_graph import random_stress612sage: for _ in xrange(400):613... random_stress()614615"""616cdef int i, j, k, l, n617cdef DenseGraph Gnew618num_verts = 10619# This code deliberately uses random instead of sage.misc.prandom,620# so that every time it is run it does different tests, instead of621# doing the same random stress test every time. (Maybe it should622# use sage.misc.random_testing?)623from random import randint624from sage.graphs.all import DiGraph625from sage.misc.misc import uniq626Gnew = DenseGraph(num_verts)627Gold = DiGraph(num_verts, loops=True, implementation='networkx')628for n from 0 <= n < 100:629i = randint(0,num_verts-1)630j = randint(0,num_verts-1)631k = randint(0,num_verts-1)632if k != 0:633Gold.add_edge(i,j)634Gnew.add_arc_unsafe(i,j)635else:636Gold.delete_edge(i,j)637Gnew.del_arc_unsafe(i,j)638if Gnew.num_arcs != Gold.size():639raise RuntimeError( "NO" )640for i from 0 <= i < num_verts:641if Gnew.out_degrees[i] != Gold.out_degree(i):642raise RuntimeError( "NO" )643if Gnew.in_degrees[i] != Gold.in_degree(i):644raise RuntimeError( "NO" )645646def _test_adjacency_sequence_out():647"""648Randomly test the method ``DenseGraph.adjacency_sequence_out()``. No output649indicates that no errors were found.650651TESTS::652653sage: from sage.graphs.base.dense_graph import _test_adjacency_sequence_out654sage: _test_adjacency_sequence_out() # long time655"""656from sage.graphs.digraph import DiGraph657from sage.graphs.graph_generators import GraphGenerators658from sage.misc.prandom import randint, random659low = 0660high = 500661randg = DiGraph(GraphGenerators().RandomGNP(randint(low, high), random()))662n = randg.order()663cdef DenseGraph g = DenseGraph(n,664verts=randg.vertices(),665arcs=randg.edges(labels=False))666assert g._num_verts() == randg.order(), (667"Graph order mismatch: %s vs. %s" % (g._num_verts(), randg.order()))668assert g._num_arcs() == randg.size(), (669"Graph size mismatch: %s vs. %s" % (g._num_arcs(), randg.size()))670M = randg.adjacency_matrix()671cdef int *V = <int *>sage_malloc(n * sizeof(int))672cdef int i = 0673for v in randg.vertex_iterator():674V[i] = v675i += 1676cdef int *seq = <int *> sage_malloc(n * sizeof(int))677for 0 <= i < randint(50, 101):678u = randint(low, n - 1)679g.adjacency_sequence_out(n, V, u, seq)680A = [seq[k] for k in range(n)]681try:682assert A == list(M[u])683except AssertionError:684sage_free(V)685sage_free(seq)686raise AssertionError("Graph adjacency mismatch")687sage_free(seq)688sage_free(V)689690###########################################691# Dense Graph Backend692###########################################693694from c_graph import CGraphBackend695from c_graph cimport check_vertex, vertex_label, get_vertex696697class DenseGraphBackend(CGraphBackend):698"""699Backend for Sage graphs using DenseGraphs.700701::702703sage: from sage.graphs.base.dense_graph import DenseGraphBackend704705This class is only intended for use by the Sage Graph and DiGraph class.706If you are interested in using a DenseGraph, you probably want to do707something like the following example, which creates a Sage Graph instance708which wraps a DenseGraph object::709710sage: G = Graph(30, implementation="c_graph", sparse=False)711sage: G.add_edges([(0,1), (0,3), (4,5), (9, 23)])712sage: G.edges(labels=False)713[(0, 1), (0, 3), (4, 5), (9, 23)]714715Note that Sage graphs using the backend are more flexible than DenseGraphs716themselves. This is because DenseGraphs (by design) do not deal with Python717objects::718719sage: G.add_vertex((0,1,2))720sage: G.vertices()721[0,722...72329,724(0, 1, 2)]725sage: from sage.graphs.base.dense_graph import DenseGraph726sage: DG = DenseGraph(30)727sage: DG.add_vertex((0,1,2))728Traceback (most recent call last):729...730TypeError: an integer is required731732"""733734def __init__(self, n, directed=True):735"""736Initialize a dense graph with n vertices.737738EXAMPLE::739740sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)741sage: D.add_edge(0,1,None,False)742sage: list(D.iterator_edges(range(9), True))743[(0, 1, None)]744745"""746self._cg = DenseGraph(n)747self._cg_rev = None748self._directed = directed749self.vertex_labels = {}750self.vertex_ints = {}751752def add_edge(self, object u, object v, object l, bint directed):753"""754Adds the edge ``(u,v)`` to self.755756INPUT:757758- ``u,v`` - the vertices of the edge759- ``l`` - the edge label (ignored)760- ``directed`` - if False, also add ``(v,u)``761762NOTE:763The input ``l`` is for consistency with other backends.764765EXAMPLE::766767sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)768sage: D.add_edge(0,1,None,False)769sage: list(D.iterator_edges(range(9), True))770[(0, 1, None)]771772"""773if u is None: u = self.add_vertex(None)774if v is None: v = self.add_vertex(None)775776cdef int u_int = check_vertex(u, self.vertex_ints, self.vertex_labels,777self._cg, None, 0)778cdef int v_int = check_vertex(v, self.vertex_ints, self.vertex_labels,779self._cg, None, 0)780781if directed or u_int == v_int:782self._cg.add_arc(u_int, v_int)783else:784self._cg.add_arc(u_int, v_int)785self._cg.add_arc(v_int, u_int)786787def add_edges(self, object edges, bint directed):788"""789Add edges from a list.790791INPUT:792793- ``edges`` - the edges to be added - can either be of the form794``(u,v)`` or ``(u,v,l)``795- ``directed`` - if False, add ``(v,u)`` as well as ``(u,v)``796797EXAMPLE::798799sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)800sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)801sage: list(D.iterator_edges(range(9), True))802[(0, 1, None),803(2, 3, None),804(4, 5, None),805(5, 6, None)]806807"""808for e in edges:809u,v = e[:2]810self.add_edge(u,v,None,directed)811812def del_edge(self, object u, object v, object l, bint directed):813"""814Delete edge ``(u,v)``.815816INPUT:817818- ``u,v`` - the vertices of the edge819- ``l`` - the edge label (ignored)820- ``directed`` - if False, also delete ``(v,u,l)``821822NOTE:823The input ``l`` is for consistency with other backends.824825EXAMPLE::826827sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)828sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)829sage: list(D.iterator_edges(range(9), True))830[(0, 1, None),831(2, 3, None),832(4, 5, None),833(5, 6, None)]834sage: D.del_edge(0,1,None,True)835sage: list(D.iterator_out_edges(range(9), True))836[(1, 0, None),837(2, 3, None),838(3, 2, None),839(4, 5, None),840(5, 4, None),841(5, 6, None),842(6, 5, None)]843844"""845if not ( self.has_vertex(u) and self.has_vertex(v) ):846return847cdef int u_int = check_vertex(u, self.vertex_ints, self.vertex_labels,848self._cg, None, 0)849cdef int v_int = check_vertex(v, self.vertex_ints, self.vertex_labels,850self._cg, None, 0)851if v is None:852u, v = u[:2]853if directed:854self._cg.del_all_arcs(u_int, v_int)855else:856self._cg.del_all_arcs(u_int, v_int)857self._cg.del_all_arcs(v_int, u_int)858859def get_edge_label(self, object u, object v):860"""861Returns the edge label for ``(u,v)``. Always None, since dense graphs862do not support edge labels.863864INPUT:865866- ``u,v`` - the vertices of the edge867868EXAMPLE::869870sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)871sage: D.add_edges([(0,1), (2,3,7), (4,5), (5,6)], False)872sage: list(D.iterator_edges(range(9), True))873[(0, 1, None),874(2, 3, None),875(4, 5, None),876(5, 6, None)]877sage: D.del_edge(0,1,None,True)878sage: list(D.iterator_out_edges(range(9), True))879[(1, 0, None),880(2, 3, None),881(3, 2, None),882(4, 5, None),883(5, 4, None),884(5, 6, None),885(6, 5, None)]886sage: D.get_edge_label(2,3)887sage: D.get_edge_label(2,4)888Traceback (most recent call last):889...890LookupError: (2, 4) is not an edge of the graph.891892"""893if not self.has_edge(u, v, None):894raise LookupError("({0}, {1}) is not an edge of the graph.".format(repr(u), repr(v)))895return None896897def has_edge(self, object u, object v, object l):898"""899Returns whether this graph has edge ``(u,v)``.900901NOTE:902The input ``l`` is for consistency with other backends.903904INPUT:905906- ``u,v`` - the vertices of the edge907- ``l`` - the edge label (ignored)908909EXAMPLE::910911sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)912sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)913sage: D.has_edge(0,1,None)914True915916"""917if not ( self.has_vertex(u) and self.has_vertex(v) ):918return False919cdef int u_int = get_vertex(u, self.vertex_ints, self.vertex_labels,920self._cg)921cdef int v_int = get_vertex(v, self.vertex_ints, self.vertex_labels,922self._cg)923return self._cg.has_arc(u_int, v_int)924925def iterator_edges(self, object vertices, bint labels):926"""927Iterate over the edges incident to a sequence of vertices. Edges are928assumed to be undirected.929930INPUT:931- ``vertices`` - a list of vertex labels932- ``labels`` - boolean, whether to return labels as well933934EXAMPLE::935936sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)937sage: G.add_edge(1,2,None,False)938sage: list(G.iterator_edges(range(9), False))939[(1, 2)]940sage: list(G.iterator_edges(range(9), True))941[(1, 2, None)]942943"""944cdef object v945vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,946self._cg) for v in vertices if self.has_vertex(v)]947cdef int u_int, v_int948if labels:949return iter([tuple(sorted(950(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),951vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg)952)))+(None,)953for v_int in vertices954for u_int in self._cg.out_neighbors(v_int)955if u_int >= v_int or u_int not in vertices])956else:957return iter([tuple(sorted(958(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),959vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg)960)))961for v_int in vertices962for u_int in self._cg.out_neighbors(v_int)963if u_int >= v_int or u_int not in vertices])964965def iterator_in_edges(self, object vertices, bint labels):966"""967Iterate over the incoming edges incident to a sequence of vertices.968969INPUT:970- ``vertices`` - a list of vertex labels971- ``labels`` - boolean, whether to return labels as well972973EXAMPLE::974975sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)976sage: G.add_edge(1,2,None,True)977sage: list(G.iterator_in_edges([1], False))978[]979sage: list(G.iterator_in_edges([2], False))980[(1, 2)]981sage: list(G.iterator_in_edges([2], True))982[(1, 2, None)]983984"""985cdef object v986vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,987self._cg) for v in vertices if self.has_vertex(v)]988cdef int u_int, v_int989if labels:990return iter([991(vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),992vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),993None)994for v_int in vertices995for u_int in self._cg.in_neighbors(v_int)])996else:997return iter([998(vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),999vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg))1000for v_int in vertices1001for u_int in self._cg.in_neighbors(v_int)])10021003def iterator_out_edges(self, object vertices, bint labels):1004"""1005Iterate over the outbound edges incident to a sequence of vertices.10061007INPUT:1008- ``vertices`` - a list of vertex labels1009- ``labels`` - boolean, whether to return labels as well10101011EXAMPLE::10121013sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)1014sage: G.add_edge(1,2,None,True)1015sage: list(G.iterator_out_edges([2], False))1016[]1017sage: list(G.iterator_out_edges([1], False))1018[(1, 2)]1019sage: list(G.iterator_out_edges([1], True))1020[(1, 2, None)]10211022"""1023cdef object u, v1024vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,1025self._cg) for v in vertices if self.has_vertex(v)]1026cdef int u_int, v_int1027if labels:1028return iter([1029(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),1030vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),1031None)1032for v_int in vertices1033for u_int in self._cg.out_neighbors(v_int)])1034else:1035return iter([1036(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),1037vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg))1038for v_int in vertices1039for u_int in self._cg.out_neighbors(v_int)])10401041def multiple_edges(self, new):1042"""1043Get/set whether or not ``self`` allows multiple edges.10441045INPUT:10461047- ``new`` - boolean (to set) or ``None`` (to get)10481049EXAMPLES::10501051sage: import sage.graphs.base.dense_graph1052sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)1053sage: G.multiple_edges(True)1054Traceback (most recent call last):1055...1056NotImplementedError: Dense graphs do not support multiple edges.1057sage: G.multiple_edges(None)1058False10591060"""1061if new is None:1062return False1063if new:1064raise NotImplementedError("Dense graphs do not support multiple edges.")10651066def set_edge_label(self, object u, object v, object l, bint directed):1067"""1068Label the edge ``(u,v)`` by ``l``.10691070INPUT:10711072- ``u,v`` - the vertices of the edge1073- ``l`` - the edge label1074- ``directed`` - if False, also set ``(v,u)`` with label ``l``10751076EXAMPLE::10771078sage: import sage.graphs.base.dense_graph1079sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)1080sage: G.set_edge_label(1,2,'a',True)1081Traceback (most recent call last):1082...1083NotImplementedError: Dense graphs do not support edge labels.1084"""1085raise NotImplementedError("Dense graphs do not support edge labels.")108610871088