# Sparse Distributed Representations

A sparse distributed representation (SDR) is a set of boolean values which represent the state of a group of neurons or their associated processes. There is a new class to represent an SDR. The SDR class has methods to hold, measure, and manipulate them. Many of the algorithms pass and return SDRs. For complete documentation see `help(nupic.bindings.sdr.SDR)`. Here is a shortened except from the documentation:

SDR's have three commonly used data formats which are:

• dense A numpy array of boolean values, representing all of the bits in the SDR. This format allows random-access queries of the SDRs values.
• sparse A numpy array containing the indices of only the true values in the SDR. These are indices into the flattened SDR. This format allows for quickly accessing all of the true bits in the SDR.
• coordinates List of numpy arrays, containing the indices of only the true values in the SDR. This is a list of lists: the outer list contains an entry for each dimension in the SDR. The inner lists contain the coordinates of each true bit. The inner lists run in parallel. This format is useful because it contains the location of each true bit inside of the SDR's dimensional space.

The SDR class has three magic properties, one for each of these data formats. These properties are the primary way of accessing the SDR's data. When these properties are read from, the data is automatically converted to the requested format and is cached so getting a value in one format many times incurs no extra performance cost. Assigning to the SDR via any one of these properties clears the cached values and causes them to be recomputed as needed.

### Example usage:

```from nupic.bindings.sdr import SDR
import numpy   # SDR uses all numpy arrays, but will accept lists instead.

# Make an SDR with 9 values, arranged in a (3 x 3) grid.
X = SDR(dimensions = (3, 3))

# These three statements are equivalent.
X.dense  = [[0, 1, 0],
[0, 1, 0],
[0, 0, 1]]
X.sparse = [ 1, 4, 8 ]
X.coordinates = [[0, 1, 2], [1, 1, 2]]

# Access data in any format, SDR will automatically convert data formats,
# even if it was not the format used by the most recent assignment to the
# SDR.
X.dense ==  [[ 0, 1, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 1 ]]
X.sparse == [ 1, 4, 8 ]
X.coordinates == [[ 0, 1, 2 ], [1, 1, 2 ]]

# Data format conversions are cached, and when an SDR value changes the
# cache is cleared.
X.sparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache.
X.dense     # This line will convert formats
X.dense     # This line will resuse the result of the previous line```

Here are some other interesting SDR methods:

```sdr.getSparsity()
sdr.getOverlap( sdr )        # Returns number of bits which overlap
sdr.randomize( sparsity )
sdr.addNoise( percentNoise ) # Moves a fraction of the active bits to new locations.
sdr.concatenate( sdr_A, sdr_B )
sdr.intersection( sdr_A, sdr_B )
sdr.reshape( new_dimensions )
sdr.flatten()```

## Measurement Tools

The SDR has tools to measure it. The class `sdr.Metrics` combines all of these measurement tools into one convenient class. It can be setup to automatically track an SDR via callbacks.

These tools use exponential moving averages to incorporate data. These exponents are controlled by a parameter `period` which is related to the time-scale of the data, how fast it moves. While there are fewer data points than the period, a regular average is used instead of an exponential moving average.

### Example Usage of `sdr.Metrics`.

```from nupic.bindings.sdr import SDR, Metrics
A = SDR( 2000 )
M = Metrics( A, period = 1000 )  # This will automatically track SDR A.
for i in range( 345 ):
A.randomize( sparsity = .10 )
print( M )
"""
SDR( 2000 )
Sparsity Min/Mean/Std/Max 0.1 / 0.0999997 / 1.33063e-06 / 0.1
Activation Frequency Min/Mean/Std/Max 0.0492753 / 0.1 / 0.0163682 / 0.156522
Entropy 0.995378
Overlap Min/Mean/Std/Max 0.05 / 0.0986482 / 0.0210721 / 0.165
"""```

``````help( nupic.bindings.sdr.Sparsity )