Ticket #8166: trac_8166.patch

File trac_8166.patch, 5.8 KB (added by ncohen, 11 years ago)
  • sage/graphs/generic_graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1273950179 14400
    # Node ID 65fc9f7cd99e2b92e69727fd5bf63ba6fec4b984
    # Parent  45fc4178e0672a4996a4e6b9083b05800d51db04
    trac #8166 - max matching
    
    diff -r 45fc4178e067 -r 65fc9f7cd99e sage/graphs/generic_graph.py
    a b  
    38423842        return paths
    38433843
    38443844
    3845     def matching(self,value_only=False, use_edge_labels=True, solver=None, verbose=0):
     3845    def matching(self,value_only=False, algorithm = "Edmonds", use_edge_labels=True, solver=None, verbose=0):
    38463846        r"""
    38473847        Returns a maximum weighted matching of the graph
    38483848        represented by the list of its edges. For more information, see the
     
    38623862            &\forall x\in G, b_x\mbox{ is a binary variable}
    38633863   
    38643864        INPUT:
     3865
     3866        - ``algorithm`` (string)
     3867
     3868          - ``"Edmonds"`` selects Edmonds' algorithm as implemented in NetworkX
     3869          - ``"LP"`` uses a Linear Program formulation of the matching problem
     3870
     3871          By default, Emonds' algorithm is used.
    38653872   
    38663873        - ``value_only`` (boolean)
    38673874
     
    38813888          function of ``MixedIntegerLinearProgram``. See the documentation  of ``MixedIntegerLinearProgram.solve``
    38823889          for more informations.
    38833890
     3891          Only useful when ``algorithm == "LP"``.
     3892
    38843893        - ``verbose`` (integer) -- sets the level of verbosity. Set to 0
    38853894          by default (quiet).
    3886    
    3887         EXAMPLE::
     3895
     3896          Only useful when ``algorithm == "LP"``.
     3897
     3898        ALGORITHM:
     3899
     3900        The problem is solved using Edmond's algorithm inplemented in NetworkX,
     3901        or using Linear Programming depending on the value of ``algorithm``.
     3902   
     3903        EXAMPLE:
     3904
     3905        Maximum matching in a Pappus Graph::
    38883906       
    38893907           sage: g=graphs.PappusGraph()
    3890            sage: g.matching(value_only=True) # optional - requires Glpk or COIN-OR/CBC
     3908           sage: g.matching(value_only=True)
    38913909           9.0
    3892         """
    3893 
    3894         from sage.numerical.mip import MixedIntegerLinearProgram
    3895         g=self
    3896 
    3897         # returns the weight of an edge considering it may not be
    3898         # weighted ...
     3910
     3911        Same test with the Linear Program formulation ::
     3912
     3913           sage: g=graphs.PappusGraph()
     3914           sage: g.matching(algorithm = "LP", value_only=True) # optional - requires GLPK CBC or CPLEX
     3915           9.0
     3916
     3917        If ``algorithm`` is set to anything different from ``"Edmonds"`` or ``"LP"``, an
     3918        exception is raised ::
     3919
     3920           sage: g.matching(algorithm="somethingdifferent")
     3921           ...
     3922           ValueError: Algorithm must be set to either "Edmonds" or "LP"
     3923        """
    38993924
    39003925        from sage.rings.real_mpfr import RR
    39013926        weight=lambda x: x if x in RR else 1
    39023927
    3903         p=MixedIntegerLinearProgram(maximization=True)
    3904 
    3905         b=p.new_variable(dim=2)
    3906         p.set_objective(sum([weight(w)*b[min(u,v)][max(u,v)] for (u,v,w) in g.edges()]))
    3907 
    3908 
    3909         # for any vertex v, there is at most one edge incident to v in the maximum matching
    3910         for v in g.vertices():
    3911             p.add_constraint(sum([b[min(u,v)][max(u,v)] for u in g.neighbors(v)]),max=1)
    3912 
    3913         p.set_binary(b)
    3914    
    3915         if value_only:
    3916             return p.solve(objective_only=True, solver = solver, log = verbose)
    3917         else:
    3918             p.solve(solver = solver, log = verbose)
    3919             b=p.get_values(b)
    3920             return [(u,v,w) for (u,v,w) in g.edges() if b[min(u,v)][max(u,v)] == 1]
     3928        if algorithm == "Edmonds":
     3929
     3930            import networkx
     3931
     3932            if use_edge_labels:
     3933                g = networkx.Graph()
     3934                for u,v,l in self.edges():
     3935                    g.add_edge(u,v, attr_dict={"weight":weight(l)})
     3936            else:
     3937                g = self.networkx_graph(copy=False)
     3938
     3939            d =  networkx.max_weight_matching(g)
     3940
     3941            if value_only:
     3942                return sum([ weight(self.edge_label(u,v)) for u,v in d.iteritems()])*0.5
     3943
     3944            else:
     3945                return [(u,v,self.edge_label(u,v)) for u,v in d.iteritems() if u<v]
     3946           
     3947        elif algorithm == "LP":
     3948
     3949            from sage.numerical.mip import MixedIntegerLinearProgram
     3950            g=self
     3951   
     3952            # returns the weight of an edge considering it may not be
     3953            # weighted ...
     3954   
     3955            p=MixedIntegerLinearProgram(maximization=True)
     3956   
     3957            b=p.new_variable(dim=2)
     3958            p.set_objective(sum([weight(w)*b[min(u,v)][max(u,v)] for (u,v,w) in g.edges()]))
     3959   
     3960   
     3961            # for any vertex v, there is at most one edge incident to v in the maximum matching
     3962            for v in g.vertices():
     3963                p.add_constraint(sum([b[min(u,v)][max(u,v)] for u in g.neighbors(v)]),max=1)
     3964   
     3965            p.set_binary(b)
     3966       
     3967            if value_only:
     3968                return p.solve(objective_only=True, solver = solver, log = verbose)
     3969            else:
     3970                p.solve(solver = solver, log = verbose)
     3971                b=p.get_values(b)
     3972                return [(u,v,w) for (u,v,w) in g.edges() if b[min(u,v)][max(u,v)] == 1]
     3973
     3974        else:
     3975            raise ValueError("Algorithm must be set to either \"Edmonds\" or \"LP\"")
    39213976
    39223977    def dominating_set(self, independent=False, value_only=False, solver=None, verbose=0):
    39233978        r"""
  • sage/graphs/graph.py

    diff -r 45fc4178e067 -r 65fc9f7cd99e sage/graphs/graph.py
    a b  
    31533153   
    31543154        return classes_b
    31553155
    3156     def max_weight_matching(self):
    3157         import networkx
    3158         return networkx.max_weight_matching(self.networkx_graph(copy=False))
    3159 
    3160 
    31613156def compare_edges(x, y):
    31623157    """
    31633158    Compare edge x to edge y, return -1 if x y, 1 if x y, else 0.