6

Suppose that I have a list of lists, for example:

my_list = {{1,2,9},{2,3,7},{5,6,9},{8,10,11}}

I want to manipulate the list such that it contains only all the mutually disjoint elements of the list, as follows:

my_list = {{1,2,9},{8,10,11}}

or

my_list = {{2,3,7},{5,6,9},{8,10,11}}

Preferably, the instances with more elements, like the second one.

Thanks in advance for any help and guide.

Anjan Kumar
  • 4,979
  • 1
  • 15
  • 28
Marilla
  • 165
  • 7

5 Answers5

5

I would turn your question into a graph problem. Consider your lists as vertices, and an edge between two vertices exists if there is a common element. Then, FindIndependentVertexSet should find the set with the maximal number of vertices with no common edge, i.e., what you're interested in. Here is the code:

maximalDisjointSubset[list_]:=Module[{vertices = Range@Length@list,edges},
    edges=Cases[
        Subsets[vertices,2],
        {i_,j_} /; Intersection @@ list[[{i,j}]] != {} :> i<->j
    ];
    list[[First @ FindIndependentVertexSet @ Graph[vertices,edges]]]
]

For your example:

maximalDisjointSubset[{{1,2,9},{2,3,7},{5,6,9},{8,10,11}}]

{{2, 3, 7}, {5, 6, 9}, {8, 10, 11}}

Note that finding a maximal independent vertex set is an NP-hard optimization problem.

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
  • Many thanks Carl for your answer; yes, that's exactly what I want as well. Actually, I was thinking to use the "FindIndependentVertexSet", but by considering every individual number as a vertex and not every list. Considering the lists solves the problem. That's great. – Marilla Feb 23 '17 at 10:12
4

I think this is what you're after:

fn=Module[{ms = Subsets[#, {2, Length@#}]}, 
  Take[Reverse[Pick[ms, And @@ DisjointQ @@@ Subsets[#, {2}] & /@ ms]],UpTo[1]]] &;

mylist = {{1, 2, 9}, {2, 3, 7}, {5, 6, 9}, {8, 10, 11}}
fn@mylist

{{{2, 3, 7}, {5, 6, 9}, {8, 10, 11}}}

BTW, don't use underscores willy-nilly (note I used mylist vs my_list), or you'll be in for some nasty surprises.

If you want all the instances, in order of length (as opposed to one of the longest cases as in OP), use:

fn2 = Module[{ms = Subsets[#, {2, Length@#}]}, 
             Pick[ms, And @@ DisjointQ @@@ Subsets[#, {2}] & /@ ms]] &;
ciao
  • 25,774
  • 2
  • 58
  • 139
1

Perhaps for small lists:

my = {{1, 2, 9}, {2, 3, 7}, {5, 6, 9}, {8, 10, 11}};
g = RelationGraph[Intersection[#1, #2] == {} &, my];
FindClique[g, Infinity, All]

yields:

{{{2, 3, 7}, {5, 6, 9}, {8, 10, 11}}, {{1, 2, 9}, {8, 10, 11}}}
ubpdqn
  • 60,617
  • 3
  • 59
  • 148
0

It is unclear what you're asking, but perhaps this is your solution:

list1 = {{1, 2, 9}, {2, 3, 7}, {5, 6, 9}, {8, 10, 11}};
list2 = {{1, 2, 9}, {8, 10, 11}};
Complement[list1, list2]
David G. Stork
  • 41,180
  • 3
  • 34
  • 96
  • Thanks David for your reply. Actually, the list2 would be the list to find; So, I don't have it from the beginning. – Marilla Feb 23 '17 at 10:08
0
list = {{1, 2, 9}, {2, 3, 7}, {5, 6, 9}, {8, 10, 11}};

DeleteDuplicates[list, IntersectingQ]

{{1, 2, 9}, {8, 10, 11}}


As your Preferably

First[FindIndependentVertexSet[RelationGraph[IntersectingQ, list]]]

{{2,3,7},{5,6,9},{8,10,11}}

yode
  • 26,686
  • 4
  • 62
  • 167