# 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): 