One can do this in a procedural manner. A direct version did not give much (it was about the same speed as the original code). Instead I'll show a method that works only with the list of first (5-tuple) elements. The benefit is one can use Compile and that gives a quite measurable speed gain.
I use a dummy function for the checkCondC. If the max value of the difference of two 5-tuples is less than some threshold, we say the condition fails and do not add the second arg to the list under construction.
This version constructs the list of keepers, and for every new 5-tuple in the original list, tests against keepers before determining whether to add the new on or move on. It is an O(n^2) algorithm but does not have excessive costs from creating/destroying intermediate lists. We simply create an output of the same dimensions as the input, and replace dummy elements by keepers while maintaining a caount of how many keepers we have at any step.
checkCondC =
Compile[{{ll1, _Real, 1}, {ll2, _Real, 1}}, Max[Abs[ll1 - ll2]]];
maxNonintersectingC = Compile[{{ll, _Real, 2}, {eps, _Real}}, Module[
{res = ConstantArray[0., Dimensions[ll]], next, max = 1, good},
res[[1]] = ll[[1]];
Do[
next = ll[[j]];
good =
Catch[Do[
If[checkCondC[res[[k]], next] < eps,
Throw[False]]
, {k, max}];
True];
If[good, max++; res[[max]] = next];
, {j, Length[ll]}];
Take[res, max]
], CompilationOptions -> {"InlineCompiledFunctions" -> True},
CompilationTarget -> "C"];
Now we take a large example.
m = 8000;
inlist = Map[{{1, 1, 1/3, 1, 1}*Most[#], 1/120*Last[#]} &,
RandomReal[{80, 120}, {m, 6}]];
Check that these look a bit like the elements in the original post.
In[282]:= inlist[[1 ;; 3]]
(* Out[282]= {{{114.210179264, 94.9872032272, 30.742668711,
83.7376433634, 119.920328664},
0.928968044627}, {{104.641626332, 92.2701423248, 29.4891773984,
114.993318079, 80.4115524547},
0.960390210004}, {{90.6277601511, 98.6345852935, 30.8461476176,
85.7636679809, 111.535125216}, 0.868401515828}} *)
Timing:
Timing[
mx = Reverse[maxNonintersectingC[inlist[[All, 1]], eps]];]
Length[mx]
(* Out[283]= {0.096, Null}
Out[284]= 512 *)
If we do not compile to C it is still fairly fast, at around 0.27 seconds. By contrast, my pedestrian non-compiled version took around 6.3 seconds.
It is not too difficult to add support for retaining those second elements in the lists. One way would be to feed them in as a separate vark 1 list of reals, Append the jth such element to the jth list when that list is a keeper, and appropriately restructuring after the compiled part is finished.
checkCondyou will use. – rhermans Aug 13 '18 at 12:28checkCond? – m_goldberg Aug 14 '18 at 23:38restlist is packable? Is it sorted in any way? How many elements does it have? Does order, in which elements in finalkeeplist end-up, matter? IscheckCondcompilable? Is it fast compared to other operations in iteration?checkCond[First@keep1[[1]], #[[1]]] < threshold &code seems to give a relation onrest, is this relation transitive? All above details can greatly affect performance. – jkuczm Aug 16 '18 at 09:16keep? – yosimitsu kodanuri Aug 16 '18 at 10:38DeleteDuplicates[rest, checkCond[First@#1, First@#2] >= threshold &], is that the case? – jkuczm Aug 16 '18 at 13:53checkCond. If you have one fixedcheckCond, could you add its definition to your question? If you need your code working for various differentcheckCondfunctions then try to add definition of a representative example. I think the most important thing is whethercheckCond[First@#1, First@#2] < threshold &gives a transitive relation, if so, we might go from $\mathcal{O}(n^2)$ to $\mathcal{O}(n\log n)$. If not, we might still be able to use some tricks, like binning, to get average complexity down, even if worst case will remain unchanged. – jkuczm Aug 16 '18 at 13:55Rectangle? how to do you calculate/compare their areas? – user42582 Aug 16 '18 at 15:46