Ticket #6764: trac_6764.patch

File trac_6764.patch, 5.3 KB (added by ncohen, 11 years ago)
  • sage/graphs/graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1250442254 25200
    # Node ID 1b2521fe4ca4f38b7ff644c4558b73af7827836c
    # Parent  4e9352907c3563eca5880b200169cfd08f7f0aa8
    Function Graph.independent_set_of_representatives
    
    diff -r 4e9352907c35 -r 1b2521fe4ca4 sage/graphs/graph.py
    a b  
    1057810578        else:
    1057910579            raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.")
    1058010580   
     10581    def independent_set_of_representatives(self,family):
     10582        r"""
     10583        Returns an independent set of representatives.
     10584
     10585        Given a graph `G` and and a family `F=\{F_i:i\in [1,...,k]\}` of subsets
     10586        of ``g.vertices()``, an ISR ( Independent Set of Reprersentatives ) is an
     10587        assignation of a vertex `v_i\in F_i` to each set `F_i` such that
     10588        `v_i != v_j` if `i<j` ( they are represdentatives ) and the set
     10589        `\cup_{i}v_i` is an independent set in `G`.
     10590       
     10591        It generalizes, for example, graph coloring and graph list coloring.
     10592       
     10593        ( See [AhaBerZiv07]_ for more informations )
     10594
     10595        INPUT :
     10596
     10597        - ``family`` -- A list of lists defining the family `F`
     10598          ( actually, a Family of subsets of ``G.vertices()`` )
     10599
     10600        OUTPUT :
     10601       
     10602        - A list whose `i^{\mbox{th}}` element is the representativeof the `i^{\mbox{th}}`
     10603          element of the ``family`` list. If there is no ISR, ``None`` is returned
     10604
     10605        EXAMPLE :
     10606
     10607        For a bipartite graph missing one edge, the solution is as expected::
     10608       
     10609           sage: g = graphs.CompleteBipartiteGraph(3,3)
     10610           sage: g.delete_edge(1,4)
     10611           sage: g.independent_set_of_representatives([[0,1,2],[3,4,5]]) # optional - requires GLPK or CBC
     10612           [1, 4]
     10613
     10614        The Petersen Graph is 3-colorable, which can be expressed as an
     10615        independent set of representatives problem : take 3 disjoint copies
     10616        of the Petersen Graph, each one representing one color. Then take
     10617        as a partition of the set of vertices the family defined by the three
     10618        copies of each vertex. The ISR of such a family
     10619        defines a 3-coloring ::
     10620
     10621            sage: g = 3 * graphs.PetersenGraph()
     10622            sage: n = g.order()/3
     10623            sage: f = [[i,i+n,i+2*n] for i in xrange(n)]
     10624            sage: isr = g.independent_set_of_representatives(f)   # optional - requires GLPK or CBC
     10625            sage: c = [floor(i/n) for i in isr]                   # optional - requires GLPK or CBC
     10626            sage: color_classes = [[],[],[]]                      # optional - requires GLPK or CBC
     10627            sage: for v,i in enumerate(c):                        # optional - requires GLPK or CBC
     10628            ...     color_classes[i].append(v)                    # optional - requires GLPK or CBC
     10629            sage: for classs in color_classes:                    # optional - requires GLPK or CBC
     10630            ...     g.subgraph(classs).size() == 0                # optional - requires GLPK or CBC
     10631            True
     10632            True
     10633            True
     10634
     10635        REFERENCE:
     10636
     10637        .. [AhaBerZiv07] R. Aharoni and E. Berger and R. Ziv
     10638          Independent systems of representatives in weighted graphs
     10639          Combinatorica vol 27, num 3, p253--267
     10640          2007
     10641
     10642        """
     10643
     10644        from sage.numerical.mip import MixedIntegerLinearProgram
     10645        p=MixedIntegerLinearProgram()
     10646       
     10647        # Boolean variable indicating whether the vertex
     10648        # is the representative of some set
     10649        vertex_taken=p.new_variable()
     10650
     10651        # Boolean variable in two dimension whose first
     10652        # element is a vertex and whose second element
     10653        # is one of the sets given as arguments.
     10654        # When true, indicated that the vertex is the representent
     10655        # of the corresponding set
     10656
     10657        classss=p.new_variable(dim=2)
     10658
     10659        # Associates to the vertices the classes
     10660        # to which they belong
     10661       
     10662        lists=dict([(v,[]) for v in self.vertex_iterator()])
     10663        for i,f in enumerate(family):
     10664            [lists[v].append(i) for v in f]
     10665           
     10666            # a classss has exactly one representant
     10667            p.add_constraint(sum([classss[v][i] for v in f]),max=1,min=1)
     10668
     10669        # A vertex represents at most one classss (vertex_taken is binary), and
     10670        # vertex_taken[v]==1 if v is the representative of some classss
     10671
     10672        [p.add_constraint(sum([classss[v][i] for i in lists[v]])-vertex_taken[v],max=0) for v in self.vertex_iterator()]
     10673
     10674        # Two adjacent vertices can not both be representants of a set
     10675
     10676        for (u,v) in self.edges(labels=None):
     10677            p.add_constraint(vertex_taken[u]+vertex_taken[v],max=1)
     10678
     10679        p.set_objective(None)
     10680
     10681        p.set_binary(vertex_taken)
     10682        p.set_binary(classss)
     10683
     10684        try:
     10685            p.solve()
     10686        except:
     10687            return None
     10688
     10689        classss=p.get_values(classss)
     10690       
     10691        repr=[]
     10692        for i,f in enumerate(family):
     10693            for v in f:
     10694                if classss[v][i]==1:
     10695                    repr.append(v)
     10696                    break
     10697
     10698        return repr
     10699
    1058110700    ### Centrality
    1058210701
    1058310702    def centrality_betweenness(self, normalized=True):