Recently I found myself reading about “subitizing”, which is the process of instinctively counting small sets of items in a fraction of second. For example, try quickly counting a few of these:

The Wikipedia article indicates that you can nearly always correctly count four or fewer items in a small fraction of a second. Above four, you start to make mistakes. I wanted to test this claim in Mathematica (using myself as the test subject). I decided to create a simple game in which small groups of items are momentarily displayed on the screen, after which players estimate how many they saw.



If you have the free Computable Document Format (CDF) browser plugin (or Mathematica 8) installed, then you can play the game right here in your web browser (if you don’t have the plugin, you’ll just see a placeholder image):

The game keeps track of your successes and failures and plots them as a function of how many items were present and the time you were given to count them.

Creating a game like this in Mathematica is surprisingly easy. In this post I’ll show how you can make this one, step by step. Then I’ll show the results I obtained by playing it a few hundred times.

Generating “Subitizing” Diagrams

The first thing you need is a way to randomly generate items for the player to count. Here’s a function that generates a random point lying within a radius s of the origin:

(The √ and s^2 ensure you get points uniformly distributed in a circular region.)

Now suppose you want to draw each item as a disk at position p with a small radius r. The corresponding Mathematica graphics primitive is Disk [p, r]. Here, then, is a first attempt at a subitizing diagram:

You can immediately see a problem: some of the items are overlapping. Here’s a function that tests whether two Disk objects are overlapping by comparing the distance between them ( EuclideanDistance ) to the sum of their radii:

Since you’ll have a list of several disks, you want a function that will check every pair of disks to see if any of them overlap:

Using AnyOverlapQ you can repeatedly generate random sets of items until you find a non-overlapping set. Here is a function that uses this method to generate n non-overlapping items, each with a random radius a < r < b:

It uses the one-argument form of While to repeatedly generate items until AnyOverlapQ returns False . Using RandomDiskPoint [1 - b] instead of RandomDiskPoint [1] further ensures that the random items never overlap a boundary of radius 1.

Now you can write a function to generate random subitizing diagrams:

The extra argument colors specifies a list of colors to randomly choose from for each item. Riffle is used to combine two lists by alternately taking elements from each:

Here are a couple of examples of using SubitizeDiagram :

Creating the Interactive Game

This will be the interface of the function SubitizeGame :

SubitizeGame[nmax, {a, b}, colors, tmax]

Here nmax is the maximum number of items to be shown in each random diagram and tmax is the maximum time (in seconds) each diagram is to be shown for. (The arguments a, b, and colors specify the minimum size, maximum size, and possible colors of the items, just as above in SubitizingDiagram .)

The flow of the game is as follows: First, show a warning to “get ready”. Second, show a random subitizing diagram for a random (small) length of time. Third, show a panel of buttons to let the player indicate how many items were seen. Finally, record the player’s guess along with the correct answer and the amount of times the items were shown, and then move on to the next round.

One handy building block is a function that “flips” from displaying one expression to another after t seconds:

TimedFlip [{e1, e2}, t] displays as e1 for t seconds, then displays as e2 afterward. (The option UpdateInterval -> 0 causes the expression to update as often as possible, which is useful with Dynamic expressions that depend on the current time.)

Here’s a “get ready” warning:

It is easiest to implement the panel of buttons that players will use to specify their guess inside the SubitizeGame function, so, without further ado, here is the rest of the code for the game:

There are a few things to notice here: The guessbutton function creates a Button that, when clicked, appends data about the player’s guess to a list of results stored in the variable GameResults [nmax, {a, b}, colors, tmax]. (This means you get a different set of recorded results for each distinct set of game parameters nmax, a, b, etc.) Initially the list of results should be empty for every set of game parameters:

The guesspanel function uses Grid and Partition to arrange the buttons in a grid with four columns.

The startnextround function uses a couple of nested TimedFlip objects to create an expression that successively flips between the “Get ready” warning, the diagram, and the panel of buttons. Note that each Button created by guessbutton automatically calls startnextround after it records the guess results.

Finally, note that the only thing actually returned by SubitizeGame is the simple object Dynamic [ display ]. The actual appearance of the game at any given time is totally encapsulated in the value of the display variable. (In this game, display is set to a newly created TimedFlip object after each round.)

Results

I played the game a few hundred times with simple settings in which the items were uniformly sized black disks, the display time was between 0.25 and 0.5 seconds, and there were between 1 and 12 items in each diagram:

SubitizeGame[12, {0.05, 0.05}, {Black}, 0.5]

Here is a visual summary of the results:

( RightWrongScatterPlot uses results from GameResults , and you can see its definition in the downloadable CDF file for this post. It’s also used in the version of the game that appears at the top of this post.)

As you can see from the plot above, I didn’t make any mistakes identifying the number of items when there were four or fewer of them. With five items I made a few mistakes, mainly when I didn’t have much time to look at the diagram. For six or more items, I made at least some mistakes right up to 0.5 seconds.

Here’s my overall accuracy as a function of the number of items:

Unsurprisingly, it degrades pretty steadily as the number of items grows.

An interesting variant on the graph above is to plot overall accuracy as a function of my guess of the number of items:

There is a large edge effect at 12 items. I think this arose because I knew that there were always 12 or fewer items, never 13 or 14. That makes it a “safer” guess than the others.

Finally, here’s a plot of how much larger my guess was, on average, than the number of items:

As you can see, I tended to overestimate smaller numbers of items and underestimate larger numbers of items. I don’t know why.

At this point I should emphasize that the results I’m showing in this blog post were certainly not produced under controlled lab conditions! Rather, they were produced by me while I was writing the game shown above. (By reading this blog post, you’ve probably also spoiled any chance of doing a properly controlled test on yourself—you’d better recruit some oblivious volunteers.)

There are lots of other things you could investigate using this simple game or variations of it: Are colorful dots easier or harder to count than black ones? Does the size of the items matter (including whether they are uniformly sized)? Is it easier to count larger groups of items when they happen to be clustered together into identifiable smaller groups, compared with when they are fairly evenly distributed over the diagram? What about counting regularly arranged items instead of randomly placed items?

Download the CDF file for this post and give it a try!

Click here to download this post as a Computable Document Format (CDF) file. The downloadable CDF file also contains some extra material and source code not shown in this web version. To open the CDF file you need Mathematica 8 or the free Wolfram CDF Player.