# HG changeset patch
# User Nathann Cohen
# Date 1276001765 -7200
# Node ID 90a1fda9099b6741567239beb684301137b22c41
# Parent cb1ad1ee5bd452850fde04d47f9618dec4c3e997
trac 8953 -- Graph.is_perfect
diff -r cb1ad1ee5bd4 -r 90a1fda9099b sage/graphs/graph.py
--- a/sage/graphs/graph.py Fri Jul 16 01:54:01 2010 -0700
+++ b/sage/graphs/graph.py Tue Jun 08 14:56:05 2010 +0200
@@ -1654,6 +1654,128 @@
return left == right
+ def is_perfect(self, certificate = False):
+ r"""
+ Tests whether the graph is perfect.
+
+ A graph `G` is said to be perfect if `\chi(H)=\omega(H)` hold
+ for any induced subgraph `H\subseteq_i G` (and so for `G`
+ itself, too), where `\chi(H)` represents the chromatic number
+ of `H`, and `\omega(H)` its clique number. The Strong Perfect
+ Graph Theorem [SPGT]_ gives another characterization of
+ perfect graphs:
+
+ A graph is perfect if and only if it contains no odd hole
+ (cycle on an odd number `k` of vertices, `k>3`) nor any odd
+ antihole (complement of a hole) as an induced subgraph.
+
+ INPUT:
+
+ - ``certificate`` (boolean) -- whether to return
+ a certificate (default : ``False``)
+
+ OUTPUT:
+
+ When ``certificate = False``, this function returns
+ a boolean value. When ``certificate = True``, it returns
+ a subgraph of ``self`` isomorphic to an odd hole or an odd
+ antihole if any, and ``None`` otherwise.
+
+ EXAMPLE:
+
+ A Bipartite Graph is always perfect ::
+
+ sage: g = graphs.RandomBipartite(8,4,.5)
+ sage: g.is_perfect()
+ True
+
+ Interval Graphs, which are chordal graphs, too ::
+
+ sage: g = graphs.RandomInterval(7)
+ sage: g.is_perfect()
+ True
+
+ The PetersenGraph, which is triangle-free and
+ has chromatic number 3 is obviously not perfect::
+
+ sage: g = graphs.PetersenGraph()
+ sage: g.is_perfect()
+ False
+
+ We can obtain an induced 5-cycle as a certificate::
+
+ sage: g.is_perfect(certificate = True)
+ Subgraph of (Petersen graph): Graph on 5 vertices
+
+ REFERENCES:
+
+ .. [SPGT] M. Chudnovsky, N. Robertson, P. Seymour, R. Thomas.
+ The strong perfect graph theorem
+ Annals of Mathematics
+ vol 164, number 1, pages 51--230
+ 2006
+ """
+
+ from sage.graphs.bipartite_graph import BipartiteGraph
+
+ if isinstance(self, BipartiteGraph) or self.is_bipartite():
+ return True if not certificate else None
+
+ self_complement = self.complement()
+
+ start_complement = self_complement.girth()
+ start_self = self.girth()
+
+ from sage.graphs.graph_generators import graphs
+
+
+ # In these cases, we know the graph is no perfect.
+ if start_self == 5:
+ if certificate:
+ return self.subgraph_search(graphs.CycleGraph(5), induced = True)
+ else:
+ return False
+
+ if start_complement == 5:
+ if certificate:
+ return self_complement.subgraph_search(graphs.CycleGraph(5), induced = True).complement()
+ else:
+ return False
+
+ # We are only looking for odd holes of size at least 5
+ from sage.rings.finite_rings.integer_mod import Mod
+
+ start = lambda x : (x+1) if Mod(x,2) == 0 else ( 5 if x == 3 else x )
+
+ # these values are possibly the infinity !!!!
+
+ start_self = start(start_self) if start_self <= self.order() else self.order()+2
+ start_complement = start(start_complement) if start_complement <= self.order() else self.order()+2
+
+ counter_example = None
+
+ for i in range(min(start_self, start_complement), self.order()+1,2):
+
+ # trying in self
+ if i >= start_self:
+ counter_example = self.subgraph_search(graphs.CycleGraph(i), induced = True)
+
+ if counter_example is not None:
+ break
+
+ # trying in the complement
+ if i >= start_complement:
+ counter_example = self.subgraph_search(graphs.CycleGraph(i), induced = True)
+ if counter_example is not None:
+ counter_example = counter_example.complement()
+ break
+
+ if certificate:
+ return counter_example
+ else:
+ return counter_example is None
+
+
def degree_constrained_subgraph(self, bounds=None, solver=None, verbose=0):
r"""
Returns a degree-constrained subgraph.