Ticket #11846: trac_11846.patch

File trac_11846.patch, 3.8 KB (added by ncohen, 9 years ago)
  • sage/graphs/graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1316957562 -7200
    # Node ID 3a03752d5274112fc0c54f44e7f883175a9c5cb3
    # Parent  6d083e3d29a3ee52e0e72ebe4964a3cf87a84b99
    trac #11846 -- MILP algorithm for the Graph.independent_set method
    
    diff -r 6d083e3d29a3 -r 3a03752d5274 sage/graphs/graph.py
    a b  
    37363736        import networkx
    37373737        return BipartiteGraph(networkx.make_clique_bipartite(self.networkx_graph(copy=False), **kwds))
    37383738
    3739     def independent_set(self):
     3739    def independent_set(self, algorithm = "Cliquer", verbose = 0):
    37403740        """
    3741         Returns a maximal independent set, which is a set of vertices which
    3742         induces an empty subgraph. Uses Cliquer [NisOst2003]_.
     3741        Returns a maximum independent set.
     3742
     3743        An independent set of a graph is a set of pairwise nonadjacent
     3744        vertices. A maximum independent set is an independent set of maximum
     3745        cardinality.  induces an empty subgraph.
     3746
     3747        INPUT:
     3748
     3749        - ``algorithm`` -- the algorithm to be used
     3750
     3751            * If ``algorithm = "Cliquer"`` (default), the problem is solved
     3752              using Cliquer [NisOst2003]_.
     3753
     3754              (see the :mod:`Cliquer modules <sage.graphs.cliquer>`)
     3755
     3756            * If ``algorithm = "MILP"``, the problem is solved through a Mixed
     3757              Integer Linear Program.
     3758
     3759              (see :class:`MixedIntegerLinearProgram
     3760              <sage.numerical.mip>`)
     3761
     3762        - ``verbose`` -- integer (default: ``0``). Sets the level of
     3763          verbosity. Set to 0 by default, which means quiet.
     3764         
     3765          Only useful when ``algorithm = "MILP"``.
     3766
     3767
     3768        .. NOTE::
     3769
     3770            While Cliquer is usually (and by far) the most efficient of the two
     3771            implementations, the Mixed Integer Linear Program formulation
     3772            sometimes proves faster on very "symmetrical" graphs.
    37433773       
    3744         .. NOTE::
    3745        
    3746             Currently only implemented for undirected graphs. Use to_undirected
    3747             to convert a digraph to an undirected graph.
    3748        
    3749         EXAMPLES::
     3774        EXAMPLES:
     3775
     3776        Using Cliquer::
    37503777       
    37513778            sage: C=graphs.PetersenGraph()
    37523779            sage: C.independent_set()
    37533780            [0, 3, 6, 7]
     3781
     3782        As a linear program::
     3783
     3784            sage: C=graphs.PetersenGraph()
     3785            sage: len(C.independent_set(algorithm = "MILP"))
     3786            4
     3787
     3788        TESTS:
     3789
     3790        Given a wrong algorithm::
     3791
     3792            sage: C.independent_set(algorithm = "guess")
     3793            Traceback (most recent call last):
     3794            ...
     3795            ValueError: The algorithm must be either "Cliquer" or "MILP".
    37543796        """
    3755         from sage.graphs.cliquer import max_clique
    3756         return max_clique(self.complement())
     3797        if algorithm == "Cliquer":
     3798            from sage.graphs.cliquer import max_clique
     3799            return max_clique(self.complement())
     3800
     3801        elif algorithm == "MILP":
     3802            from sage.numerical.mip import MixedIntegerLinearProgram, Sum
     3803
     3804            p = MixedIntegerLinearProgram(maximization = True)
     3805
     3806            b = p.new_variable(binary = True)
     3807
     3808            p.set_objective(Sum([b[v] for v in self]))
     3809
     3810            for u,v in self.edges(labels = False):
     3811                if u == v:
     3812                    continue
     3813
     3814                p.add_constraint(b[u] + b[v] <= 1)
     3815
     3816            p.solve(log = verbose)
     3817
     3818            b = p.get_values(b)
     3819
     3820            return [v for v in self if b[v] > .5]           
     3821           
     3822        else:
     3823            raise ValueError("The algorithm must be either \"Cliquer\" or \"MILP\".")
    37573824   
    37583825    def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None,
    37593826                                     cliques=None):