Ticket #8798: trac_8798.patch

File trac_8798.patch, 9.4 KB (added by ncohen, 10 years ago)
  • sage/graphs/generic_graph.py

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