Ticket #9546: trac_9546.patch

File trac_9546.patch, 6.2 KB (added by ncohen, 10 years ago)
  • sage/graphs/generic_graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1279518718 -28800
    # Node ID 8c1cd7a7635c12d4caacd502b86e92b4174d4f5b
    # Parent  0476406f40ad3e24b3912e3df228ba0babe8601e
    trac #9546 - bounded_outdegree_orientation
    
    diff -r 0476406f40ad -r 8c1cd7a7635c sage/graphs/generic_graph.py
    a b  
    50015001
    50025002        # Whether we should consider the edges labeled
    50035003        if use_edge_labels:
    5004             l_capacity=lambda x: 1 if (x is None or x == {}) else (floor(x) if integer else x)
     5004            l_capacity=lambda x: 1 if (x is None or x == {}) else (x//1 if integer else x)
    50055005        else:
    50065006            l_capacity=lambda x: 1
    50075007
  • sage/graphs/graph.py

    diff -r 0476406f40ad -r 8c1cd7a7635c sage/graphs/graph.py
    a b  
    21722172           
    21732173        return d
    21742174
     2175    def bounded_outdegree_orientation(self, bound):
     2176        r"""
     2177        Computes an orientation of ``self`` such that every vertex `v`
     2178        has out-degree less than `b(v)`
     2179
     2180        INPUT:
     2181
     2182        - ``bound`` -- Maximum bound on the out-degree. Can be of
     2183          three different types :
     2184
     2185             * An integer `k`. In this case, computes an orientation
     2186               whose maximum out-degree is less than `k`.
     2187
     2188             * A dictionary associating to each vertex its associated
     2189               maximum out-degree.
     2190
     2191             * A function associating to each vertex its associated
     2192               maximum out-degree.
     2193
     2194        OUTPUT:
     2195
     2196        A DiGraph representing the orientation if it exists. A
     2197        ``ValueError`` exception is raised otherwise.
     2198
     2199        ALGORITHM:
     2200
     2201        The problem is solved through a maximum flow :
     2202
     2203        Given a graph `G`, we create a ``DiGraph`` `D` defined on
     2204        `E(G)\cup V(G)\cup \{s,t\}`. We then link `s` to all of `V(G)`
     2205        (these edges having a capacity equal to the bound associated
     2206        to each element of `V(G)`), and all the elements of `E(G)` to
     2207        `t` . We then link each `v \in V(G)` to each of its incident
     2208        edges in `G`. A maximum integer flow of value `|E(G)|`
     2209        corresponds to an admissible orientation of `G`. Otherwise,
     2210        none exists.
     2211
     2212        EXAMPLES:
     2213
     2214        There is always an orientation of a graph `G` such that a
     2215        vertex `v` has out-degree at most `\lceil \frac {d(v)} 2
     2216        \rceil`::
     2217
     2218            sage: g = graphs.RandomGNP(40, .4)
     2219            sage: b = lambda v : ceil(g.degree(v)/2)
     2220            sage: D = g.bounded_outdegree_orientation(b)
     2221            sage: all( D.out_degree(v) <= b(v) for v in g )
     2222            True
     2223
     2224
     2225        Chvatal's graph, being 4-regular, can be oriented in such a
     2226        way that its maximum out-degree is 2::
     2227
     2228            sage: g = graphs.ChvatalGraph()
     2229            sage: D = g.bounded_outdegree_orientation(2)
     2230            sage: max(D.out_degree())
     2231            2
     2232
     2233        For any graph `G`, it is possible to compute an orientation
     2234        such that the maximum out-degree is at most the maximum
     2235        average degree of `G` divided by 2. Anything less, though, is
     2236        impossible.
     2237
     2238            sage: g = graphs.RandomGNP(40, .4)
     2239            sage: mad = g.maximum_average_degree()
     2240       
     2241        Hence this is possible ::
     2242
     2243            sage: d = g.bounded_outdegree_orientation(ceil(mad/2))
     2244
     2245        While this is not::
     2246
     2247            sage: try:
     2248            ...      g.bounded_outdegree_orientation(ceil(mad/2-1))
     2249            ...      print "Error"
     2250            ... except ValueError:
     2251            ...       pass
     2252
     2253        TESTS:
     2254
     2255        As previously for random graphs, but more intensively::
     2256
     2257            sage: for i in xrange(30):                                   # long
     2258            ...       g = graphs.RandomGNP(40, .4)                       # long
     2259            ...       b = lambda v : ceil(g.degree(v)/2)                 # long
     2260            ...       D = g.bounded_outdegree_orientation(b)             # long
     2261            ...       if not (                                           # long
     2262            ...            all( D.out_degree(v) <= b(v) for v in g ) or  # long
     2263            ...            D.size() != g.size()):                        # long
     2264            ...           print "Something wrong happened"               # long
     2265
     2266        """
     2267        from sage.graphs.all import DiGraph
     2268        n = self.order()
     2269
     2270        if n == 0:
     2271            return DiGraph()
     2272
     2273        vertices = self.vertices()
     2274        vertices_id = dict(map(lambda (x,y):(y,x), list(enumerate(vertices))))
     2275
     2276        b = {}
     2277
     2278       
     2279        # Checking the input type. We make a dictionay out of it
     2280        if isinstance(bound, dict):
     2281            b = bound
     2282        else:
     2283            try:
     2284                b = dict(zip(vertices,map(bound, vertices)))
     2285
     2286            except TypeError:
     2287                b = dict(zip(vertices, [bound]*n))
     2288       
     2289        d = DiGraph()
     2290
     2291        # Adding the edges (s,v) and ((u,v),t)
     2292        d.add_edges( ('s', vertices_id[v], b[v]) for v in vertices)
     2293
     2294        d.add_edges( ((vertices_id[u], vertices_id[v]), 't', 1)
     2295                     for (u,v) in self.edges(labels=None) )
     2296
     2297        # each v is linked to its incident edges
     2298
     2299        for u,v in self.edges(labels = None):
     2300            u,v = vertices_id[u], vertices_id[v]
     2301            d.add_edge(u, (u,v), 1)
     2302            d.add_edge(v, (u,v), 1)
     2303
     2304        # Solving the maximum flow
     2305        value, flow = d.flow('s','t', value_only = False, integer = True, use_edge_labels = True)
     2306
     2307        if value != self.size():
     2308            raise ValueError("No orientation exists for the given bound")
     2309
     2310        D = DiGraph()
     2311        D.add_vertices(vertices)
     2312
     2313        # The flow graph may not contain all the vertices, if they are
     2314        # not part of the flow...
     2315
     2316        for u in [x for x in range(n) if x in flow]:
     2317
     2318            for (uu,vv) in flow.neighbors_out(u):
     2319                v = vv if vv != u else uu
     2320                D.add_edge(vertices[u], vertices[v])
     2321
     2322        # I do not like when a method destroys the embedding ;-)
     2323
     2324        D.set_pos(self.get_pos())
     2325
     2326        return D
     2327
     2328
    21752329    ### Coloring
    21762330
    21772331    def bipartite_color(self):