| 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 | |