Ticket #6679: trac_6679-reviewer.patch

File trac_6679-reviewer.patch, 35.4 KB (added by mvngu, 11 years ago)

based on trac_6679.patch

  • sage/graphs/graph.py

    # HG changeset patch
    # User Minh Van Nguyen <nguyenminh2@gmail.com>
    # Date 1259691203 28800
    # Node ID 6bb946d9b299a5b6ecbca3503f1f8691dc2ddde7
    # Parent  ba3480f452b56ec298bfd288ba022d3c5cd96c18
    trac 6679: reviewer patch
    
    diff -r ba3480f452b5 -r 6bb946d9b299 sage/graphs/graph.py
    a b  
    1002210022        return chromatic_polynomial(self)
    1002310023
    1002410024    def chromatic_number(self, algorithm="DLX"):
    10025         """
     10025        r"""
    1002610026        Returns the minimal number of colors needed to color the vertices
    1002710027        of the graph `G`.
    1002810028
    1002910029        INPUT:
    1003010030
    10031         - ``algorithm`` -- Selects an algorithm
    10032 
    10033             - If ``algorithm = "DLX"`` ( default ), the chromatic number is computed
    10034               through the dancing link algorithm.
    10035 
    10036               Computing the chromatic number through the Dancing Link Algorithm is a
    10037               very slow method, as it computes ALL the possible colorings to check
    10038               that one exists.
    10039 
    10040             - If ``algorithm = "CP"``, the chromatic number is computed
    10041               through the coefficients of the Chromatic Polynomial.
    10042 
    10043               Computing the chromatic number through the chromatic polynomial is a
    10044               very slow method, which will only be useful for small graphs.
    10045 
    10046             - If ``algorithm = "MILP"``, the chromatic number
    10047               is computed through a Mixed Integer Linear Program.
    10048 
    10049               Computing the chromatic number through a Mixed Integer Linear
    10050               Program may require to install an optional Sage package like GLPK
    10051               or Coin-OR's CBC.
    10052 
    10053         For more functions related to graph coloring, see
    10054         the ``sage.graphs.graph_coloring`` module.
    10055 
    10056         EXAMPLES::
    10057        
    10058             sage: G = Graph({0:[1,2,3],1:[2]})
     10031        - ``algorithm`` -- Select an algorithm from the following supported
     10032          algorithms:
     10033
     10034          - If ``algorithm="DLX"`` (default), the chromatic number is
     10035            computed using the dancing link algorithm. It is
     10036            inefficient speedwise to compute the chromatic number through
     10037            the dancing link algorithm because this algorithm computes
     10038            *all* the possible colorings to check that one exists.
     10039
     10040          - If ``algorithm="CP"``, the chromatic number is computed
     10041            using the coefficients of the chromatic polynomial. Again, this
     10042            method is inefficient in terms of speed and it only useful for
     10043            small graphs.
     10044
     10045          - If ``algorithm="MILP"``, the chromatic number is computed
     10046            using a mixed integer linear program. This method requires
     10047            you to install an optional Sage package like GLPK or
     10048            COIN-OR's CBC. Of the methods "DLX", "CP", and "MILP", the last
     10049            method is the fastest method of the three.
     10050
     10051        .. SEEALSO::
     10052
     10053            For more functions related to graph coloring, see the
     10054            module :mod:`sage.graphs.graph_coloring`.
     10055
     10056        EXAMPLES::
     10057       
     10058            sage: G = Graph({0: [1, 2, 3], 1: [2]})
    1005910059            sage: G.chromatic_number(algorithm="DLX")
    1006010060            3
    1006110061            sage: G.chromatic_number(algorithm="MILP") # optional - requires GLPK or CBC
     
    1006510065
    1006610066        TESTS::
    1006710067
    10068             sage: G = Graph({0:[1,2,3],1:[2]})
     10068            sage: G = Graph({0: [1, 2, 3], 1: [2]})
    1006910069            sage: G.chromatic_number(algorithm="foo")
    1007010070            Traceback (most recent call last):
    1007110071            ...
    10072             ValueError: The `algorithm` variable must be set to either `DLX`, `MILP` or `CP`.
    10073         """
     10072            ValueError: The 'algorithm' keyword must be set to either 'DLX', 'MILP' or 'CP'.
     10073        """
     10074        # default built-in algorithm; bad performance
    1007410075        if algorithm == "DLX":
    1007510076            from sage.graphs.graph_coloring import chromatic_number
    1007610077            return chromatic_number(self)
    10077 
     10078        # Algorithm with good performance, but requires an optional
     10079        # package: choose any of GLPK or CBC.
    1007810080        elif algorithm == "MILP":
    1007910081            from sage.graphs.graph_coloring import vertex_coloring
    1008010082            return vertex_coloring(self, value_only=True)
    10081 
     10083        # another algorithm with bad performance; only good for small graphs
    1008210084        elif algorithm == "CP":
    1008310085            f = self.chromatic_polynomial()
    1008410086            i = 0
     
    1008610088                i += 1
    1008710089            return i
    1008810090        else:
    10089             raise ValueError("The `algorithm` variable must be set to either `DLX`, `MILP` or `CP`.")
     10091            raise ValueError("The 'algorithm' keyword must be set to either 'DLX', 'MILP' or 'CP'.")
    1009010092
    1009110093    def coloring(self, algorithm="DLX", hex_colors=False):
    10092         """
     10094        r"""
    1009310095        Returns the first (optimal) proper vertex-coloring found.
    1009410096       
    1009510097        INPUT:
    1009610098       
    10097         - If ``algorithm = "DLX"`` (default), the chromatic number is computed
    10098           through the dancing link algorithm.
    10099 
    10100         - If ``algorithm = "MILP"``, the chromatic number
    10101           is computed through a Mixed Integer Linear Program.
    10102 
    10103           Computing the chromatic number through a Mixed Integer Linear
    10104           Program may require to install an optional Sage package like GLPK
    10105           or Coin-OR's CBC.
    10106 
    10107         - ``hex_colors`` -- if ``True``, return a dict which can
    10108            easily be used for plotting
    10109 
    10110         For more functions related to graph coloring, see
    10111         the ``sage.graphs.graph_coloring`` module.
     10099        - ``algorithm`` -- Select an algorithm from the following supported
     10100          algorithms:
     10101
     10102          - If ``algorithm="DLX"`` (default), the chromatic number is computed
     10103            using the dancing link algorithm.
     10104
     10105          - If ``algorithm="MILP"``, the chromatic number is computed using
     10106            a mixed integer linear program. This algorithm requires you to
     10107            install an optional Sage package like GLPK or COIN-OR's CBC.
     10108
     10109        - ``hex_colors`` -- (default: ``False``) if ``True``, return a
     10110          dictionary which can easily be used for plotting.
     10111
     10112        .. SEEALSO::
     10113
     10114            For more functions related to graph coloring, see the
     10115            module :mod:`sage.graphs.graph_coloring`.
    1011210116       
    1011310117        EXAMPLES::
    1011410118       
    1011510119            sage: G = Graph("Fooba")
    10116 
    1011710120            sage: P = G.coloring(algorithm="MILP"); P  # optional - requires GLPK or CBC
    1011810121            [[2, 1, 3], [0, 6, 5], [4]]
    1011910122            sage: P = G.coloring(algorithm="DLX"); P
    1012010123            [[1, 2, 3], [0, 5, 6], [4]]
    1012110124            sage: G.plot(partition=P)
    10122 
    10123             sage: H = G.coloring(hex_colors=True,algorithm="MILP") # optional - requires GLPK or CBC
    10124             sage: for c in sorted(H.keys()):                       # optional - requires GLPK or CBC
    10125             ...    print c, H[c]                                   # optional - requires GLPK or CBC
     10125            sage: H = G.coloring(hex_colors=True, algorithm="MILP") # optional - requires GLPK or CBC
     10126            sage: for c in sorted(H.keys()):                        # optional - requires GLPK or CBC
     10127            ...       print c, H[c]                                 # optional - requires GLPK or CBC
    1012610128            #0000ff [4]
    1012710129            #00ff00 [0, 6, 5]
    1012810130            #ff0000 [2, 1, 3]
    1012910131            sage: H = G.coloring(hex_colors=True, algorithm="DLX")
    1013010132            sage: for c in sorted(H.keys()):
    10131             ...    print c, H[c]
     10133            ...       print c, H[c]
    1013210134            #0000ff [4]
    1013310135            #00ff00 [1, 2, 3]
    1013410136            #ff0000 [0, 5, 6]
     
    1013910141            sage: G.coloring(algorithm="foo")
    1014010142            Traceback (most recent call last):
    1014110143            ...
    10142             ValueError: The `algorithm` variable must be set to either `DLX` or `MILP`.
     10144            ValueError: The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.
    1014310145        """
    1014410146        if algorithm == "MILP":
    1014510147            from sage.graphs.graph_coloring import vertex_coloring
    10146             return vertex_coloring(self,hex_colors=hex_colors)
     10148            return vertex_coloring(self, hex_colors=hex_colors)
    1014710149        elif algorithm == "DLX":
    1014810150            from sage.graphs.graph_coloring import first_coloring
    1014910151            return first_coloring(self, hex_colors=hex_colors)
    1015010152        else:
    10151             raise ValueError("The `algorithm` variable must be set to either `DLX` or `MILP`.")
     10153            raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.")
    1015210154   
    1015310155    ### Centrality
    1015410156
     
    1083810840
    1083910841        """
    1084010842        if self.is_directed() or self.has_loops() or self.has_multiple_edges():
    10841             raise ValueError("Self must be an undirected simple graph to have a clique_complex.")
     10843            raise ValueError("Self must be an undirected simple graph to have a clique complex.")
    1084210844        import sage.homology.simplicial_complex
    1084310845        C = sage.homology.simplicial_complex.SimplicialComplex(self.vertices(),self.cliques_maximal(),maximality_check=True)
    1084410846        C._graph = self
  • sage/graphs/graph_coloring.py

    diff -r ba3480f452b5 -r 6bb946d9b299 sage/graphs/graph_coloring.py
    a b  
    22Graph Coloring Functions
    33
    44AUTHORS:
    5     -- Tom Boothby   (2008-02-21): Initial version
    6     -- Carlo Hamalainen (2009-03-28): minor change: switch to C++ DLX solver
    7     -- Nathann Cohen (2009-10-24): Coloring methods using Linear Programming
     5
     6- Tom Boothby (2008-02-21): Initial version
     7- Carlo Hamalainen (2009-03-28): minor change: switch to C++ DLX solver
     8- Nathann Cohen (2009-10-24): Coloring methods using linear programming
    89"""
    910
    1011#*****************************************************************************
     
    142143    except RuntimeError:
    143144        raise RuntimeError, "Too much recursion!  Graph coloring failed."
    144145
    145 def first_coloring(G,n=0, hex_colors=True):
    146     """
     146def first_coloring(G, n=0, hex_colors=False):
     147    r"""
    147148    Given a graph, and optionally a natural number `n`, returns
    148149    the first coloring we find with at least `n` colors.
    149150
    150151    INPUT:
    151152
    152     - ``hex_colors`` -- When set to ``True`` ( it is ``False`` by default ),
    153        the partition returned is a dictionary whose keys are colors and whose
    154        values are the color classes ( ideal to be plotted )
    155     -  ``n`` -- The minimal number of colors to be tried.
     153    - ``hex_colors`` -- (default: ``False``) when set to ``True``, the
     154      partition returned is a dictionary whose keys are colors and whose
     155      values are the color classes (ideal for plotting).
    156156
     157    -  ``n`` -- The minimal number of colors to try.
    157158
    158     EXAMPLES:
     159    EXAMPLES::
     160
    159161        sage: from sage.graphs.graph_coloring import first_coloring
    160         sage: G = Graph({0:[1,2,3],1:[2]})
    161         sage: first_coloring(G,3)
    162         {'#00ff00': [1, 3], '#ff0000': [0], '#0000ff': [2]}
     162        sage: G = Graph({0: [1, 2, 3], 1: [2]})
     163        sage: first_coloring(G, 3)
     164        [[1, 3], [0], [2]]
    163165    """
    164166    o = G.order()
    165     for m in range(n,o+1):
    166         for C in all_graph_colorings(G,m):
     167    for m in xrange(n, o + 1):
     168        for C in all_graph_colorings(G, m):
    167169            if hex_colors:
    168170                return C
    169171            else:
     
    240242        for C in all_graph_colorings(G,n):
    241243            return n   
    242244
    243 
    244 def vertex_coloring(self,k=None,value_only=False,hex_colors=False,log=0):
    245     """
    246     Computes the chromatic number of a graph, or tests its `k`-colorability
    247     ( cf. http://en.wikipedia.org/wiki/Graph_coloring )
     245def vertex_coloring(g, k=None, value_only=False, hex_colors=False, log=0):
     246    r"""
     247    Computes the chromatic number of the given graph or tests its
     248    `k`-colorability. See http://en.wikipedia.org/wiki/Graph_coloring for
     249    further details on graph coloring.
    248250   
    249251    INPUT:
    250252
    251     - ``value_only`` ( boolean )--
    252         - When set to ``True``, only the chromatic number is returned
    253         - When set to ``False`` (default), a partition of the vertex set into
    254           independant sets is returned is possible
     253    - ``g`` -- a graph.
    255254
    256     - ``k`` ( an integer ) -- Tests whether the graph is `k`-colorable.
    257       The function returns a partition of the vertex set in `k`
    258       independent sets if possible and ``False`` otherwise.
     255    - ``k`` -- (default: ``None``) tests whether the graph is `k`-colorable.
     256      The function returns a partition of the vertex set in `k` independent
     257      sets if possible and ``False`` otherwise.
    259258
    260     - ``hex_colors`` -- When set to ``True`` ( it is ``False`` by default ),
    261        the partition returned is a dictionary whose keys are colors and whose
    262        values are the color classes ( ideal to be plotted )
     259    - ``value_only`` -- (default: ``False``):
    263260
    264     - ``log`` ( integer ) -- As vertex-coloring is a `NP`-complete problem,
    265       its solving may take some time depending on the graph. Use ``log`` to
    266       define the level of verbosity you want from the linear program solver.
    267                        
    268       By default ``log=0``, meaning that there will be no message printed by the solver.
     261      - When set to ``True``, only the chromatic number is returned.
    269262
    270     OUTPUT :
     263      - When set to ``False`` (default), a partition of the vertex set into
     264        independent sets is returned if possible.
     265
     266    - ``hex_colors`` -- (default: ``False``) when set to ``True``, the
     267      partition returned is a dictionary whose keys are colors and whose
     268      values are the color classes (ideal for plotting).
     269
     270    - ``log`` -- (default: ``0``) as vertex-coloring is an `NP`-complete
     271      problem, this function may take some time depending on the graph.
     272      Use ``log`` to define the level of verbosity you want from the
     273      linear program solver. By default ``log=0``, meaning that there will
     274      be no message printed by the solver.
     275
     276    OUTPUT:
    271277   
    272     - If ``k=None`` and ``value_only=None``:
    273       Returns a partition of the vertex set into the minimum possible of independent sets
     278    - If ``k=None`` and ``value_only=False``, then return a partition of the
     279      vertex set into the minimum possible of independent sets.
    274280
    275     - If ``k=None`` and ``value_only=True``:
    276       Returns the chromatic number
     281    - If ``k=None`` and ``value_only=True``, return the chromatic number.
    277282             
    278     - If ``k`` is set and ``value_only=None``:
    279       Returns False if the graph is not `k`-colorable, and a partition of the
    280       vertex set into `k` independent sets otherwise
     283    - If ``k`` is set and ``value_only=None``, return ``False`` if the
     284      graph is not `k`-colorable, and a partition of the vertex set into
     285      `k` independent sets otherwise.
    281286
    282     - If ``k`` is set and ``value_only=True``:
    283       Test whether the graph is `k`-colorable and returns ``True`` or ``False`` accordingly
    284              
     287    - If ``k`` is set and ``value_only=True``, test whether the graph is
     288      `k`-colorable, and return ``True`` or ``False`` accordingly.
    285289
    286290    EXAMPLE::
    287291   
    288292       sage: from sage.graphs.graph_coloring import vertex_coloring
    289        sage: g=graphs.PetersenGraph()
     293       sage: g = graphs.PetersenGraph()
    290294       sage: vertex_coloring(g, value_only=True) # optional - requires GLPK or CBC
    291295       3
    292        
    293296    """
    294297    from sage.numerical.mip import MixedIntegerLinearProgram
    295298    from sage.plot.colors import rainbow
    296     g=self
    297299
    298300    # If k==None, tries to find an optimal coloring
    299     if k==None:
    300 
    301         # No need to start a linear program if the graph is an independent set or bipartite
    302         #
     301    if k is None:
     302        # No need to start a linear program if the graph is an
     303        # independent set or bipartite.
    303304        # - Independent set
    304         if g.size()==0:
     305        if g.size() == 0:
    305306            if value_only:
    306307                return 1
    307308            elif hex_colors:
    308                 return dict(zip(rainbow(1),g.vertices()))
     309                return dict(zip(rainbow(1), g.vertices()))
    309310            else:
    310311                return g.vertices()
    311 
    312312        # - Bipartite set
    313313        if g.is_bipartite():
    314             if value_only==True:
     314            if value_only:
    315315                return 2
    316             if hex_colors:
    317                 return dict(zip(rainbow(2),g.bipartite_sets()))
     316            elif hex_colors:
     317                return dict(zip(rainbow(2), g.bipartite_sets()))
    318318            else:
    319319                return g.bipartite_sets()
    320 
    321320        # - No need to try any k smaller than the maximum clique in the graph
    322         # - max, because the graph could be triangle-free
    323 
    324         k=max(3, g.clique_number() )
    325 
     321        # - max, because the graph could be triangle-free.
     322        k = max(3, g.clique_number())
    326323        while True:
    327324            # tries to color the graph, increasing k each time it fails.
    328             tmp=vertex_coloring(g, k=k, value_only=value_only,hex_colors=hex_colors,log=log)
    329             if tmp!=False:
     325            tmp = vertex_coloring(g, k=k, value_only=value_only,
     326                                  hex_colors=hex_colors, log=log)
     327            if tmp is not False:
    330328                if value_only:
    331329                    return k
    332330                else:
    333331                    return tmp
    334             k=k+1
     332            k += 1
    335333    else:
    336         # Is the graph empty ?
    337 
    338         # If the graph is empty, something should be returned..
     334        # Is the graph empty?
     335        # If the graph is empty, something should be returned.
    339336        # This is not so stupid, as the graph could be emptied
    340         # by the test of degeneracy
    341         if g.order()==0:
    342             if value_only==True:
     337        # by the test of degeneracy.
     338        if g.order() == 0:
     339            if value_only:
    343340                return True
    344             elif hex_colors==True:
    345                 return dict([(color,[]) for color in rainbow(k)])
     341            elif hex_colors:
     342                return dict([(color, []) for color in rainbow(k)])
    346343            else:
    347                 return [[] for i in range(k)]
    348 
    349         # Is the graph connected ?
    350 
     344                return [[] for i in xrange(k)]
     345        # Is the graph connected?
    351346        # This is not so stupid, as the graph could be disconnected
    352         # by the test of degeneracy ( as previously )
    353 
    354         if g.is_connected()==False:
    355             if value_only==True:
     347        # by the test of degeneracy (as previously).
     348        if not g.is_connected():
     349            if value_only:
    356350                for component in g.connected_components():
    357                     if vertex_coloring(g.subgraph(component),k=k,value_only=value_only,hex_colors=hex_colors,log=log)==False:
     351                    tmp = vertex_coloring(g.subgraph(component), k=k,
     352                                          value_only=value_only,
     353                                          hex_colors=hex_colors,
     354                                          log=log)
     355                    if tmp is False:
    358356                        return False
    359357                return True
    360 
    361             colorings=[]
     358            colorings = []
    362359            for component in g.connected_components():
    363                 tmp=vertex_coloring(g.subgraph(component),k=k,value_only=value_only,hex_colors=False,log=log)
    364                 if tmp==False:
     360                tmp = vertex_coloring(g.subgraph(component), k=k,
     361                                      value_only=value_only,
     362                                      hex_colors=False, log=log)
     363                if tmp is False:
    365364                    return False
    366365                colorings.append(tmp)
    367             value=[[] for color in range(k)]
    368             for color in range(k):
     366            value = [[] for color in xrange(k)]
     367            for color in xrange(k):
    369368                for component in colorings:
    370369                    value[color].extend(component[color])
    371 
    372370            if hex_colors:
    373                 return dict(zip(rainbow(k),value))
     371                return dict(zip(rainbow(k), value))
    374372            else:
    375373                return value
    376374                   
    377375        # Degeneracy
    378 
    379         # Vertices whose degree is less than k are of no importance in the coloring
    380 
    381         if min(g.degree())<k:
    382             vertices=set(g.vertices())
    383             deg=[]
    384             tmp=[v for v in vertices if g.degree(v)<k]
    385             while len(tmp)>0:
    386                 v=tmp.pop(0)
    387                 neighbors=list(set(g.neighbors(v)) & vertices)
    388                 if v in vertices and len(neighbors)<k:
     376        # Vertices whose degree is less than k are of no importance in
     377        # the coloring.
     378        if min(g.degree()) < k:
     379            vertices = set(g.vertices())
     380            deg = []
     381            tmp = [v for v in vertices if g.degree(v) < k]
     382            while len(tmp) > 0:
     383                v = tmp.pop(0)
     384                neighbors = list(set(g.neighbors(v)) & vertices)
     385                if v in vertices and len(neighbors) < k:
    389386                    vertices.remove(v)
    390387                    tmp.extend(neighbors)
    391388                    deg.append(v)
    392 
    393             if value_only==True:
    394                 return vertex_coloring(g.subgraph(list(vertices)),k=k,value_only=value_only,hex_colors=hex_colors,log=log)
    395 
    396             value=vertex_coloring(g.subgraph(list(vertices)),k=k,value_only=value_only,hex_colors=False,log=log)
    397             if value==False:
     389            if value_only:
     390                return vertex_coloring(g.subgraph(list(vertices)), k=k,
     391                                       value_only=value_only,
     392                                       hex_colors=hex_colors,
     393                                       log=log)
     394            value = vertex_coloring(g.subgraph(list(vertices)), k=k,
     395                                    value_only=value_only,
     396                                    hex_colors=False,
     397                                    log=log)
     398            if value is False:
    398399                return False
    399             while len(deg)>0:
     400            while len(deg) > 0:
    400401                for classe in value:
    401                     if len(list(set(classe) & set(g.neighbors(deg[-1]))))==0:
     402                    if len(list(set(classe) & set(g.neighbors(deg[-1])))) == 0:
    402403                        classe.append(deg[-1])
    403404                        deg.pop(-1)
    404405                        break
    405406            if hex_colors:
    406                 return dict(zip(rainbow(k),value))
     407                return dict(zip(rainbow(k), value))
    407408            else:
    408409                return value
    409          
    410410       
    411         p=MixedIntegerLinearProgram(maximization=True)
    412         color=p.new_variable(dim=2)
    413 
     411        p = MixedIntegerLinearProgram(maximization=True)
     412        color = p.new_variable(dim=2)
    414413        # a vertex has exactly one color
    415         [p.add_constraint(sum([color[v][i] for i in range(k)]),min=1,max=1) for v in g.vertices()]
    416 
    417         # Adjacent vertices have different colors
    418         [p.add_constraint(color[u][i]+color[v][i],max=1) for (u,v) in g.edge_iterator(labels=None) for i in range(k)]
    419 
    420         # Anything is good as an objective value as long as it is satisfiable
    421         p.add_constraint(color[g.vertex_iterator().next()][0], max=1, min=1)
     414        [p.add_constraint(sum([color[v][i] for i in xrange(k)]), min=1, max=1)
     415             for v in g.vertices()]
     416        # adjacent vertices have different colors
     417        [p.add_constraint(color[u][i] + color[v][i], max=1)
     418             for (u, v) in g.edge_iterator(labels=None)
     419                 for i in xrange(k)]
     420        # anything is good as an objective value as long as it is satisfiable
     421        p.add_constraint(color[g.vertex_iterator().next()][0],  max=1, min=1)
    422422        p.set_objective(color[g.vertex_iterator().next()][0])
    423 
    424423        p.set_binary(color)
    425424        from sage.numerical.mip import MIPSolverException
    426 
    427425        try:
    428             if value_only==True:
    429                 p.solve(objective_only=True,log=log)
     426            if value_only:
     427                p.solve(objective_only=True, log=log)
    430428                return True
    431429            else:
    432                 chi=p.solve(log=log)
     430                chi = p.solve(log=log)
    433431        except MIPSolverException:
    434432            return False
    435433
    436         color=p.get_values(color)
    437 
     434        color = p.get_values(color)
    438435        # builds the color classes
    439         classes=[[] for i in range(k)]
    440         [classes[i].append(v) for i in range(k) for v in g.vertices() if color[v][i]==1]
    441 
     436        classes = [[] for i in xrange(k)]
     437        [classes[i].append(v)
     438             for i in xrange(k)
     439                 for v in g.vertices()
     440                     if color[v][i] == 1]
    442441        if hex_colors:
    443             return dict(zip(rainbow(len(classes)),classes))
     442            return dict(zip(rainbow(len(classes)), classes))
    444443        else:
    445444            return classes
    446445
    447 def edge_coloring(self,value_only=False,vizing=False,hex_colors=False, log=0):
    448     """
    449     Properly colors the edges of a graph.
    450     ( cf. http://en.wikipedia.org/wiki/Edge_coloring )
     446def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, log=0):
     447    r"""
     448    Properly colors the edges of a graph. See the URL
     449    http://en.wikipedia.org/wiki/Edge_coloring for further details on
     450    edge coloring.
    451451   
    452452    INPUT:
    453453
    454     - ``value_only`` (boolean) --
     454    - ``g`` -- a graph.
    455455
    456         - When set to ``True``, only the chromatic index is returned
    457         - When set to ``False`` (default), a partition of the edge set into
    458           matchings is returned is possible
     456    - ``value_only`` -- (default: ``False``):
    459457
    460     - ``vizing`` (boolean) --
    461         - When set to ``True``, tries to find a `\Delta+1`-edge-coloring ( where
    462           `\Delta` is equal to the maximum degree in the graph )
     458      - When set to ``True``, only the chromatic index is returned.
    463459
    464         - When set to ``False``, tries to find a `\Delta`-edge-coloring ( where
    465           `\Delta` is equal to the maximum degree in the graph ). If impossible,
    466           tries to find and returns a `\Delta+1`-edge-coloring
    467                        
    468               --- Implies ``value_only = False`` ---
     460      - When set to ``False``, a partition of the edge set into
     461        matchings is returned if possible.
    469462
    470     - ``hex_colors`` (boolean) --
     463    - ``vizing`` -- (default: ``False``):
    471464
    472       When set to ``True`` ( it is ``False`` by default ), the partition returned
    473       is a dictionary whose keys are colors and whose values are the color classes
    474       ( ideal to be plotted )
     465      - When set to ``True``, tries to find a `\Delta + 1`-edge-coloring,
     466        where `\Delta` is equal to the maximum degree in the graph.
    475467
    476     - ``log`` ( integer ) --
    477       As edge-coloring is a `NP`-complete problem, its solving may take some time
    478       depending on the graph. Use ``log`` to define the level of verbosity you want
    479       from the linear program solver.
     468      - When set to ``False``, tries to find a `\Delta`-edge-coloring,
     469        where `\Delta` is equal to the maximum degree in the graph. If
     470        impossible, tries to find and returns a `\Delta + 1`-edge-coloring.
     471        This implies that ``value_only=False``.
    480472
    481       By default ``log=0``, meaning that there will be no message printed by the solver.
     473    - ``hex_colors`` -- (default: ``False``) when set to ``True``, the
     474      partition returned is a dictionary whose keys are colors and whose
     475      values are the color classes (ideal for plotting).
    482476
    483     OUTPUT :
     477    - ``log`` -- (default: ``0``) as edge-coloring is an `NP`-complete
     478      problem, this function may take some time depending on the graph. Use
     479      ``log`` to define the level of verbosity you wantfrom the linear
     480      program solver. By default ``log=0``, meaning that there will be no
     481      message printed by the solver.
     482
     483    OUTPUT:
    484484
    485485    In the following, `\Delta` is equal to the maximum degree in the graph
     486    ``g``.
    486487   
    487     - If ``vizing=True`` and ``value_only=False``:
    488               Returns a partition of the edge set into Delta+1 matchings
     488    - If ``vizing=True`` and ``value_only=False``, return a partition of
     489      the edge set into `\Delta + 1` matchings.
    489490
    490     - If ``vizing=False`` and ``value_only=True``:
    491               Returns the chromatic index
     491    - If ``vizing=False`` and ``value_only=True``, return the chromatic index.
    492492
    493     - If ``vizing=False`` and ``value_only=False``:
    494               Returns a partition of the edge set into the minimum number of matchings
     493    - If ``vizing=False`` and ``value_only=False``, return a partition of
     494      the edge set into the minimum number of matchings.
    495495             
    496     - If ``vizing=True`` is set and ``value_only=True``:
    497               Should return something, but mainly you are just trying to compute the maximum
    498               degree of the graph, and this is not the easiest way ;-)
    499                By Vizing's theorem, a graph has a chromatic index equal to `\Delta`
    500               or to `\Delta+1`
     496    - If ``vizing=True`` and ``value_only=True``, should return something,
     497      but mainly you are just trying to compute the maximum degree of the
     498      graph, and this is not the easiest way. By Vizing's theorem, a graph
     499      has a chromatic index equal to `\Delta` or to `\Delta + 1`.
    501500
    502501    EXAMPLE::
    503502   
    504503       sage: from sage.graphs.graph_coloring import edge_coloring
    505        sage: g=graphs.PetersenGraph()
     504       sage: g = graphs.PetersenGraph()
    506505       sage: edge_coloring(g, value_only=True) # optional - requires GLPK or CBC
    507506       4
    508507
    509     Completes graphs are colored using the linear-time Round-robin coloring ::
     508    Complete graphs are colored using the linear-time round-robin coloring::
    510509
    511510       sage: from sage.graphs.graph_coloring import edge_coloring
    512511       sage: len(edge_coloring(graphs.CompleteGraph(20)))
    513512       19
    514        
    515513    """
    516514    from sage.numerical.mip import MixedIntegerLinearProgram
    517515    from sage.plot.colors import rainbow
    518     g=self
    519 
    520516
    521517    if g.is_clique():
    522518        if value_only:
    523             return g.order() if g.order() % 2 ==0 else g.order()+1
    524         vertices=g.vertices()
     519            return g.order() if g.order() % 2 == 0 else g.order() + 1
     520        vertices = g.vertices()
    525521        r = round_robin(g.order())
    526         classes=[[] for v in g]
    527         if g.order() % 2 == 0 and vizing == False:
     522        classes = [[] for v in g]
     523        if g.order() % 2 == 0 and not vizing:
    528524            classes.pop()
    529 
    530         for (u,v,c) in r.edge_iterator():
     525        for (u, v, c) in r.edge_iterator():
    531526            classes[c].append((vertices[u], vertices[v]))
    532        
    533527        if hex_colors:
    534             from sage.plot.colors import rainbow
    535             return zip(rainbow(len(classes)),classes)
     528            return zip(rainbow(len(classes)), classes)
    536529        else:
    537530            return classes             
    538        
    539531
    540     p=MixedIntegerLinearProgram(maximization=True)
    541     color=p.new_variable(dim=2)
    542     obj={}
    543     k=max(g.degree())
    544 
     532    p = MixedIntegerLinearProgram(maximization=True)
     533    color = p.new_variable(dim=2)
     534    obj = {}
     535    k = max(g.degree())
    545536    # reorders the edge if necessary...
    546     R = lambda x : x if (x[0]<=x[1]) else (x[1],x[0],x[2])
    547 
    548     # Vizing's coloring uses Delta+1 colors
     537    R = lambda x: x if (x[0] <= x[1]) else (x[1], x[0], x[2])
     538    # Vizing's coloring uses Delta + 1 colors
    549539    if vizing:
    550         value_only=False
    551         k=k+1
    552 
    553     #  A vertex can not have two incident edges with
    554     # the same color
    555     [p.add_constraint(sum([color[R(e)][i] for e in g.edges_incident(v)]),max=1) for v in g.vertex_iterator() for i in range(k)]
    556 
    557     # An edge must have a color
    558     [p.add_constraint(sum([color[R(e)][i] for i in range(k)]),max=1,min=1) for e in g.edge_iterator()]
    559 
    560     # Anything is good as an objective value as long as it is satisfiable
    561     e=g.edge_iterator().next()
     540        value_only = False
     541        k += 1
     542    #  A vertex can not have two incident edges with the same color.
     543    [p.add_constraint(
     544            sum([color[R(e)][i] for e in g.edges_incident(v)]), max=1)
     545                for v in g.vertex_iterator()
     546                    for i in xrange(k)]
     547    # an edge must have a color
     548    [p.add_constraint(sum([color[R(e)][i] for i in xrange(k)]), max=1, min=1)
     549         for e in g.edge_iterator()]
     550    # anything is good as an objective value as long as it is satisfiable
     551    e = g.edge_iterator().next()
    562552    p.set_objective(color[R(e)][0])
    563 
    564553    p.set_binary(color)
    565554    try:
    566         if value_only==True:
    567             p.solve(objective_only=True,log=log)
     555        if value_only:
     556            p.solve(objective_only=True, log=log)
    568557        else:
    569             chi=p.solve(log=log)
     558            chi = p.solve(log=log)
    570559    except:
    571560        if value_only:
    572             return k+1
     561            return k + 1
    573562        else:
    574             # if the coloring with Delta colors fails, tries Delta+1
    575             return edge_coloring(g,vizing=True,hex_colors=hex_colors,log=log)
     563            # if the coloring with Delta colors fails, tries Delta + 1
     564            return edge_coloring(g, vizing=True, hex_colors=hex_colors, log=log)
    576565    if value_only:
    577566        return k
    578 
    579567    # Builds the color classes
    580     color=p.get_values(color)
    581     classes=[[] for i in range(k)]
    582     [classes[i].append(e) for e in g.edge_iterator() for i in range(k) if color[R(e)][i]==1]
     568    color = p.get_values(color)
     569    classes = [[] for i in xrange(k)]
     570    [classes[i].append(e)
     571         for e in g.edge_iterator()
     572             for i in xrange(k)
     573                 if color[R(e)][i] == 1]
    583574    # if needed, builds a dictionary from the color classes adding colors
    584575    if hex_colors:
    585         return dict(zip(rainbow(len(classes)),classes))
     576        return dict(zip(rainbow(len(classes)), classes))
    586577    else:
    587578        return classes
    588579
    589580def round_robin(n):
    590581    r"""
    591     Computes a Round-robin coloring of the complete graph on `n` vertices.
     582    Computes a round-robin coloring of the complete graph on `n` vertices.
    592583
    593     A Round-robin coloring of the complete graph `G` on
    594     `2n` vertices (`V=[0,\dots,2n-1]`) is a proper coloring of its edges
    595     such that the edges with color `i` are all the `(i+j,i-j)`, plus the
    596     edge `(2n-1,i)`.
     584    A round-robin coloring of the complete graph `G` on `2n` vertices
     585    (`V = [0, \dots, 2n - 1]`) is a proper coloring of its edges such that
     586    the edges with color `i` are all the `(i + j, i - j)` plus the
     587    edge `(2n - 1, i)`.
    597588
    598     If `n` is odd, one obtain a Round-robin coloring of the complete graph
    599     through the Round-robin coloring of the graph with `n+1` vertices, to
    600     which one is removed.
     589    If `n` is odd, one obtain a round-robin coloring of the complete graph
     590    through the round-robin coloring of the graph with `n + 1` vertices.
    601591
    602592    INPUT:
    603593
     
    605595
    606596    OUTPUT:
    607597
    608     - A CompleteGraph with labelled edges, such that the label of each
     598    - A ``CompleteGraph`` with labelled edges such that the label of each
    609599      edge is its color.
    610600
    611601    EXAMPLES::
     
    638628        True
    639629        sage: Set([e[2] for e in g.edge_iterator()]).cardinality()
    640630        9       
    641 
    642 
    643631    """
    644 
    645     if not (n>1):
    646         raise ValueError, "There must be at least two vertices in the graph."
    647 
    648     mod = lambda x,y : x - y*(x//y)
    649 
     632    if n <= 1:
     633        raise ValueError("There must be at least two vertices in the graph.")
     634    mod = lambda x, y: x - y*(x // y)
    650635    if n % 2 == 0:
    651         g=GraphGenerators().CompleteGraph(n)
    652         for i in range(n-1):
    653             g.set_edge_label(n-1,i,i)
    654             for j in range(1,(n-1)//2+1):
    655                 g.set_edge_label(mod(i-j,n-1),mod(i+j,n-1),i)
    656 
     636        g = GraphGenerators().CompleteGraph(n)
     637        for i in xrange(n - 1):
     638            g.set_edge_label(n - 1, i, i)
     639            for j in xrange(1, (n - 1) // 2 + 1):
     640                g.set_edge_label(mod(i - j, n - 1), mod(i + j, n - 1), i)
    657641        return g
    658            
    659642    else:
    660         g=round_robin(n+1)
     643        g = round_robin(n + 1)
    661644        g.delete_vertex(n)
    662645        return g
    663646
    664 
    665647class Test:
    666648    """
    667649    This class performs randomized testing for all_graph_colorings.