Skip to content

SDR replaces VectorHelpers #320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e2fa54e
SDR: make sdr_dense_t element UInt, from char
breznak Mar 7, 2019
70cdb1a
SpatialPooler: use SDR for conversion from sparse/dense
breznak Mar 7, 2019
f651b42
SDR: make set*Inplace() public
breznak Mar 7, 2019
858d1f3
SDRProxy fix UInt in dense
breznak Mar 7, 2019
3391f78
Hotgym: use SDR instead of VectorHelpers
breznak Mar 7, 2019
4d793ab
SDR: equals uses getSparse internally
breznak Mar 7, 2019
c2bcb04
fix pybindings for SDR getDense change to vector<UInt>
breznak Mar 7, 2019
6d68136
SDR: update unit test
breznak Mar 7, 2019
bdb7ffd
Hotgym: use compute(SDR) calls
breznak Mar 7, 2019
83d0e9c
SDR: TMP rever to Byte for dense()
breznak Mar 7, 2019
9cfd73d
TM: add compute(SDR, learn) without extra inputs wrapper
breznak Mar 7, 2019
6371aa2
SpatialPooler: use SDR, sparse initMapPotentials
breznak Mar 7, 2019
eb016bc
Revert "SDR: make set*Inplace() public"
breznak Mar 7, 2019
1f430b2
Hotgym fix SDR use
breznak Mar 7, 2019
11a6190
Hotgym code fix
breznak Mar 8, 2019
d4cf24d
SDR: move to namespace nupic::sdr, allow copy-constructor
breznak Mar 8, 2019
dc7fb3c
Revert "SDR: move to namespace nupic::sdr, allow copy-constructor"
breznak Mar 12, 2019
436c600
Merge branch 'master_community' into sdr_cleanup
breznak Mar 12, 2019
96302f9
SP: initMapPotential takes output SDR as its parameter
breznak Mar 12, 2019
e303d36
fix py binding
breznak Mar 12, 2019
a76cd0e
SP: fix test for initMapPotential
breznak Mar 12, 2019
53dd7ac
SDR: again use dense for equals
breznak Mar 12, 2019
4cf4c05
SDR test fixes
breznak Mar 12, 2019
6c2106d
VectorHelpers: remove sparseToBinary, binaryToSparse
breznak Mar 12, 2019
0469db8
BacktrackingTM Region: use SDR instead of VectorHelpers
breznak Mar 12, 2019
b331253
TMRegion tests: use SDR instead of VectorHelpers
breznak Mar 12, 2019
6818ef0
BackTM Test: use SDR instead of VectorHelpers::binaryToSparse
breznak Mar 12, 2019
24350fe
Merge branch 'master' into sdr_cleanup
breznak Mar 12, 2019
182a7af
rm unused variable
breznak Mar 12, 2019
355f73f
SDR fix tests
breznak Mar 12, 2019
7e7bd2a
SDR setSparse add debug check that input vector is not cleared
breznak Mar 13, 2019
9866a36
Revert "SDR setSparse add debug check that input vector is not cleared"
breznak Mar 13, 2019
d12bff8
SDR: fix test
breznak Mar 13, 2019
e30add5
Merge branch 'master_community' into sdr_cleanup
breznak Mar 13, 2019
bed3bdf
improved asserts
breznak Mar 14, 2019
9a9575d
Merge branch 'master_community' into sdr_cleanup
breznak Apr 3, 2019
f2d1a0d
merge fixes
breznak Apr 3, 2019
2b1cf93
Merge branch 'master_community' into sdr_cleanup
breznak Apr 5, 2019
2823d4e
Merge branch 'master_community' into sdr_cleanup
breznak Apr 10, 2019
3ca10e4
Connections: adaptSegment small cleanup
breznak Apr 10, 2019
a9912f3
Merge branch 'master_community' into sdr_cleanup
breznak Apr 11, 2019
ffeb5a6
Merge branch 'master_community' into sdr_cleanup
breznak May 6, 2019
d37daf9
post merge conflicts
breznak May 6, 2019
954013e
remove whitespace changes
breznak May 6, 2019
4a850b9
Merge branch 'master_community' into sdr_cleanup
breznak May 6, 2019
0243edc
Merge branch 'master_community' into sdr_cleanup
breznak May 6, 2019
a324d30
Merge branch 'master_community' into sdr_cleanup
breznak May 13, 2019
a738702
Merge branch 'master_community' into sdr_cleanup
breznak May 13, 2019
7643e34
Merge branch 'master_community' into sdr_cleanup
breznak Jun 13, 2019
cb1ce21
fix merge conflicts
breznak Jun 13, 2019
3de7990
some review feedback
breznak Jun 13, 2019
409c9d4
SDR Unit Tests: fixes & comments
ctrl-z-9000-times Jun 13, 2019
2604dd0
fix sorted inputs for SDR
breznak Jun 13, 2019
a1d9a14
remove obsoleted VectorHelpers file
breznak Jun 13, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ set(utils_files
nupic/utils/Random.cpp
nupic/utils/Random.hpp
nupic/utils/SlidingWindow.hpp
nupic/utils/VectorHelpers.hpp
nupic/utils/SdrMetrics.cpp
nupic/utils/SdrMetrics.hpp
nupic/utils/MurmurHash3.hpp
Expand Down
42 changes: 19 additions & 23 deletions src/nupic/algorithms/SpatialPooler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

#include <nupic/algorithms/SpatialPooler.hpp>
#include <nupic/utils/Topology.hpp>
#include <nupic/utils/VectorHelpers.hpp>

using namespace std;
using namespace nupic;
Expand Down Expand Up @@ -450,18 +449,17 @@ void SpatialPooler::initialize(
inhibitionRadius_ = 0;

connections_.initialize(numColumns_, synPermConnected_);
for (Size i = 0; i < numColumns_; ++i) {
connections_.createSegment( (CellIdx)i );

// Note: initMapPotential_ & initPermanence_ return dense arrays.
vector<UInt> potential = initMapPotential_((UInt)i, wrapAround_);
vector<Real> perm = initPermanence_(potential, initConnectedPct_);
for(UInt presyn = 0; presyn < numInputs_; presyn++) {
if( potential[presyn] )
connections_.createSynapse( (Segment)i, presyn, perm[presyn] );
for (Size column = 0; column < numColumns_; column++) {
connections_.createSegment( static_cast<CellIdx>(column) );

SDR potential({numInputs_});
initMapPotential_(static_cast<UInt>(column), wrapAround_, potential);
const vector<Real> perm = initPermanence_(potential, initConnectedPct_);
for(const auto presyn : potential.getSparse()) {
connections_.createSynapse( static_cast<Segment>(column), presyn, perm[presyn] );
}

connections_.raisePermanencesToThreshold( (Segment)i, stimulusThreshold_ );
connections_.raisePermanencesToThreshold( static_cast<Segment>(column), stimulusThreshold_ );
}

updateInhibitionRadius_();
Expand Down Expand Up @@ -505,6 +503,7 @@ void SpatialPooler::compute(const SDR &input, const bool learn, SDR &active) {

void SpatialPooler::boostOverlaps_(const vector<SynapseIdx> &overlaps, //TODO use Eigen sparse vector here
vector<Real> &boosted) const {
NTA_ASSERT(overlaps.size() == numColumns_);
for (UInt i = 0; i < numColumns_; i++) {
boosted[i] = overlaps[i] * boostFactors_[i];
}
Expand All @@ -530,8 +529,10 @@ UInt SpatialPooler::initMapColumn_(UInt column) const {
}


vector<UInt> SpatialPooler::initMapPotential_(UInt column, bool wrapAround) {
NTA_ASSERT(column < numColumns_);
void SpatialPooler::initMapPotential_(UInt column, bool wrapAround, SDR& potential) {
NTA_CHECK(potential.size == numInputs_);
NTA_CHECK(column < numColumns_);

const UInt centerInput = initMapColumn_(column);

vector<UInt> columnInputs;
Expand All @@ -547,9 +548,9 @@ vector<UInt> SpatialPooler::initMapPotential_(UInt column, bool wrapAround) {
}

const UInt numPotential = (UInt)round(columnInputs.size() * potentialPct_);
const auto selectedInputs = rng_.sample<UInt>(columnInputs, numPotential);
const vector<UInt> potential = VectorHelpers::sparseToBinary<UInt>(selectedInputs, numInputs_);
return potential;
auto selectedInputs = rng_.sample<UInt>(columnInputs, numPotential);
std::sort(selectedInputs.begin(), selectedInputs.end());
potential.setSparse(selectedInputs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not sorted! This is the bug causing the exactOutput test to fail.

Because the potential pool is not sorted, the initial Permanences are randomly generated differently than before.

This also fails in debug mode where there is an ASSERT( is_sorted ) for this type of error.

}


Expand All @@ -563,14 +564,9 @@ Real SpatialPooler::initPermNonConnected_() {
}


vector<Real> SpatialPooler::initPermanence_(const vector<UInt> &potential, //TODO make potential sparse
Real connectedPct) {
const vector<Real> SpatialPooler::initPermanence_(const SDR &potential, const Real connectedPct) {
vector<Real> perm(numInputs_, 0);
for (UInt i = 0; i < numInputs_; i++) {
if (potential[i] < 1) {
continue;
}

for (const auto i : potential.getSparse()) {
if (rng_.getReal64() <= connectedPct) {
perm[i] = initPermConnected_();
} else {
Expand Down
6 changes: 4 additions & 2 deletions src/nupic/algorithms/SpatialPooler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,10 @@ class SpatialPooler : public Serializable

@param wrapAround A boolean value indicating that boundaries should be
ignored.
@param potential A SDR (sized as input), the return values are written to
this field
*/
vector<UInt> initMapPotential_(UInt column, bool wrapAround);
void initMapPotential_(UInt column, bool wrapAround, SDR& potential);

/**
Returns a randomly generated permanence value for a synapses that is
Expand Down Expand Up @@ -880,7 +882,7 @@ class SpatialPooler : public Serializable
@param connectedPct A real value between 0 or 1 specifying the percent of
the input bits that will start off in a connected state.
*/
vector<Real> initPermanence_(const vector<UInt> &potential, Real connectedPct);
const vector<Real> initPermanence_(const SDR &potential, const Real connectedPct);

void clip_(vector<Real> &perm) const;

Expand Down
1 change: 0 additions & 1 deletion src/nupic/regions/TMRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include <nupic/engine/Spec.hpp>
#include <nupic/ntypes/Array.hpp>
#include <nupic/utils/Log.hpp>
#include <nupic/utils/VectorHelpers.hpp>

#define VERSION 1

Expand Down
36 changes: 0 additions & 36 deletions src/nupic/utils/VectorHelpers.hpp

This file was deleted.

1 change: 0 additions & 1 deletion src/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ set(utils_tests
unit/utils/GroupByTest.cpp
unit/utils/MovingAverageTest.cpp
unit/utils/RandomTest.cpp
unit/utils/VectorHelpersTest.cpp
unit/utils/SdrMetricsTest.cpp
)

Expand Down
36 changes: 22 additions & 14 deletions src/test/unit/algorithms/SpatialPoolerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ bool almost_eq(Real a, Real b) {
return (diff > -1e-5 && diff < 1e-5);
}

bool check_vector_eq(UInt arr[], vector<UInt> vec) { //TODO replace with ArrayBase, VectorHelpers or teplates
bool check_vector_eq(UInt arr[], vector<UInt> vec) { //TODO replace with ArrayBase, or teplates
for (UInt i = 0; i < vec.size(); i++) {
if (arr[i] != vec[i]) {
return false;
Expand Down Expand Up @@ -127,6 +127,14 @@ bool check_vector_eq(vector<Real> vec1, vector<Real> vec2) {
return true;
}

bool check_vector_eq(UInt arr[], SDR &sdr) {
const auto vec = sdr.getSparse();
for(UInt i = 0; i < vec.size(); i++) {
if(arr[i] != vec[i]) return false;
}
return true;
}

void check_spatial_eq(const SpatialPooler& sp1, const SpatialPooler& sp2) {
UInt numColumns = sp1.getNumColumns();
UInt numInputs = sp2.getNumInputs();
Expand Down Expand Up @@ -1615,39 +1623,39 @@ TEST(SpatialPoolerTest, testinitMapPotential1D) {
sp.initialize(inputDim, columnDim);
sp.setPotentialRadius(potentialRadius);

vector<UInt> mask;
SDR mask({sp.getNumInputs()});

// Test without wrapAround and potentialPct = 1
sp.setPotentialPct(1.0);

UInt expectedMask1[12] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
mask = sp.initMapPotential_(0, false);
sp.initMapPotential_(0, false, mask);
ASSERT_TRUE(check_vector_eq(expectedMask1, mask));

UInt expectedMask2[12] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0};
mask = sp.initMapPotential_(2, false);
sp.initMapPotential_(2, false, mask);
ASSERT_TRUE(check_vector_eq(expectedMask2, mask));

// Test with wrapAround and potentialPct = 1
sp.setPotentialPct(1.0);

UInt expectedMask3[12] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1};
mask = sp.initMapPotential_(0, true);
sp.initMapPotential_(0, true, mask);
ASSERT_TRUE(check_vector_eq(expectedMask3, mask));

UInt expectedMask4[12] = {1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1};
mask = sp.initMapPotential_(3, true);
sp.initMapPotential_(3, true, mask);
ASSERT_TRUE(check_vector_eq(expectedMask4, mask));

// Test with potentialPct < 1
sp.setPotentialPct(0.5);
UInt supersetMask1[12] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1};
mask = sp.initMapPotential_(0, true);
ASSERT_TRUE(accumulate(mask.begin(), mask.end(), 0.0f) == 3u);
sp.initMapPotential_(0, true, mask);
ASSERT_TRUE(mask.getSum() == 3u);

UInt unionMask1[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (UInt i = 0; i < 12; i++) {
unionMask1[i] = supersetMask1[i] | mask.at(i);
unionMask1[i] = supersetMask1[i] | mask.getDense().at(i);
}

ASSERT_TRUE(check_vector_eq(unionMask1, supersetMask1, 12));
Expand All @@ -1667,21 +1675,21 @@ TEST(SpatialPoolerTest, testinitMapPotential2D) {
sp.setPotentialRadius(potentialRadius);
sp.setPotentialPct(potentialPct);

vector<UInt> mask;
SDR mask({sp.getNumInputs()});

// Test without wrapAround
UInt expectedMask1[72] = {
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
mask = sp.initMapPotential_(0, false);
sp.initMapPotential_(0, false, mask);
ASSERT_TRUE(check_vector_eq(expectedMask1, mask));

UInt expectedMask2[72] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
mask = sp.initMapPotential_(2, false);
sp.initMapPotential_(2, false, mask);
ASSERT_TRUE(check_vector_eq(expectedMask2, mask));

// Test with wrapAround
Expand All @@ -1691,14 +1699,14 @@ TEST(SpatialPoolerTest, testinitMapPotential2D) {
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1};
mask = sp.initMapPotential_(0, true);
sp.initMapPotential_(0, true, mask);
ASSERT_TRUE(check_vector_eq(expectedMask3, mask));

UInt expectedMask4[72] = {
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1};
mask = sp.initMapPotential_(3, true);
sp.initMapPotential_(3, true, mask);
ASSERT_TRUE(check_vector_eq(expectedMask4, mask));
}

Expand Down
30 changes: 15 additions & 15 deletions src/test/unit/regions/TMRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
#include <nupic/os/Timer.hpp>
#include <nupic/regions/TMRegion.hpp>
#include <nupic/types/Exception.hpp>
#include <nupic/utils/VectorHelpers.hpp>

#include <cmath> // fabs/abs
#include <cstdlib> // exit
Expand All @@ -75,6 +74,8 @@
#include "yaml-cpp/yaml.h"
#include "gtest/gtest.h"

namespace testing {

#define VERBOSE if (verbose) std::cerr << "[ ] "
static bool verbose = false; // turn this on to print extra stuff for debugging the test.

Expand All @@ -84,7 +85,6 @@ static bool verbose = false; // turn this on to print extra stuff for debugging

using namespace nupic;

namespace testing {

// Verify that all parameters are working.
// Assumes that the default value in the Spec is the same as the default when
Expand Down Expand Up @@ -277,9 +277,9 @@ TEST(TMRegionTest, testLinking) {
<< r3InputArray.getCount();
EXPECT_TRUE(r3InputArray.getType() == NTA_BasicType_SDR);
VERBOSE << " " << r3InputArray << "\n";
std::vector<Byte> expected3in = VectorHelpers::sparseToBinary<Byte>(
{ 1, 2, 3, 5, 6, 8, 11, 13, 17, 19 }, (UInt32)r3InputArray.getCount());
EXPECT_TRUE(r3InputArray == expected3in);
SDR expectedR3Input({(UInt32)r3InputArray.getCount()});
expectedR3Input.setSparse(SDR_sparse_t{ 1, 2, 3, 5, 6, 8, 11, 13, 17, 19 });
EXPECT_EQ(r3InputArray.getSDR(), expectedR3Input);

VERBOSE << " TMRegion output "
<< region3->getOutputDimensions("bottomUpOut") << "\n";
Expand All @@ -293,13 +293,13 @@ TEST(TMRegionTest, testLinking) {
<< r3InputArray.getCount();
EXPECT_TRUE(r3OutputArray.getType() == NTA_BasicType_SDR);
VERBOSE << " " << r3OutputArray << "\n";
std::vector<Byte> expected3out = VectorHelpers::sparseToBinary<Byte>(
{ 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
SDR expectedR3Out({(UInt32)r3OutputArray.getCount()});
expectedR3Out.setSparse( SDR_sparse_t{ 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 40u, 41u, 42u, 43u,
44u, 55u, 56u, 57u, 58u, 59u, 65u, 66u, 67u, 68u, 69u, 85u, 86u, 87u,
88u, 89u, 95u, 96u, 97u, 98u, 99u }, (UInt32)r3OutputArray.getCount());
EXPECT_TRUE(r3OutputArray == expected3out);
EXPECT_EQ(r3OutputArray.getSDR().getSparse().size(), 50u);
88u, 89u, 95u, 96u, 97u, 98u, 99u });
EXPECT_EQ(r3OutputArray.getSDR(), expectedR3Out);
EXPECT_EQ(r3OutputArray.getSDR().getSum(), 50u);

// execute TMRegion several more times and check that it has output.
VERBOSE << "Execute 9 times." << std::endl;
Expand All @@ -313,20 +313,20 @@ TEST(TMRegionTest, testLinking) {
<< r3OutputArray.getCount() << ", should be ("
<< numberOfCols << " * " << cellsPerColumn;
VERBOSE << " " << r3OutputArray << ")\n";
std::vector<Byte> expected3outa = VectorHelpers::sparseToBinary<Byte>(
{20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 35u, 36u, 37u, 38u,
expectedR3Out.setSparse(
SDR_sparse_t{20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 35u, 36u, 37u, 38u,
39u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 60u, 61u, 62u,
63u, 64u, 70u, 71u, 72u, 73u, 74u, 80u, 81u, 82u, 83u, 84u, 90u, 91u,
92u, 93u, 94u, 95u, 96u, 97u, 98u, 99u}, (UInt32)r3OutputArray.getCount());
EXPECT_TRUE(r3OutputArray == expected3outa);
92u, 93u, 94u, 95u, 96u, 97u, 98u, 99u});
EXPECT_EQ(r3OutputArray, expectedR3Out.getDense());


VERBOSE << " Input to VectorFileEffector "
<< region4->getInputDimensions("dataIn") << "\n";
Array r4InputArray = region4->getInputData("dataIn");
EXPECT_TRUE(r4InputArray.getType() == NTA_BasicType_Real32);
VERBOSE << " " << r4InputArray << "\n";
EXPECT_TRUE(r4InputArray == expected3outa);
EXPECT_TRUE(r4InputArray == expectedR3Out.getDense());

// cleanup
region3->executeCommand({"closeFile"});
Expand Down
Loading