# Ticket #14434: trac_14434-clean_doc.patch

File trac_14434-clean_doc.patch, 5.8 KB (added by vdelecroix, 6 years ago)
• ## sage/graphs/generic_graph.py

```# HG changeset patch
# User Vincent Delecroix <20100.delecroix at gmail.com>
# Date 1370414735 -7200
# Node ID 210523cbe254aa29d2a1e7cd7090d97b04b8dcf0
# Parent  7eb54e37fcbcd2dd85894f17883479b765e83df2
trac 14334: clean documentation for feedback_vertex_set

diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py```
 a The minimum feedback vertex set of a (di)graph is a set of vertices that intersect all of its cycles.  Equivalently, a minimum feedback vertex set of a (di)graph is a set `S` of vertices such that the digraph `G-S` is acyclic. For more information, see the `Wikipedia article on feedback vertex sets `_. is acyclic. For more information, see :wikipedia:`Feedback_vertex_set`. INPUT: (Constraints generation) When the parameter ``constraint_generation`` is enabled (default) the following MILP formulation is used to solve the problem:: following MILP formulation is used to solve the problem: .. MATH:: As the number of circuits contained in a graph is exponential, this LP is solved through constraint generation. This means that the solver is sequentially asked to solved the problem, knowing only a portion of the sequentially asked to solve the problem, knowing only a portion of the circuits contained in `G`, each time adding to the list of its constraints the circuit which its last answer had left intact. In a digraph built from a graph, any edge is replaced by arcs going in the two opposite directions, thus creating a cycle of length two. Hence, to remove all the cycles from the graph, each edge must see one of its neighbors removed : a feedback vertex set is in this situation a of its neighbors removed: a feedback vertex set is in this situation a vertex cover:: sage: cycle=graphs.CycleGraph(5) sage: dcycle=DiGraph(cycle) sage: cycle = graphs.CycleGraph(5) sage: dcycle = DiGraph(cycle) sage: cycle.vertex_cover(value_only=True) 3 sage: feedback = dcycle.feedback_vertex_set() sage: g = digraphs.RandomDirectedGNP(10,.3) sage: x = g.feedback_vertex_set(value_only = True) sage: y = g.feedback_vertex_set(value_only = True, ...            constraint_generation = False) ....:          constraint_generation = False) sage: x == y True Bad algorithm:: Bad algorithm:: sage: g = graphs.PetersenGraph() sage: g.feedback_vertex_set(constraint_generation = False) Traceback (most recent call last): ... ValueError: The only implementation available for undirected graphs is with constraint_generation set to True. """ """ if not constraint_generation and not self.is_directed(): raise ValueError("The only implementation available for "+ raise ValueError("The only implementation available for " "undirected graphs is with constraint_generation " "set to True.") p = MixedIntegerLinearProgram(constraint_generation = True, maximization = False) # An variable for each vertex # A variable for each vertex b = p.new_variable(binary = True) # Variables are binary, and their coefficient in the objective is 1 p.set_objective( p.sum( b[v] for v in self)) p.set_objective(p.sum( b[v] for v in self)) p.solve(log = verbose) # There is a circuit left. Let's add the corresponding # constraint ! p.add_constraint( p.sum( b[v] for v in certificate), min = 1) p.add_constraint(p.sum(b[v] for v in certificate), min = 1) obj = p.solve(log = verbose) # Ordering-based MILP Implementation # ###################################### p = MixedIntegerLinearProgram(maximization=False, solver=solver) p = MixedIntegerLinearProgram(maximization = False, solver = solver) b = p.new_variable(binary = True) d = p.new_variable(integer = True) n = self.order() # The removed vertices cover all the back arcs ( third condition ) for (u,v) in self.edges(labels=None): p.add_constraint(d[u]-d[v]+n*(b[u]+b[v]),min=1) for (u,v) in self.edges(labels = None): p.add_constraint(d[u]-d[v]+n*(b[u]+b[v]), min = 1) for u in self: p.add_constraint(d[u],max=n) p.add_constraint(d[u], max = n) p.set_objective(p.sum([b[v] for v in self])) if value_only: return Integer(round(p.solve(objective_only=True, log=verbose))) return Integer(round(p.solve(objective_only = True, log = verbose))) else: p.solve(log=verbose) b_sol=p.get_values(b) return [v for v in self if b_sol[v]==1] b_sol = p.get_values(b) return [v for v in self if b_sol[v] == 1] def flow(self, x, y, value_only=True, integer=False, use_edge_labels=True, vertex_bound=False, method = None, solver=None, verbose=0): r"""