Ticket #8798: trac_8798-rebased.patch

File trac_8798-rebased.patch, 9.5 KB (added by mvngu, 10 years ago)
  • sage/graphs/generic_graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1272442371 -7200
    # Node ID 14825bd6369b50415a3dc8184ae20157e84ca4aa
    # Parent  9188e33e33ed5708fcccff34d429d701dec3baaa
    trac 8798 : remove duplicates of feedback_vertex_set and feedback_edge_set from generic_graph.py
    
    diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
    a b  
    33483348        else:
    33493349            raise ValueError("Only two algorithms are available : Cliquer and MILP.")
    33503350
    3351     def feedback_edge_set(self,value_only=False):
    3352         r"""
    3353         Computes the minimum feedback edge set of a digraph
    3354         ( also called feedback arc set ).
    3355 
    3356         The minimum feedback edge set of a digraph is a set of edges
    3357         that intersect all the circuits of the digraph.
    3358         Equivalently, a minimum feedback arc set of a DiGraph is a set
    3359         `S` of arcs such that the digraph `G-S` is acyclic. For more
    3360         information, see the
    3361         `Wikipedia article on feedback arc sets
    3362         <http://en.wikipedia.org/wiki/Feedback_arc_set>`_.
    3363 
    3364         INPUT :
    3365 
    3366         - ``value_only`` (boolean) --
    3367             - When set to ``True``, only the minimum
    3368               cardinal of a minimum edge set is
    3369               returned.
    3370 
    3371             - When set to ``False``, the ``Set`` of edges
    3372               of a minimal edge set is returned.
    3373 
    3374         This problem is solved using Linear Programming, which certainly
    3375         is not the best way and will have to be updated. The program solved
    3376         is the following :
    3377 
    3378         .. MATH:
    3379             \mbox{Minimize : }&\sum_{(u,v)\in G} b_{(u,v)}\\
    3380             \mbox{Such that : }&\\
    3381             &\forall v\in G, \sum_{i\in [0,\dots,n-1]}x_{v,i}=1\\
    3382             &\forall i\in [0,\dots,n-1], \sum_{v\in G}x_{v,i}=1\\
    3383             &\forall v\in G,\sum_{i\in [0,\dots,n-1]} ix_{v,i}=d_v\\
    3384             &\forall (u,v)\in G, d_u-d_v+nb_{(u,v)}\geq 0\\
    3385                        
    3386         An explanation :
    3387 
    3388         An acyclic digraph can be seen as a poset, and every poset has
    3389         a linear extension. This means that in any acyclic digraph
    3390         the vertices can be ordered with a total order `<` in such a way
    3391         that if `(u,v)\in G`, then `u<v`.
    3392 
    3393         Thus, this linear program is built in order to assign to each vertex
    3394         `v` an unique number `d_v\in [0,\dots,n-1]` such that if there exists
    3395         an edge `(u,v)\in G` such that `d_v<d_u`, then the edge `(u,v)` is
    3396         removed (`\Rightarrow x_{(u,v)}=1`).
    3397 
    3398         The number of edges removed is then minimized, which is
    3399         the objective.
    3400 
    3401         EXAMPLE :
    3402 
    3403         If the digraph is created from a graph, and hence is symmetric
    3404         ( if `uv` is an edge, then `vu` is an edge too ), then
    3405         obviously the cardinality of its feedback arc set is the number
    3406         of edges in the first graph ::
    3407 
    3408             sage: cycle=graphs.CycleGraph(5)
    3409             sage: dcycle=DiGraph(cycle)
    3410             sage: cycle.size()
    3411             5
    3412             sage: dcycle.feedback_edge_set(value_only=True)    # optional - requires GLPK or CBC
    3413             5.0
    3414        
    3415         And in this situation, for any edge `uv` of the first graph, `uv` of `vu`
    3416         is in the returned feedback arc set::
    3417 
    3418            sage: g = graphs.RandomGNP(5,.3)
    3419            sage: dg = DiGraph(g)
    3420            sage: feedback = dg.feedback_edge_set()             # optional - requires GLPK or CBC
    3421            sage: (u,v,l) = g.edge_iterator().next()
    3422            sage: (u,v) in feedback or (v,u) in feedback        # optional - requires GLPK or CBC
    3423            True
    3424         """
    3425        
    3426         from sage.numerical.mip import MixedIntegerLinearProgram
    3427        
    3428         p=MixedIntegerLinearProgram(maximization=False)
    3429        
    3430         b=p.new_variable()
    3431         x=p.new_variable(dim=2)
    3432         d=p.new_variable()
    3433         n=self.order()
    3434         N=range(n)
    3435 
    3436         # First and second constraints
    3437         for v in self:
    3438             p.add_constraint(sum([x[v][i] for i in N]),min=1,max=1)
    3439 
    3440         for i in N:
    3441             p.add_constraint(sum([x[v][i] for v in self]),min=1,max=1)
    3442        
    3443         # Definition of d_v
    3444         for v in self:
    3445             p.add_constraint(sum([i*x[v][i] for i in N])-d[v],max=0,min=0)
    3446 
    3447         # The removed vertices cover all the back arcs ( third condition )
    3448         for (u,v) in self.edges(labels=None):
    3449             p.add_constraint(d[u]-d[v]+n*(b[(u,v)]),min=0)
    3450 
    3451         p.set_binary(b)
    3452         p.set_binary(x)
    3453 
    3454         p.set_objective(sum([b[(u,v)] for (u,v) in self.edges(labels=None)]))
    3455 
    3456         if value_only:
    3457             return p.solve(objective_only=True)
    3458         else:
    3459             p.solve()
    3460 
    3461             b_sol=p.get_values(b)
    3462 
    3463             from sage.sets.set import Set
    3464             return Set([(u,v) for (u,v) in self.edges(labels=None) if b_sol[(u,v)]==1])
    3465 
    3466     def feedback_vertex_set(self,value_only=False):
    3467         r"""
    3468         Computes the minimum feedback vertex set of a digraph.
    3469 
    3470         The minimum feedback vertex set of a digraph is a set of vertices
    3471         that intersect all the circuits of the digraph.
    3472         Equivalently, a minimum feedback vertex set of a DiGraph is a set
    3473         `S` of vertices such that the digraph `G-S` is acyclic. For more
    3474         information, see the
    3475         `Wikipedia article on feedback vertex sets
    3476         <http://en.wikipedia.org/wiki/Feedback_vertex_set>`_.
    3477 
    3478         INPUT :
    3479 
    3480         - ``value_only`` (boolean) --
    3481             - When set to ``True``, only the minimum
    3482               cardinal of a minimum vertex set is
    3483               returned.
    3484 
    3485             - When set to ``False``, the ``Set`` of vertices
    3486               of a minimal feedback vertex set is returned.
    3487 
    3488         This problem is solved using Linear Programming, which certainly
    3489         is not the best way and will have to be replaced by a better algorithm.
    3490         The program solved is the following :
    3491 
    3492         .. MATH:
    3493             \mbox{Minimize : }&\sum_{v\in G} b_v\\
    3494             \mbox{Such that : }&\\
    3495             &\forall v\in G, \sum_{i\in [0,\dots,n-1]}x_{v,i}=1\\
    3496             &\forall i\in [0,\dots,n-1], \sum_{v\in G}x_{v,i}=1\\
    3497             &\forall v\in G,\sum_{i\in [0,\dots,n-1]} ix_{v,i}=d_v\\
    3498             &\forall (u,v)\in G, d_u-d_v+nb_u+nb_v\geq 0\\
    3499                        
    3500         A brief explanation :
    3501 
    3502         An acyclic digraph can be seen as a poset, and every poset has
    3503         a linear extension. This means that in any acyclic digraph
    3504         the vertices can be ordered with a total order `<` in such a way
    3505         that if `(u,v)\in G`, then `u<v`.
    3506         Thus, this linear program is built in order to assign to each vertex
    3507         `v` an unique number `d_v\in [0,\dots,n-1]` such that if there exists
    3508         an edge `(u,v)\in G` such that `d_v<d_u`, then either `u` is removed
    3509         (`\Rightarrow b_u=1`) or `v` is removed (`\Rightarrow b_v=1`).
    3510         The number of vertices removed is then minimized, which is
    3511         the objective.
    3512 
    3513         EXAMPLE:
    3514 
    3515         In a digraph built from a graph, any edge is replaced by arcs going
    3516         in the two opposite directions, thus creating a cycle of length two.
    3517         Hence, to remove all the cycles from the graph, each edge must see
    3518         one of its neighbors removed : a feedback vertex set is in this
    3519         situation a vertex cover ::
    3520 
    3521             sage: cycle=graphs.CycleGraph(5)
    3522             sage: dcycle=DiGraph(cycle)
    3523             sage: cycle.vertex_cover(value_only=True)         # optional - requires GLPK or CBC
    3524             3
    3525             sage: feedback = dcycle.feedback_vertex_set()     # optional - requires GLPK or CBC
    3526             sage: feedback.cardinality()                      # optional - requires GLPK or CBC
    3527             3
    3528             sage: (u,v,l) = cycle.edge_iterator().next()
    3529             sage: u in feedback or v in feedback              # optional - requires GLPK or CBC
    3530             True
    3531            
    3532         For a circuit, the minimum feedback arc set is clearly `1` ::
    3533 
    3534             sage: circuit = digraphs.Circuit(5)
    3535             sage: circuit.feedback_vertex_set(value_only=True) == 1    # optional - requires GLPK or CBC
    3536             True
    3537         """
    3538        
    3539         from sage.numerical.mip import MixedIntegerLinearProgram
    3540        
    3541         p=MixedIntegerLinearProgram(maximization=False)
    3542        
    3543         b=p.new_variable()
    3544         x=p.new_variable(dim=2)
    3545         d=p.new_variable()
    3546         n=self.order()
    3547         N=range(n)
    3548 
    3549         # First and second constraints
    3550         for v in self:
    3551             p.add_constraint(sum([x[v][i] for i in N]),min=1,max=1)
    3552 
    3553         for i in N:
    3554             p.add_constraint(sum([x[v][i] for v in self]),min=1,max=1)
    3555        
    3556         # Definition of d_v
    3557         for v in self:
    3558             p.add_constraint(sum([i*x[v][i] for i in N])-d[v],max=0,min=0)
    3559 
    3560         # The removed vertices cover all the back arcs ( third condition )
    3561         for (u,v) in self.edges(labels=None):
    3562             p.add_constraint(d[u]-d[v]+n*(b[u]+b[v]),min=0)
    3563 
    3564         p.set_binary(b)
    3565         p.set_binary(x)
    3566 
    3567         p.set_objective(sum([b[v] for v in self]))
    3568 
    3569         if value_only:
    3570             return p.solve(objective_only=True)
    3571         else:
    3572             p.solve()
    3573             b_sol=p.get_values(b)
    3574 
    3575             from sage.sets.set import Set
    3576             return Set([v for v in self if b_sol[v]==1])
    3577 
    3578 
    35793351    def max_cut(self,value_only=True,use_edge_labels=True, vertices=False):
    35803352        r"""
    35813353        Returns a maximum edge cut of the graph. For more information, see the