Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any efficient easy way to compare two lists with the same length with Mathematica?

Given two lists A={a1,a2,a3,...an} and B={b1,b2,b3,...bn}, I would say A>=B if and only if all ai>=bi.

There is a built-in logical comparison of two lists, A==B, but no A>B. Do we need to compare each element like this

And@@Table[A[[i]]>=B[[i]],{i,n}]

Any better tricks to do this?

EDIT: Great thanks for all of you.

Here's a further question:

How to find the Maximum list (if exist) among N lists?

Any efficient easy way to find the maximum list among N lists with the same length using Mathematica?

like image 553
Osiris Xu Avatar asked Jan 16 '12 19:01

Osiris Xu


2 Answers

Method 1: I prefer this method.

NonNegative[Min[a - b]]

Method 2: This is just for fun. As Leonid noted, it is given a bit of an unfair advantage for the data I used. If one makes pairwise comparisons, and return False and Break when appropriate, then a loop may be more efficient (although I generally shun loops in mma):

result = True;
n = 1; While[n < 1001, If[a[[n]] < b[[n]], result = False; Break[]]; n++]; result

Some timing comparisons on lists of 10^6 numbers:

a = Table[RandomInteger[100], {10^6}];
b = Table[RandomInteger[100], {10^6}];

(* OP's method *)
And @@ Table[a[[i]] >= b[[i]], {i, 10^6}] // Timing

(* acl's uncompiled method *)
And @@ Thread[a >= b] // Timing

(* Leonid's method *)
lessEqual[a, b] // Timing

(* David's method #1 *)
NonNegative[Min[a - b]] // Timing

timings 2


Edit: I removed the timings for my Method #2, as they can be misleading. And Method #1 is more suitable as a general approach.

like image 118
DavidC Avatar answered Sep 18 '22 22:09

DavidC


For instance,

And @@ Thread[A >= B]

should do the job.

EDIT: On the other hand, this

cmp = Compile[
  {
   {a, _Integer, 1},
   {b, _Integer, 1}
   },
  Module[
   {flag = True},
   Do[
    If[Not[a[[p]] >= b[[p]]], flag = False; Break[]],
    {p, 1, Length@a}];
   flag],
  CompilationTarget \[Rule] "C"
  ]

is 20 times faster. 20 times uglier, too, though.

EDIT 2: Since David does not have a C compiler available, here are all the timing results, with two differences. Firstly, his second method has been fixed to compare all elements. Secondly, I compare a to itself, which is the worst case (otherwise, my second method above will only have to compare elements up to the first to violate the condition).

(*OP's method*)
And @@ Table[a[[i]] >= b[[i]], {i, 10^6}] // Timing

(*acl's uncompiled method*)
And @@ Thread[a >= b] // Timing

(*Leonid's method*)
lessEqual[a, b] // Timing

(*David's method #1*)
NonNegative[Min[a - b]] // Timing

(*David's method #2*)
Timing[result = True;
 n = 1; While[n < Length[a], 
  If[a[[n]] < b[[n]], result = False; Break[]];
  n++]; result]

(*acl's compiled method*)
cmp[a, a] // Timing

enter image description here

So the compiled method is much faster (note that David's second method and the compiled method here are the same algorithm, and the only difference is overhead).

All these are on battery power so there may be some random fluctuations, but I think they are representative.

EDIT 3: If, as ruebenko suggested in a comment, I replace Part with Compile`GetElement, like this

cmp2 = Compile[{{a, _Integer, 1}, {b, _Integer, 1}}, 
  Module[{flag = True}, 
   Do[If[Not[Compile`GetElement[a, p] >= Compile`GetElement[b, p]], 
     flag = False; Break[]], {p, 1, Length@a}];
   flag], CompilationTarget -> "C"]

then cmp2 is a twice as fast as cmp.

like image 32
acl Avatar answered Sep 20 '22 22:09

acl