# 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
|
|
3736 | 3736 | import networkx |
3737 | 3737 | return BipartiteGraph(networkx.make_clique_bipartite(self.networkx_graph(copy=False), **kwds)) |
3738 | 3738 | |
3739 | | def independent_set(self): |
| 3739 | def independent_set(self, algorithm = "Cliquer", verbose = 0): |
3740 | 3740 | """ |
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. |
3743 | 3773 | |
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:: |
3750 | 3777 | |
3751 | 3778 | sage: C=graphs.PetersenGraph() |
3752 | 3779 | sage: C.independent_set() |
3753 | 3780 | [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". |
3754 | 3796 | """ |
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\".") |
3757 | 3824 | |
3758 | 3825 | def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, |
3759 | 3826 | cliques=None): |