In [1]:
# ----------------------------------------------------------------------
# Numenta Platform for Intelligent Computing (NuPIC)
# Copyright (C) 2016, Numenta, Inc.  Unless you have an agreement
# with Numenta, Inc., for a separate license for this software code, the
# following terms and conditions apply:
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero Public License for more details.
#
# You should have received a copy of the GNU Affero Public License
# along with this program.  If not, see http://www.gnu.org/licenses.
#
# http://numenta.org/licenses/
# ----------------------------------------------------------------------


from sympy import *
init_printing()
from IPython.display import display

%matplotlib inline

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['pdf.fonttype'] = 42

In [2]:
# number of columns
n = Symbol("n", positive=True)

# number of cells per column
m = Symbol("m", positive=True)

# number of active bits
w = Symbol("w", positive=True)

# match thresh
b = Symbol("b", positive=True)

In [12]:
nColL4Val = 150
wVal = 10
bVal = 7
mVal = 16

nCw = factorial(n) / (factorial(w) * factorial(n - w))
overlapSet = binomial(w, b) * binomial(n - w, w - b)

numPts = nCw.subs(n, nColL4Val).subs(w, wVal)
display("raw feature capacity", numPts.evalf()) 

sizeOverlapSet = 0
for bVal in range(7, 10):
    sizeOverlapSet += overlapSet.subs(w, wVal).subs(n, nColL4Val).subs(b, bVal)

display("inexact matches for each template: ", sizeOverlapSet.evalf())

numFeatures = numPts / sizeOverlapSet

display("feature capacity after adjusting inexact matches: ", numFeatures.evalf())


'raw feature capacity'
$$1.16955429822231 \cdot 10^{15}$$
'inexact matches for each template: '
$$54148850.0$$
'feature capacity after adjusting inexact matches: '
$$21598876.0282501$$

In [14]:
mtow = pow(m, w)
numPts = mtow.subs(m, mVal).subs(w, wVal)
sizeInexactMatch = 0
for bVal in range(7, 10):
    sizeInexactMatch += nCw.subs(n, wVal).subs(w, bVal) * pow(mVal, wVal-bVal)

numLocations = numPts / sizeInexactMatch
display("raw location capacity: ", numPts.evalf()) 
display("location capacity after adjusting inexact matches: ", numLocations.evalf())


'raw location capacity: '
$$1099511627776.0$$
'location capacity after adjusting inexact matches: '
$$2185039.00591415$$

Verify capacity calculation with simulation


In [16]:
def generateL4SDR(n=150, m=16, w=10):
  colOrder = np.random.permutation(np.arange(n))
  activeCols = colOrder[:w]
  activeCells = np.random.randint(low=0, high=m, size=(w, ))

  activeBits = activeCols * m + activeCells
  return set(activeBits), set(activeCols)

numRpts = 100000
overlap = []
for rpt in range(numRpts):
    sdr1, sdr1cols = generateL4SDR()
    sdr2, sdr2cols = generateL4SDR()
    overlap.append(len(sdr1.intersection(sdr2)))
overlap = np.array(overlap)
display("mean overlap", np.mean(overlap)) 
display("max overlap", np.max(overlap))


'mean overlap'
$$0.04265$$
'max overlap'
3

In [ ]: