Group Abstract Group Abstract

Message Boards Message Boards

0
|
11.1K Views
|
16 Replies
|
5 Total Likes
View groups...
Share
Share this post:

In Mathematica 9, how do I check if all list members are True?

Posted 4 years ago
POSTED BY: Michael Gmirkin
16 Replies

It performs exactly as I would expect. In some cases the test you wish to run is very fast, so that it is faster to run that test on all the inputs and check the results after than it is to do the incremental checks needed for the short circuit.

As mentioned above, OddQ is written in low-level kernel code and is optimised when mapped:

In[13]:= list = RandomInteger[100, 10^6];

In[14]:= First@RepeatedTiming[OddQ /@ list]

Out[14]= 0.21808

In[15]:= oddQ[x_] := OddQ[x];

In[16]:= First@RepeatedTiming[oddQ /@ list]

Out[16]= 0.524905

But if running your predicate function is not as fast as OddQ then you do want to use avoid applying it to all elements of the list if possible.

Lastly, OddQ is listable, so you can be even faster by avoiding map:

In[17]:= First@RepeatedTiming[OddQ@list]

Out[17]= 0.0154204
POSTED BY: Jason Biggs

I think the point is, if you already have a list of boolean values, list = {True, False, False, ....} then And @@ list is absolutely the right thing to do. AllTrue or any of the v9 implementations of it listed above would be overkill.

POSTED BY: Jason Biggs
Posted 4 years ago

Jason,

Agreed.

Do you have any idea why the allTrue implementation you provided, that attempts to short-circuit Map, does not perform as expected?

POSTED BY: Rohit Namjoshi
Posted 4 years ago

This might be relevant. From the documentation reference of And:

enter image description here

As I see it, the OP had a list consisting of only True or False and wanted to see if all elements were True. The additional condition of OddQ somehow crept in later in the discussion.

POSTED BY: Hans Milton
POSTED BY: Jason Biggs
Posted 4 years ago

Careful. For conjunctions, Mathematica performs a short circuit evaluation, i.e. it stops anding up Booleans as soon as it encounters false. Btw this is standard procedure for any modern programming languages.

POSTED BY: Bernd Günther
Posted 4 years ago

I think Jason's point is that AllTrue short-circuits the Map. However, the timings suggest that it is slower. What am I missing?

test1 = {1}~Join~ConstantArray[2, 10^6];
test2 = ConstantArray[2, 10^6]~Join~{1};

allTrue[list_, test_] := test /@ list // MatchQ[{True ..}]
allTrueJason[list_, test_] := Catch[Map[Function[If[! test@#, Throw[False]]], list];
  True]

allTrue[test1, OddQ] // AbsoluteTiming
(* {0.204723, False} *)

allTrueJason[test1, OddQ] // AbsoluteTiming
(* {0.461795, False} *)

Similar timings for test2.

POSTED BY: Rohit Namjoshi

Map (/@) will probably get compiled for large lists, so that could explain the difference…

POSTED BY: Sander Huisman
Posted 4 years ago

Jason is right; it doesn't short circuit. You see the difference in

And @@ ((Print[#]; EvenQ[#]) & /@ {2, 4, 6, 1, 3, 5})

versus

AllTrue[{2, 4, 6, 1, 3, 5}, (Print[#]; EvenQ[#]) &]

This shatters illusions.

POSTED BY: Bernd Günther

Obviously, this will not short circuit, it will first map everything and then apply the And operator.

You would have to do this:

And[Print[2]; EvenQ[2], Print[4]; EvenQ[4], Print[6]; EvenQ[6], 
 Print[1]; EvenQ[1], Print[3]; EvenQ[3], Print[5]; EvenQ[5]]

2
4
6
1
False
POSTED BY: Sander Huisman
Posted 4 years ago

What about using And@@? Something like And @@ EvenQ /@ {2,4,6} ?

POSTED BY: Bernd Günther
Posted 4 years ago

Hi Michael,

You can use pattern matching

listTF = {True, False, False, True};
listT = {True, True, True, True};

listTF // MatchQ[{True ..}]
(* False *)

listT // MatchQ[{True ..}]
(* True *)

Combine that with mapping a predicate function

allTrue[list_, test_] := test /@ list // MatchQ[{True ..}]

allTrue[{2, 3, 4, 6, 8}, EvenQ]
(* False *)

allTrue[{2, 4, 6, 8}, EvenQ]
(* True *)
POSTED BY: Rohit Namjoshi

Interesting, if a bit more ... complicated.

[My kludge-y solution got it done in basically 2 lines with MemberQ[list, False] and then simply doing a check whether the output is "[Output]==False" to flip the output bit from False to True. ;) ]

POSTED BY: Michael Gmirkin

This is clearly the most Wolframian way of doing it, perhaps faster is And @@, but harder to read perhaps…

POSTED BY: Sander Huisman

Well, here's my first pass at a ridiculously stupid workaround:

SomePrimeCandidate = 191;
PascalStart = 1;
PascalEnd = Ceiling[(SomePrimeCandidate - 1)/2];
PascalRange = Range[PascalStart, PascalEnd];
PascalRow = Factorial[SomePrimeCandidate]/((Factorial[(SomePrimeCandidate-PascalRange)])*(Factorial[PascalRange]));
PascalDivisibility = Divisible[PascalRow, SomePrimeCandidate];
IsComposite = MemberQ[PascalDivisibility, False];
IsPrime = (IsComposite == False)
PascalDivisibilityArray = Transpose[{PascalRow, PascalDivisibility}];
PascalDivisibilityGrid = Grid[PascalDivisibilityArray]
POSTED BY: Michael Gmirkin
POSTED BY: Michael Gmirkin
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard