From d2f061ab4fdbbf9fac43965f78ddac348d5bfaeb Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Thu, 28 Feb 2019 18:18:48 +0100 Subject: [PATCH 01/16] SP: strip unlearned columns: return usage return number of cols removed/stripped. and print if > 0 --- src/nupic/algorithms/SpatialPooler.cpp | 11 ++++++++--- src/nupic/algorithms/SpatialPooler.hpp | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/nupic/algorithms/SpatialPooler.cpp b/src/nupic/algorithms/SpatialPooler.cpp index 6abf03c2bb..8d84c0bfc0 100644 --- a/src/nupic/algorithms/SpatialPooler.cpp +++ b/src/nupic/algorithms/SpatialPooler.cpp @@ -524,19 +524,21 @@ void SpatialPooler::compute(SDR &input, bool learn, SDR &active) { } // old API version -void SpatialPooler::stripUnlearnedColumns(UInt activeArray[]) const { +size_t SpatialPooler::stripUnlearnedColumns(UInt activeArray[]) const { SDR active(columnDimensions_); active.setDense(activeArray); - stripUnlearnedColumns(active); + const auto removed = stripUnlearnedColumns(active); std::copy(active.getDense().begin(), active.getDense().end(), activeArray); + return removed; } // performs activeColumns AND current-round learned columns: active & activeDutyCyc_ -void SpatialPooler::stripUnlearnedColumns(SDR& active) const { +size_t SpatialPooler::stripUnlearnedColumns(SDR& active) const { auto sparseCols = active.getFlatSparse(); vector res; res.reserve(sparseCols.size()); + size_t removed = active.size; for (const auto& col: sparseCols) { if (activeDutyCycles_[col] > 0) { res.push_back(col); @@ -544,6 +546,9 @@ void SpatialPooler::stripUnlearnedColumns(SDR& active) const { } //update original SDR with changed values active.setFlatSparse(res); + removed = removed - active.size; //size of active befor/after the pruning + if(removed > 0) std::cout << "stripped: " << removed << std::endl; + return removed; } diff --git a/src/nupic/algorithms/SpatialPooler.hpp b/src/nupic/algorithms/SpatialPooler.hpp index 1e278a5313..00f0c9f824 100644 --- a/src/nupic/algorithms/SpatialPooler.hpp +++ b/src/nupic/algorithms/SpatialPooler.hpp @@ -289,8 +289,8 @@ class SpatialPooler : public Serializable columns calculated by the 'compute' method after disabling any columns that are not learned. */ - void stripUnlearnedColumns(UInt activeArray[]) const; - void stripUnlearnedColumns(SDR& active) const; + size_t stripUnlearnedColumns(UInt activeArray[]) const; + size_t stripUnlearnedColumns(SDR& active) const; /** * Get the version number of this spatial pooler. From d5bcc46dfc9a959eb541bbe0655bb74b68fa1f55 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Fri, 1 Mar 2019 18:26:02 +0100 Subject: [PATCH 02/16] SP: removed stripUnlearnedColumns() --- API_CHANGELOG.md | 2 + .../bindings/algorithms/py_SpatialPooler.cpp | 6 --- src/examples/hotgym/HelloSPTP.cpp | 2 - src/examples/mnist/MNIST_SP.cpp | 1 - src/nupic/algorithms/SpatialPooler.cpp | 28 ---------- src/nupic/algorithms/SpatialPooler.hpp | 12 ----- .../unit/algorithms/SpatialPoolerTest.cpp | 53 ------------------- 7 files changed, 2 insertions(+), 102 deletions(-) diff --git a/API_CHANGELOG.md b/API_CHANGELOG.md index b7d8e15c0e..54b4ee84e3 100644 --- a/API_CHANGELOG.md +++ b/API_CHANGELOG.md @@ -56,3 +56,5 @@ As a side-effect of this change, the LinkType and LinkParam parameters in the Ne are ignored. PR #271 * Removed all matrix libraries. Use the `Connections` class instead. PR #169 + +* Removed `void SpatialPooler::stripUnlearnedColumns()` as unused and not useful (did not effectively remove any columns). https://github.com/htm-community/nupic.cpp/pull/286 diff --git a/bindings/py/cpp_src/bindings/algorithms/py_SpatialPooler.cpp b/bindings/py/cpp_src/bindings/algorithms/py_SpatialPooler.cpp index c023b10497..4f30a9abf1 100644 --- a/bindings/py/cpp_src/bindings/algorithms/py_SpatialPooler.cpp +++ b/bindings/py/cpp_src/bindings/algorithms/py_SpatialPooler.cpp @@ -184,12 +184,6 @@ namespace nupic_ext self.compute(get_it(x), learn, get_it(y)); }); - // stripUnlearnedColumns - py_SpatialPooler.def("stripUnlearnedColumns", [](SpatialPooler& self, py::array_t& x) - { - self.stripUnlearnedColumns(get_it(x)); - }); - // setBoostFactors py_SpatialPooler.def("setBoostFactors", [](SpatialPooler& self, py::array_t& x) { diff --git a/src/examples/hotgym/HelloSPTP.cpp b/src/examples/hotgym/HelloSPTP.cpp index 2d4a8fce1b..490b800645 100644 --- a/src/examples/hotgym/HelloSPTP.cpp +++ b/src/examples/hotgym/HelloSPTP.cpp @@ -123,7 +123,6 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool tSPloc.start(); fill(outSP.begin(), outSP.end(), 0); spLocal.compute(input.data(), true, outSP.data()); - spLocal.stripUnlearnedColumns(outSP.data()); tSPloc.stop(); NTA_CHECK(outSP.size() == COLS); } @@ -132,7 +131,6 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool tSPglob.start(); fill(outSP.begin(), outSP.end(), 0); spGlobal.compute(input.data(), true, outSP.data()); - spGlobal.stripUnlearnedColumns(outSP.data()); tSPglob.stop(); NTA_CHECK(outSP.size() == COLS); } diff --git a/src/examples/mnist/MNIST_SP.cpp b/src/examples/mnist/MNIST_SP.cpp index 454adac094..407ad9c636 100644 --- a/src/examples/mnist/MNIST_SP.cpp +++ b/src/examples/mnist/MNIST_SP.cpp @@ -148,7 +148,6 @@ void test() { // Compute input.setDense( image ); sp.compute(input, false, columns); - sp.stripUnlearnedColumns(columns); ClassifierResult result; clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), /* bucketIdxList */ {}, diff --git a/src/nupic/algorithms/SpatialPooler.cpp b/src/nupic/algorithms/SpatialPooler.cpp index 8d84c0bfc0..654767b0b9 100644 --- a/src/nupic/algorithms/SpatialPooler.cpp +++ b/src/nupic/algorithms/SpatialPooler.cpp @@ -523,34 +523,6 @@ void SpatialPooler::compute(SDR &input, bool learn, SDR &active) { } } -// old API version -size_t SpatialPooler::stripUnlearnedColumns(UInt activeArray[]) const { - SDR active(columnDimensions_); - active.setDense(activeArray); - const auto removed = stripUnlearnedColumns(active); - std::copy(active.getDense().begin(), active.getDense().end(), activeArray); - return removed; -} - -// performs activeColumns AND current-round learned columns: active & activeDutyCyc_ -size_t SpatialPooler::stripUnlearnedColumns(SDR& active) const { - auto sparseCols = active.getFlatSparse(); - vector res; - res.reserve(sparseCols.size()); - - size_t removed = active.size; - for (const auto& col: sparseCols) { - if (activeDutyCycles_[col] > 0) { - res.push_back(col); - } - } - //update original SDR with changed values - active.setFlatSparse(res); - removed = removed - active.size; //size of active befor/after the pruning - if(removed > 0) std::cout << "stripped: " << removed << std::endl; - return removed; -} - void SpatialPooler::boostOverlaps_(const vector &overlaps, //TODO use Eigen sparse vector here vector &boosted) const { diff --git a/src/nupic/algorithms/SpatialPooler.hpp b/src/nupic/algorithms/SpatialPooler.hpp index 00f0c9f824..f6281efb5b 100644 --- a/src/nupic/algorithms/SpatialPooler.hpp +++ b/src/nupic/algorithms/SpatialPooler.hpp @@ -279,18 +279,6 @@ class SpatialPooler : public Serializable */ virtual void compute(SDR &input, bool learn, SDR &active); - /** - Removes the set of columns who have never been active from the set - of active columns selected in the inhibition round. Such columns - cannot represent learned pattern and are therefore meaningless if - only inference is required. - - @param activeArray An array of 1's and 0's representing winning - columns calculated by the 'compute' method after disabling - any columns that are not learned. - */ - size_t stripUnlearnedColumns(UInt activeArray[]) const; - size_t stripUnlearnedColumns(SDR& active) const; /** * Get the version number of this spatial pooler. diff --git a/src/test/unit/algorithms/SpatialPoolerTest.cpp b/src/test/unit/algorithms/SpatialPoolerTest.cpp index 9fed69fa58..76e1b792e5 100644 --- a/src/test/unit/algorithms/SpatialPoolerTest.cpp +++ b/src/test/unit/algorithms/SpatialPoolerTest.cpp @@ -1696,59 +1696,6 @@ TEST(SpatialPoolerTest, testinitMapPotential2D) { ASSERT_TRUE(check_vector_eq(expectedMask4, mask)); } -TEST(SpatialPoolerTest, testStripUnlearnedColumns) { - SpatialPooler sp; - vector inputDim{5}, columnDim{3}; - sp.initialize(inputDim, columnDim); - - // None learned, none active - { - Real activeDutyCycles[3] = {0, 0, 0}; - UInt activeArray[3] = {0, 0, 0}; - UInt expected[3] = {0, 0, 0}; - - sp.setActiveDutyCycles(activeDutyCycles); - sp.stripUnlearnedColumns(activeArray); - - ASSERT_TRUE(check_vector_eq(activeArray, expected, 3)); - } - - // None learned, some active - { - Real activeDutyCycles[3] = {0, 0, 0}; - UInt activeArray[3] = {1, 0, 1}; - UInt expected[3] = {0, 0, 0}; - - sp.setActiveDutyCycles(activeDutyCycles); - sp.stripUnlearnedColumns(activeArray); - - ASSERT_TRUE(check_vector_eq(activeArray, expected, 3)); - } - - // Some learned, none active - { - Real activeDutyCycles[3] = {1, 1, 0}; - UInt activeArray[3] = {0, 0, 0}; - UInt expected[3] = {0, 0, 0}; - - sp.setActiveDutyCycles(activeDutyCycles); - sp.stripUnlearnedColumns(activeArray); - - ASSERT_TRUE(check_vector_eq(activeArray, expected, 3)); - } - - // Some learned, some active - { - Real activeDutyCycles[3] = {1, 1, 0}; - UInt activeArray[3] = {1, 0, 1}; - UInt expected[3] = {1, 0, 0}; - - sp.setActiveDutyCycles(activeDutyCycles); - sp.stripUnlearnedColumns(activeArray); - - ASSERT_TRUE(check_vector_eq(activeArray, expected, 3)); - } -} TEST(SpatialPoolerTest, getOverlaps) { SpatialPooler sp; From 0c3bc81048c5ca171f7edc14f40c4682981d4050 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 10:57:03 +0100 Subject: [PATCH 03/16] Revert "Start ASCII experiment" This reverts commit 19ef8526b1a01d13862eb5e237f7258611a2aa23. --- src/CMakeLists.txt | 19 ------------------- src/examples/ascii.cpp | 26 -------------------------- 2 files changed, 45 deletions(-) delete mode 100644 src/examples/ascii.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50ac98090e..479d91a629 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -419,25 +419,6 @@ add_custom_target(mnist COMMENT "Executing ${src_executable_mnistsp}" VERBATIM) - -######################################################### -## ASCII Example -# -set(src_executable_ascii ascii) -add_executable(${src_executable_ascii} "examples/ascii.cpp") -target_link_libraries(${src_executable_ascii} ${core_library}) -target_compile_options(${src_executable_ascii} PUBLIC ${INTERNAL_CXX_FLAGS}) -target_compile_definitions(${src_executable_ascii} PRIVATE ${COMMON_COMPILER_DEFINITIONS}) -target_include_directories(${src_executable_ascii} PRIVATE - ${CORE_LIB_INCLUDES} - ${EXTERNAL_INCLUDES} - ) -# add_custom_target(ascii -# COMMAND ${src_executable_ascii} -# DEPENDS ${src_executable_ascii} -# COMMENT "Executing ${src_executable_ascii}" -# VERBATIM) - ################################################## # # Install targets into CMAKE_INSTALL_PREFIX diff --git a/src/examples/ascii.cpp b/src/examples/ascii.cpp deleted file mode 100644 index 355f2fdb90..0000000000 --- a/src/examples/ascii.cpp +++ /dev/null @@ -1,26 +0,0 @@ - -#include -#include -#include -#include - -using namespace std; - - -int main() { - cout << "ASCII" << endl; - - auto dataFilename = "./ascii.cpp"; - ifstream dataFile( dataFilename ); - string str((istreambuf_iterator(dataFile)), istreambuf_iterator()); - - // Make model - - // Run model - - // Measure online stability - - // Measure inter/intra catagory overlap - - // Measure whole word classification accuracy -} From c7e7b9db6ecca91f3c9ec13508a2b13ce61dcd87 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 11:03:47 +0100 Subject: [PATCH 04/16] merge MNIST example from master --- src/examples/mnist/MNIST_SP.cpp | 261 ++++++++++++-------------------- 1 file changed, 100 insertions(+), 161 deletions(-) diff --git a/src/examples/mnist/MNIST_SP.cpp b/src/examples/mnist/MNIST_SP.cpp index a40cd89819..454adac094 100644 --- a/src/examples/mnist/MNIST_SP.cpp +++ b/src/examples/mnist/MNIST_SP.cpp @@ -24,206 +24,133 @@ */ #include -#include -#include +#include //uint8_t #include #include -#include +#include #include #include -#include #include +#include // MNIST data itself + read methods, namespace mnist:: + +namespace examples { + using namespace std; using namespace nupic; -// using nupic::algorithms::spatial_pooler_extended::SpatialPoolerExtended; + +using nupic::algorithms::spatial_pooler::SpatialPooler; using nupic::algorithms::sdr_classifier::SDRClassifier; using nupic::algorithms::cla_classifier::ClassifierResult; - -vector read_mnist_labels(string path) { - ifstream file(path); - if( !file.is_open() ) { - cerr << "ERROR: Failed to open file " << path << endl; - exit(1); - } - int magic_number = 0; - int number_of_labels = 0; - file.read( (char*) &magic_number, 4); - file.read( (char*) &number_of_labels, 4); - if(magic_number != 0x00000801) { - std::reverse((char*) &magic_number, (char*) &magic_number + 4); - std::reverse((char*) &number_of_labels, (char*) &number_of_labels + 4); - } - if(magic_number != 0x00000801) { - cerr << "ERROR: MNIST data is compressed or corrupt" << endl; - exit(1); - } - vector retval; - for(int i = 0; i < number_of_labels; ++i) { - unsigned char label = 0; - file.read( (char*) &label, 1); - retval.push_back((UInt) label); - } - return retval; -} - - -vector read_mnist_images(string path) { - ifstream file(path); - if( !file.is_open() ) { - cerr << "ERROR: Failed to open file " << path << endl; - exit(1); - } - int magic_number = 0; - int number_of_images = 0; - int n_rows = 0; - int n_cols = 0; - file.read( (char*) &magic_number, 4); - file.read( (char*) &number_of_images, 4); - file.read( (char*) &n_rows, 4); - file.read( (char*) &n_cols, 4); - if(magic_number != 0x00000803) { - std::reverse((char*) &magic_number, (char*) &magic_number + 4); - std::reverse((char*) &number_of_images, (char*) &number_of_images + 4); - std::reverse((char*) &n_rows, (char*) &n_rows + 4); - std::reverse((char*) &n_cols, (char*) &n_cols + 4); - } - if(magic_number != 0x00000803) { - cerr << "ERROR: MNIST data is compressed or corrupt" << endl; - exit(1); - } - NTA_ASSERT(n_rows == 28); - NTA_ASSERT(n_cols == 28); - UInt img_size = n_rows * n_cols; - vector retval; - for(int i = 0; i < number_of_images; ++i) { - auto data_raw = new unsigned char[img_size]; - file.read( (char*) data_raw, img_size); - // Copy the data into an array of UInt's - auto data = new UInt[img_size]; - // auto data = new UInt[2 * img_size]; - // Apply a threshold to the image, yielding a B & W image. - for(UInt pixel = 0; pixel < img_size; pixel++) { - data[pixel] = data_raw[pixel] >= 128 ? 1 : 0; - // data[2 * pixel] = data_raw[pixel] >= 128 ? 1 : 0; - // data[2 * pixel + 1] = 1 - data[2 * pixel]; - } - retval.push_back(data); - delete[] data_raw; - } - return retval; -} - - -int main(int argc, char **argv) { - UInt verbosity = 1; - auto train_dataset_iterations = 1u; - // int opt; - // while ( (opt = getopt(argc, argv, "tv")) != -1 ) { // for each option... - // switch ( opt ) { - // case 't': - // train_dataset_iterations += 1; - // break; - // case 'v': - // verbosity = 1; - // break; - // case '?': - // cerr << "Unknown option: '" << char(optopt) << "'!" << endl; - // break; - // } - // } - - SDR input({28, 28}); - ColumnPooler htm( - /* proximalInputDimensions */ input.dimensions, - /* distalInputDimensions */ {1}, - /* inhibitionDimensions */ {10, 10}, - /* cellsPerInhbitionArea */ 120, - /* sparsity */ .015, - /* potentialPool */ DefaultTopology(.9, 4., false), - /* proximalSegments */ 1, - /* proximalSegmentThreshold */ 28, - /* proximalIncrement */ .032, - /* proximalDecrement */ .00928, - /* proximalSynapseThreshold */ .422, - /* distalMaxSegments */ 0, - /* distalMaxSynapsesPerSegment */ 0, - /* distalSegmentThreshold */ 0, - /* distalIncrement */ 0, - /* distalDecrement */ 0, - /* distalMispredictDecrement */ 0, - /* distalSynapseThreshold */ 0, - /* stability_rate */ 0, - /* fatigue_rate */ 0, - /* period */ 1402, - /* seed */ 0, - /* verbose */ verbosity); - - SDR cells( htm.cellDimensions ); - SDR_Metrics columnStats(cells, 1402); - - SDRClassifier clsr( +class MNIST { + + private: + SpatialPooler sp; + SDR input; + SDR columns; + SDRClassifier clsr; + mnist::MNIST_dataset, uint8_t> dataset; + + public: + UInt verbosity = 1; + const UInt train_dataset_iterations = 1u; + + +void setup() { + + input.initialize({28, 28}); + sp.initialize( + /* inputDimensions */ input.dimensions, + /* columnDimensions */ {28, 28}, //mostly affects speed, to some threshold accuracy only marginally + /* potentialRadius */ 5u, + /* potentialPct */ 0.5f, + /* globalInhibition */ false, + /* localAreaDensity */ 0.20f, //% active bits, //quite important variable (speed x accuracy) + /* numActiveColumnsPerInhArea */ -1, + /* stimulusThreshold */ 6u, + /* synPermInactiveDec */ 0.005f, + /* synPermActiveInc */ 0.01f, + /* synPermConnected */ 0.4f, + /* minPctOverlapDutyCycles */ 0.001f, + /* dutyCyclePeriod */ 1402, + /* boostStrength */ 2.5f, //boosting does help + /* seed */ 93u, + /* spVerbosity */ 1u, + /* wrapAround */ false); //wrap is false for this problem + + columns.initialize({sp.getNumColumns()}); + + clsr.initialize( /* steps */ {0}, /* alpha */ .001, /* actValueAlpha */ .3, verbosity); + dataset = mnist::read_dataset(string("../ThirdParty/mnist_data/mnist-src/")); //from CMake +} + +void train() { // Train - auto train_images = read_mnist_images("./mnist_data/train-images-idx3-ubyte"); - auto train_labels = read_mnist_labels("./mnist_data/train-labels-idx1-ubyte"); + if(verbosity) - cout << "Training for " << (train_dataset_iterations * train_labels.size()) + cout << "Training for " << (train_dataset_iterations * dataset.training_labels.size()) << " cycles ..." << endl; - for(auto i = 0u; i < train_dataset_iterations; i++) { + size_t i = 0; + + SDR_Metrics inputStats(input, 1402); + SDR_Metrics columnStats(columns, 1402); + + for(auto epoch = 0u; epoch < train_dataset_iterations; epoch++) { + NTA_INFO << "epoch " << epoch; // Shuffle the training data. - vector index( train_labels.size() ); - for(auto s = 0u; s < train_labels.size(); s++) - index[s] = s; - Random(3).shuffle( index.begin(), index.end() ); + vector index( dataset.training_labels.size() ); + index.assign(dataset.training_labels.cbegin(), dataset.training_labels.cend()); + Random().shuffle( index.begin(), index.end() ); - for(auto s = 0u; s < train_labels.size(); s++) { + for(const auto idx : index) { // index = order of label (shuffeled) // Get the input & label - UInt *image = train_images[ index[s] ]; - UInt label = train_labels[ index[s] ]; + const auto image = dataset.training_images.at(idx); + const UInt label = dataset.training_labels.at(idx); // Compute & Train input.setDense( image ); - htm.compute(input, true, cells); + sp.compute(input, true, columns); ClassifierResult result; - clsr.compute(htm.iterationNum, cells.getFlatSparse(), + clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), /* bucketIdxList */ {label}, /* actValueList */ {(Real)label}, /* category */ true, /* learn */ true, /* infer */ false, &result); - if( verbosity and htm.iterationNum % 1000 == 0 ) - cout << "." << flush; + if( verbosity && (++i % 1000 == 0) ) cout << "." << flush; } + if( verbosity ) cout << endl; } - if( verbosity ) cout << endl; - - cout << columnStats; + cout << "epoch ended" << endl; + cout << inputStats << endl; + cout << columnStats << endl; +} +void test() { // Test - auto test_images = read_mnist_images("./mnist_data/t10k-images-idx3-ubyte"); - auto test_labels = read_mnist_labels("./mnist_data/t10k-labels-idx1-ubyte"); Real score = 0; UInt n_samples = 0; if(verbosity) - cout << "Testing for " << test_labels.size() << " cycles ..." << endl; - for(UInt i = 0; i < test_labels.size(); i++) { + cout << "Testing for " << dataset.test_labels.size() << " cycles ..." << endl; + for(UInt i = 0; i < dataset.test_labels.size(); i++) { // Get the input & label - UInt *image = test_images[i]; - UInt label = test_labels[i]; + const auto image = dataset.test_images.at(i); + const UInt label = dataset.test_labels.at(i); // Compute input.setDense( image ); - htm.compute(input, false, cells); + sp.compute(input, false, columns); + sp.stripUnlearnedColumns(columns); ClassifierResult result; - clsr.compute(htm.iterationNum, cells.getFlatSparse(), + clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), /* bucketIdxList */ {}, /* actValueList */ {}, /* category */ true, @@ -233,17 +160,29 @@ int main(int argc, char **argv) { // Check results for(auto iter : result) { if( iter.first == 0 ) { - auto *pdf = iter.second; - auto max = std::max_element(pdf->begin(), pdf->end()); - UInt cls = max - pdf->begin(); + const auto *pdf = iter.second; + const auto max = std::max_element(pdf->cbegin(), pdf->cend()); + const UInt cls = max - pdf->cbegin(); if(cls == label) score += 1; n_samples += 1; } } - if( verbosity and i % 1000 == 0 ) - cout << "." << flush; + if( verbosity && i % 1000 == 0 ) cout << "." << flush; } if( verbosity ) cout << endl; - cout << "Score: " << score / n_samples << endl; + cout << "Score: " << 100.0 * score / n_samples << "% " << endl; +} + +}; // End class MNIST +} // End namespace examples + +int main(int argc, char **argv) { + examples::MNIST m; + m.setup(); + m.train(); + m.test(); + + return 0; } + From f499e0160b0d6a5b373ae440211e1d8e322a7078 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 11:06:20 +0100 Subject: [PATCH 05/16] resolve merge conflicts removed duplicit MNIST cmake entry --- src/CMakeLists.txt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 479d91a629..4744c74518 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -401,24 +401,6 @@ add_custom_target(mnist VERBATIM) -######################################################### -## MNIST Spatial Pooler Example -# -set(src_executable_mnistsp mnist_sp) -add_executable(${src_executable_mnistsp} "examples/mnist/MNIST_SP.cpp") -target_link_libraries(${src_executable_mnistsp} ${core_library}) -target_compile_options(${src_executable_mnistsp} PUBLIC ${INTERNAL_CXX_FLAGS}) -target_compile_definitions(${src_executable_mnistsp} PRIVATE ${COMMON_COMPILER_DEFINITIONS}) -target_include_directories(${src_executable_mnistsp} PRIVATE - ${CORE_LIB_INCLUDES} - ${EXTERNAL_INCLUDES} - ) -add_custom_target(mnist - COMMAND ${src_executable_mnistsp} - DEPENDS ${src_executable_mnistsp} - COMMENT "Executing ${src_executable_mnistsp}" - VERBATIM) - ################################################## # # Install targets into CMAKE_INSTALL_PREFIX @@ -427,7 +409,6 @@ install(TARGETS ${core_library} ${src_executable_hotgym} ${src_executable_mnistsp} - ${src_executable_ascii} RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) From 01e83b00fe66cac01e70d5c9455014a2e025461f Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 11:08:51 +0100 Subject: [PATCH 06/16] ColumnPooler: make in namespace nupic::algorithms::column_pooler --- src/nupic/algorithms/ColumnPooler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index 0af921e5f8..72b68a9334 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -42,6 +42,10 @@ #include #include +namespace nupic { +namespace algorithms { +namespace column_pooler { + using namespace std; using namespace nupic; using namespace nupic::math::topology; @@ -482,3 +486,4 @@ class DefaultTopology : public Topology_t } }; +}}} //-end ns From d1326106c0b192d7d4449b96fd116d1ae3bdf488 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 11:49:10 +0100 Subject: [PATCH 07/16] ColumnPooler: add initialize() and default empty constructor --- src/nupic/algorithms/ColumnPooler.cpp | 54 +++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index 72b68a9334..319032ea76 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -116,7 +116,61 @@ class ColumnPooler // : public Serializable Connections distalConnections; + + ColumnPooler() {}; //default constructor, must call initialize to setup properly + ColumnPooler( + const vector proximalInputDimensions, + const vector distalInputDimensions, + const vector inhibitionDimensions, + UInt cellsPerInhbitionArea, + Real sparsity, + Topology_t potentialPool, + UInt proximalSegments, + UInt proximalSegmentThreshold, + Permanence proximalIncrement, + Permanence proximalDecrement, + Permanence proximalSynapseThreshold, + UInt distalMaxSegments, + UInt distalMaxSynapsesPerSegment, + UInt distalSegmentThreshold, + Permanence distalIncrement, + Permanence distalDecrement, + Permanence distalMispredictDecrement, + Permanence distalSynapseThreshold, + Real stability_rate, + Real fatigue_rate, + Real period, + Int seed, + bool verbose) { + initialize( + proximalInputDimensions, + distalInputDimensions, + inhibitionDimensions, + cellsPerInhibitionArea, + sparsity, + potentialPool, + proximalSegments, + proximalSegmentThreshold, + proximalIncrement, + proximalDecrement, + proximalSynapseThreshold, + distalMaxSegments, + distalMaxSynapsesPerSegment, + distalSegmentThreshold, + distalIncrement, + distalDecrement, + distalMispredictDecrement, + distalSynapseThreshold, + sparsity_rate, + fatigue_rate, + period, + seed, + verbose); + } + + + void initialize( const vector proximalInputDimensions, const vector distalInputDimensions, const vector inhibitionDimensions, From 6bffed93c6f6ace6af134511c9c3331e503046a1 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 11:54:11 +0100 Subject: [PATCH 08/16] CP: fix typo Inhbition -> Inhibition in names --- src/nupic/algorithms/ColumnPooler.cpp | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index 319032ea76..0220e46b86 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -65,7 +65,7 @@ class ColumnPooler // : public Serializable vector distalInputDimensions_; vector inhibitionDimensions_; vector cellDimensions_; - UInt cellsPerInhbitionArea_; + UInt cellsPerInhibitionArea_; UInt proximalSegments_; vector proximalMaxSegment_; @@ -79,7 +79,7 @@ class ColumnPooler // : public Serializable const vector &proximalInputDimensions = proximalInputDimensions_; const vector &distalInputDimensions = distalInputDimensions_; const vector &inhibitionDimensions = inhibitionDimensions_; - const UInt &cellsPerInhbitionArea = cellsPerInhbitionArea_; + const UInt &cellsPerInhibitionArea = cellsPerInhibitionArea_; const vector &cellDimensions = cellDimensions_; const UInt &proximalSegments = proximalSegments_; @@ -123,7 +123,7 @@ class ColumnPooler // : public Serializable const vector proximalInputDimensions, const vector distalInputDimensions, const vector inhibitionDimensions, - UInt cellsPerInhbitionArea, + UInt cellsPerInhibitionArea, Real sparsity, Topology_t potentialPool, UInt proximalSegments, @@ -162,7 +162,7 @@ class ColumnPooler // : public Serializable distalDecrement, distalMispredictDecrement, distalSynapseThreshold, - sparsity_rate, + stability_rate, fatigue_rate, period, seed, @@ -174,7 +174,7 @@ class ColumnPooler // : public Serializable const vector proximalInputDimensions, const vector distalInputDimensions, const vector inhibitionDimensions, - UInt cellsPerInhbitionArea, + UInt cellsPerInhibitionArea, Real sparsity, @@ -202,7 +202,7 @@ class ColumnPooler // : public Serializable proximalInputDimensions_ = proximalInputDimensions; distalInputDimensions_ = distalInputDimensions; inhibitionDimensions_ = inhibitionDimensions; - cellsPerInhbitionArea_ = cellsPerInhbitionArea; + cellsPerInhibitionArea_ = cellsPerInhibitionArea; proximalSegments_ = proximalSegments; this->sparsity = sparsity; this->proximalSegmentThreshold = proximalSegmentThreshold; @@ -221,7 +221,7 @@ class ColumnPooler // : public Serializable SDR proximalInputs( proximalInputDimensions ); SDR inhibitionAreas( inhibitionDimensions ); cellDimensions_ = inhibitionAreas.dimensions; - cellDimensions_.push_back( cellsPerInhbitionArea ); + cellDimensions_.push_back( cellsPerInhibitionArea ); SDR cells( cellDimensions_ ); // Setup the proximal segments & synapses. @@ -231,7 +231,7 @@ class ColumnPooler // : public Serializable UInt cell = 0u; for(auto inhib = 0u; inhib < inhibitionAreas.size; ++inhib) { inhibitionAreas.setFlatSparse(SDR_flatSparse_t{ inhib }); - for(auto c = 0u; c < cellsPerInhbitionArea; ++c, ++cell) { + for(auto c = 0u; c < cellsPerInhibitionArea; ++c, ++cell) { for(auto s = 0u; s < proximalSegments; ++s) { auto segment = proximalConnections.createSegment( cell ); @@ -408,10 +408,10 @@ class ColumnPooler // : public Serializable // predictiveCells, SDR &activeCells) { - const UInt inhibitionAreas = activeCells.size / cellsPerInhbitionArea; - const UInt numDesired = (UInt) std::round(sparsity * cellsPerInhbitionArea); - NTA_CHECK(numDesired > 0) << "Not enough cellsPerInhbitionArea (" - << cellsPerInhbitionArea << ") for desired density (" << sparsity << ")."; + const UInt inhibitionAreas = activeCells.size / cellsPerInhibitionArea; + const UInt numDesired = (UInt) std::round(sparsity * cellsPerInhibitionArea); + NTA_CHECK(numDesired > 0) << "Not enough cellsPerInhibitionArea (" + << cellsPerInhibitionArea << ") for desired density (" << sparsity << ")."; // Compare the cell indexes by their overlap. auto compare = [&overlaps](const UInt &a, const UInt &b) -> bool @@ -419,14 +419,14 @@ class ColumnPooler // : public Serializable auto &active = activeCells.getFlatSparse(); active.clear(); - active.reserve(cellsPerInhbitionArea + numDesired * inhibitionAreas ); + active.reserve(cellsPerInhibitionArea + numDesired * inhibitionAreas ); - for(UInt offset = 0u; offset < activeCells.size; offset += cellsPerInhbitionArea) + for(UInt offset = 0u; offset < activeCells.size; offset += cellsPerInhibitionArea) { // Sort the columns by the amount of overlap. First make a list of all of // the mini-column indexes. auto activeBegin = active.end(); - for(UInt i = 0u; i < cellsPerInhbitionArea; i++) + for(UInt i = 0u; i < cellsPerInhibitionArea; i++) active.push_back( i + offset ); // Do a partial sort to divide the winners from the losers. This sort is // faster than a regular sort because it stops after it partitions the @@ -438,7 +438,7 @@ class ColumnPooler // : public Serializable active.end(), compare); // Remove the columns which lost the competition. - active.resize( active.size() - (cellsPerInhbitionArea - numDesired) ); + active.resize( active.size() - (cellsPerInhibitionArea - numDesired) ); // Finish sorting the winner columns by their overlap. // std::sort(activeBegin, active.end(), compare); // Remove sub-threshold winners From 1926f0f08162d309ab69c88477693cde17d07775 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 12:11:40 +0100 Subject: [PATCH 09/16] MNIST: using CP instead of SP --- src/examples/mnist/MNIST_SP.cpp | 47 ++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/examples/mnist/MNIST_SP.cpp b/src/examples/mnist/MNIST_SP.cpp index 454adac094..73176fe363 100644 --- a/src/examples/mnist/MNIST_SP.cpp +++ b/src/examples/mnist/MNIST_SP.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,9 @@ using namespace std; using namespace nupic; using nupic::algorithms::spatial_pooler::SpatialPooler; +using nupic::algorithms::column_pooler::ColumnPooler; +using nupic::algorithms::column_pooler::DefaultTopology; +using nupic::algorithms::connections::Permanence; using nupic::algorithms::sdr_classifier::SDRClassifier; using nupic::algorithms::cla_classifier::ClassifierResult; @@ -48,6 +52,7 @@ class MNIST { private: SpatialPooler sp; + ColumnPooler cp; SDR input; SDR columns; SDRClassifier clsr; @@ -80,7 +85,33 @@ void setup() { /* spVerbosity */ 1u, /* wrapAround */ false); //wrap is false for this problem - columns.initialize({sp.getNumColumns()}); + cp.initialize( + /* proximalInputDimensions */ input.dimensions, + /* distalInputDimensions */ vector{1}, + /* inhibitionDimensions */ vector{10, 10}, + /* cellsPerInhbitionArea */ 120, + /* sparsity */ .015, + /* potentialPool */ DefaultTopology(.9, 4., true), + /* proximalSegments */ 1, + /* proximalSegmentThreshold */ 28, + /* proximalIncrement */ .032, + /* proximalDecrement */ .00928, + /* proximalSynapseThreshold */ .422, + /* distalMaxSegments */ 0u, + /* distalMaxSynapsesPerSegment */ 0u, + /* distalSegmentThreshold */ 0u, + /* distalIncrement */ (Permanence)0.0, + /* distalDecrement */ (Permanence)0.0, + /* distalMispredictDecrement */ (Permanence)0.0, + /* distalSynapseThreshold */ (Permanence)0.0, + /* stability_rate */ 0.0, + /* fatigue_rate */ 0.0, + /* period */ 1402.0, + /* seed */ 0, + /* verbose */ verbosity); + +// columns.initialize({sp.getNumColumns()}); + columns.initialize(cp.cellDimensions); clsr.initialize( /* steps */ {0}, @@ -116,9 +147,12 @@ void train() { // Compute & Train input.setDense( image ); - sp.compute(input, true, columns); + //sp.compute(input, true, columns); //TOGGLE SP/CP computation + cp.compute(input, true, columns); + ClassifierResult result; - clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), + //clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), //TOGGLE + clsr.compute(cp.iterationNum, columns.getFlatSparse(), /* bucketIdxList */ {label}, /* actValueList */ {(Real)label}, /* category */ true, @@ -147,10 +181,11 @@ void test() { // Compute input.setDense( image ); - sp.compute(input, false, columns); - sp.stripUnlearnedColumns(columns); + //sp.compute(input, false, columns); //TOGGLE + cp.compute(input, false, columns); ClassifierResult result; - clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), + //clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), //TOGGLE + clsr.compute(cp.iterationNum, columns.getFlatSparse(), /* bucketIdxList */ {}, /* actValueList */ {}, /* category */ true, From 3d853b86531d8c7eb0e0f48da6f3334123359902 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 12:19:35 +0100 Subject: [PATCH 10/16] Connections: adaptSegment make const input, add check for segfault from CP --- src/nupic/algorithms/Connections.cpp | 4 +++- src/nupic/algorithms/Connections.hpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/nupic/algorithms/Connections.cpp b/src/nupic/algorithms/Connections.cpp index 09c3bc7c03..607b53af7e 100644 --- a/src/nupic/algorithms/Connections.cpp +++ b/src/nupic/algorithms/Connections.cpp @@ -318,6 +318,7 @@ Segment Connections::getSegment(CellIdx cell, SegmentIdx idx) const { } const vector &Connections::synapsesForSegment(Segment segment) const { + NTA_ASSERT(segment < segments_.size()) << "Segment out of bounds! " << segment; return segments_[segment].synapses; } @@ -437,7 +438,8 @@ void Connections::computeActivity( } -void Connections::adaptSegment(const Segment segment, SDR &inputs, +void Connections::adaptSegment(const Segment segment, + const SDR &inputs, const Permanence increment, const Permanence decrement) { diff --git a/src/nupic/algorithms/Connections.hpp b/src/nupic/algorithms/Connections.hpp index ee9aa5b84e..be84e8fd9f 100644 --- a/src/nupic/algorithms/Connections.hpp +++ b/src/nupic/algorithms/Connections.hpp @@ -425,7 +425,8 @@ class Connections : public Serializable * @param increment Change in permanence for synapses with active presynapses. * @param decrement Change in permanence for synapses with inactive presynapses. */ - void adaptSegment(const Segment segment, SDR &inputs, + void adaptSegment(const Segment segment, + const SDR &inputs, const Permanence increment, const Permanence decrement); From ca27761f560a73444c83cb82af550f5eaf1ef302 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 12:45:27 +0100 Subject: [PATCH 11/16] CP: tmp check potential segfault --- src/nupic/algorithms/ColumnPooler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index 0220e46b86..03f1f1efa7 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -458,6 +458,7 @@ class ColumnPooler // : public Serializable for(const auto &cell : active.getFlatSparse()) { // Adapt Proximal Segments + NTA_CHECK(cell < proximalMaxSegment_.size()) << "cell oob! " << cell << " < " << proximalMaxSegment_.size(); const auto maxSegment = proximalMaxSegment_[cell]; proximalConnections.adaptSegment(maxSegment, proximalInputActive, proximalIncrement, proximalDecrement); From d5a1ec095ed137e92695fcdb9a5fa026ffd9ad07 Mon Sep 17 00:00:00 2001 From: David McDougall Date: Sat, 2 Mar 2019 08:40:56 -0500 Subject: [PATCH 12/16] API_CHANGELOG formatting --- API_CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API_CHANGELOG.md b/API_CHANGELOG.md index 54b4ee84e3..c3e025de77 100644 --- a/API_CHANGELOG.md +++ b/API_CHANGELOG.md @@ -57,4 +57,4 @@ are ignored. PR #271 * Removed all matrix libraries. Use the `Connections` class instead. PR #169 -* Removed `void SpatialPooler::stripUnlearnedColumns()` as unused and not useful (did not effectively remove any columns). https://github.com/htm-community/nupic.cpp/pull/286 +* Removed `void SpatialPooler::stripUnlearnedColumns()` as unused and not useful (did not effectively remove any columns). PR #286 From 3a2316695538279b9ca5f110d2a2713235fe8138 Mon Sep 17 00:00:00 2001 From: ctrl-z-9000-times Date: Sat, 2 Mar 2019 11:21:03 -0500 Subject: [PATCH 13/16] SDR renamed data formats: "sparse" -> "coordinate", "flatSparse" -> "sparse" --- .../py/cpp_src/bindings/algorithms/py_SDR.cpp | 61 +++--- src/examples/mnist/MNIST_SP.cpp | 4 +- src/nupic/algorithms/SpatialPooler.cpp | 18 +- src/nupic/algorithms/TemporalMemory.cpp | 12 +- src/nupic/regions/SPRegion.cpp | 4 +- src/nupic/types/Sdr.cpp | 175 ++++++++-------- src/nupic/types/Sdr.hpp | 145 +++++++------- src/nupic/types/SdrProxy.hpp | 28 +-- src/nupic/utils/SdrMetrics.hpp | 4 +- .../unit/algorithms/SpatialPoolerTest.cpp | 4 +- .../unit/algorithms/TemporalMemoryTest.cpp | 8 +- src/test/unit/ntypes/ArrayTest.cpp | 2 +- src/test/unit/types/SdrProxyTest.cpp | 44 ++--- src/test/unit/types/SdrTest.cpp | 186 +++++++++--------- 14 files changed, 342 insertions(+), 353 deletions(-) diff --git a/bindings/py/cpp_src/bindings/algorithms/py_SDR.cpp b/bindings/py/cpp_src/bindings/algorithms/py_SDR.cpp index afc8ce49a8..963d48d356 100644 --- a/bindings/py/cpp_src/bindings/algorithms/py_SDR.cpp +++ b/bindings/py/cpp_src/bindings/algorithms/py_SDR.cpp @@ -45,7 +45,7 @@ state of a group of neurons or their associated processes. SDR's have three commonly used data formats which are: * dense * sparse -* flatSparse +* coordinates 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 @@ -61,21 +61,21 @@ Example usage: X.dense = [[0, 1, 0], [0, 1, 0], [0, 0, 1]] - X.sparse = [[0, 1, 2], [1, 1, 2]] - X.flatSparse = [ 1, 4, 8 ] + 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 -> [[ 0, 1, 2 ], [1, 1, 2 ]] - x.flatSparse -> [ 1, 4, 8 ] + 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.flatSparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache. + 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 @@ -85,12 +85,12 @@ This class will detect that it's being given it's own data and will omit the copy operation. Example Usage of In-Place Assignment: - X = SDR((1000, 1000)) + X = SDR((1000, 1000)) # Initial value is all zeros data = X.dense data[ 0, 4] = 1 data[444, 444] = 1 X.dense = data - X.flatSparse -> [ 4, 444444 ] + X.sparse -> [ 4, 444444 ] Data Validity Warning: The SDR allocates and frees its data when it is constructed and deconstructed, respectively. If you have a numpy array which @@ -102,15 +102,14 @@ Examples of Invalid Data Accesses: del A # The variable "use_after_free" now references data which has been deallocated. # Another way this can happen is: - use_after_free = SDR( dimensions ).sparse - use_after_free = SDR( dimensions ).flatSparse + use_after_free = SDR( dimensions ).dense Data Validity Warning: After assigning a new value to the SDR, all existing numpy arrays of data are invalid. In order to get the latest copy of the data, re-access the data from the SDR. Examples: A = SDR( dimensions ) out_of_date = A.dense - A.flatSparse = [] + A.sparse = [] # The variable "out_of_date" is now liable to be overwritten. A.dense = out_of_date # This does not work, since the data is invalid. )"); @@ -183,34 +182,34 @@ After modifying this array you MUST assign the array back into the SDR, in order to notify the SDR that its dense array has changed and its cached data is out of date. If you did't copy this data, then SDR won't copy either.)"); - py_SDR.def_property("flatSparse", + py_SDR.def_property("sparse", [](SDR &self) { auto capsule = py::capsule(&self, [](void *self) {}); - return py::array(self.getSum(), self.getFlatSparse().data(), capsule); + return py::array(self.getSum(), self.getSparse().data(), capsule); }, - [](SDR &self, SDR_flatSparse_t data) { + [](SDR &self, SDR_sparse_t data) { NTA_CHECK( data.size() <= self.size ); - self.setFlatSparse( data ); }, + self.setSparse( data ); }, R"(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.)"); - py_SDR.def_property("sparse", + py_SDR.def_property("coordinates", [](SDR &self) { auto capsule = py::capsule(&self, [](void *self) {}); auto outer = py::list(); - auto sparse = self.getSparse().data(); - for(auto dim = 0u; dim < self.dimensions.size(); dim++) { - auto vec = py::array(sparse[dim].size(), sparse[dim].data(), capsule); + auto coords = self.getCoordinates().data(); + for(auto dim = 0u; dim < self.dimensions.size(); ++dim) { + auto vec = py::array(coords[dim].size(), coords[dim].data(), capsule); outer.append(vec); } return outer; }, - [](SDR &self, SDR_sparse_t data) { + [](SDR &self, SDR_coordinate_t data) { NTA_CHECK( data.size() == self.dimensions.size() ); - self.setSparse( data ); }, -R"(List of numpy arrays, containing the indices of only the true values in the -SDR. This is a list of lists: the outter list contains an entry for each + self.setCoordinates( data ); }, +R"(List of numpy arrays, containing the coordinates of only the true values in +the SDR. This is a list of lists: the outter 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.)"); @@ -301,8 +300,8 @@ Example Usage: # Convert SDR dimensions from (4 x 4) to (8 x 2) A = SDR([ 4, 4 ]) B = SDR_Proxy( A, [8, 2]) - A.sparse = ([1, 1, 2], [0, 1, 2]) - B.sparse -> ([2, 2, 5], [0, 1, 0]) + A.coordinates = ([1, 1, 2], [0, 1, 2]) + B.coordinates -> ([2, 2, 5], [0, 1, 0]) SDR_Proxy supports pickle, however loading a pickled SDR proxy will return an SDR, not an SDR_Proxy.)"); @@ -326,12 +325,12 @@ Example Usage: # Setup 2 SDRs to hold the inputs. A = SDR( 10 ) B = SDR( 10 ) - A.flatSparse = [2, 3, 4, 5] - B.flatSparse = [0, 1, 2, 3] + A.sparse = [2, 3, 4, 5] + B.sparse = [0, 1, 2, 3] # Calculate the logical intersection X = SDR_Intersection(A, B) - X.flatSparse -> [2, 3] + X.sparse -> [2, 3] # Assignments to the input SDRs are propigated to the SDR_Intersection B.zero() diff --git a/src/examples/mnist/MNIST_SP.cpp b/src/examples/mnist/MNIST_SP.cpp index 454adac094..b892a21898 100644 --- a/src/examples/mnist/MNIST_SP.cpp +++ b/src/examples/mnist/MNIST_SP.cpp @@ -118,7 +118,7 @@ void train() { input.setDense( image ); sp.compute(input, true, columns); ClassifierResult result; - clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), + clsr.compute(sp.getIterationNum(), columns.getSparse(), /* bucketIdxList */ {label}, /* actValueList */ {(Real)label}, /* category */ true, @@ -150,7 +150,7 @@ void test() { sp.compute(input, false, columns); sp.stripUnlearnedColumns(columns); ClassifierResult result; - clsr.compute(sp.getIterationNum(), columns.getFlatSparse(), + clsr.compute(sp.getIterationNum(), columns.getSparse(), /* bucketIdxList */ {}, /* actValueList */ {}, /* category */ true, diff --git a/src/nupic/algorithms/SpatialPooler.cpp b/src/nupic/algorithms/SpatialPooler.cpp index 6abf03c2bb..e99dabf250 100644 --- a/src/nupic/algorithms/SpatialPooler.cpp +++ b/src/nupic/algorithms/SpatialPooler.cpp @@ -504,12 +504,12 @@ void SpatialPooler::compute(SDR &input, bool learn, SDR &active) { boostOverlaps_(overlaps_, boostedOverlaps_); - auto &activeVector = active.getFlatSparse(); + auto &activeVector = active.getSparse(); inhibitColumns_(boostedOverlaps_, activeVector); // Notify the active SDR that its internal data vector has changed. Always // call SDR's setter methods even if when modifying the SDR's own data // inplace. - active.setFlatSparse( activeVector ); + active.setSparse( activeVector ); if (learn) { adaptSynapses_(input, active); @@ -533,7 +533,7 @@ void SpatialPooler::stripUnlearnedColumns(UInt activeArray[]) const { // performs activeColumns AND current-round learned columns: active & activeDutyCyc_ void SpatialPooler::stripUnlearnedColumns(SDR& active) const { - auto sparseCols = active.getFlatSparse(); + auto sparseCols = active.getSparse(); vector res; res.reserve(sparseCols.size()); @@ -543,7 +543,7 @@ void SpatialPooler::stripUnlearnedColumns(SDR& active) const { } } //update original SDR with changed values - active.setFlatSparse(res); + active.setSparse(res); } @@ -697,12 +697,12 @@ void SpatialPooler::updateDutyCycles_(const vector &overlaps, // Turn the overlaps array into an SDR. Convert directly to flat-sparse to // avoid copies and type convertions. SDR newOverlap({ numColumns_ }); - auto &overlapsSparseVec = newOverlap.getFlatSparse(); + auto &overlapsSparseVec = newOverlap.getSparse(); for (UInt i = 0; i < numColumns_; i++) { if( overlaps[i] != 0 ) overlapsSparseVec.push_back( i ); } - newOverlap.setFlatSparse( overlapsSparseVec ); + newOverlap.setSparse( overlapsSparseVec ); const UInt period = std::min(dutyCyclePeriod_, iterationNum_); @@ -760,7 +760,7 @@ Real SpatialPooler::avgConnectedSpanForColumnND_(UInt column) const { void SpatialPooler::adaptSynapses_(SDR &input, SDR &active) { - for(const auto &column : active.getFlatSparse()) { + for(const auto &column : active.getSparse()) { connections_.adaptSegment(column, input, synPermActiveInc_, synPermInactiveDec_); connections_.raisePermanencesToThreshold( column, synPermConnected_, stimulusThreshold_); @@ -795,7 +795,7 @@ void SpatialPooler::updateDutyCyclesHelper_(vector &dutyCycles, dutyCycles[i] *= decay; const Real increment = 1.0f / period; // All non-zero values are 1. - for(const auto &idx : newValues.getFlatSparse()) + for(const auto &idx : newValues.getSparse()) dutyCycles[idx] += increment; } @@ -863,7 +863,7 @@ void SpatialPooler::updateBookeepingVars_(bool learn) { void SpatialPooler::calculateOverlap_(SDR &input, vector &overlaps) const { overlaps.assign( numColumns_, 0 ); - connections_.computeActivity(overlaps, input.getFlatSparse()); + connections_.computeActivity(overlaps, input.getSparse()); } diff --git a/src/nupic/algorithms/TemporalMemory.cpp b/src/nupic/algorithms/TemporalMemory.cpp index 8172a64b23..6cdc09db83 100644 --- a/src/nupic/algorithms/TemporalMemory.cpp +++ b/src/nupic/algorithms/TemporalMemory.cpp @@ -449,7 +449,7 @@ static void punishPredictedColumn( void TemporalMemory::activateCells(const SDR &activeColumns, bool learn) { NTA_CHECK( activeColumns.dimensions == columnDimensions_ ); - const auto &sparse = activeColumns.getFlatSparse(); + const auto &sparse = activeColumns.getSparse(); activateCells(sparse.size(), sparse.data(), learn); } @@ -528,8 +528,8 @@ void TemporalMemory::activateDendrites(bool learn, { NTA_CHECK( extraActive.size == numberOfCells() ); NTA_CHECK( extraWinners.size == numberOfCells() ); - activateDendrites( learn, extraActive.getFlatSparse(), - extraWinners.getFlatSparse()); + activateDendrites( learn, extraActive.getSparse(), + extraWinners.getSparse()); } else { @@ -675,7 +675,7 @@ vector TemporalMemory::getActiveCells() const { return activeCells_; } void TemporalMemory::getActiveCells(SDR &activeCells) const { NTA_CHECK( activeCells.size == numberOfCells() ); - activeCells.setFlatSparse( getActiveCells() ); + activeCells.setSparse( getActiveCells() ); } vector TemporalMemory::getPredictiveCells() const { @@ -699,7 +699,7 @@ vector TemporalMemory::getPredictiveCells() const { void TemporalMemory::getPredictiveCells(SDR &predictiveCells) const { NTA_CHECK( predictiveCells.size == numberOfCells() ); - predictiveCells.setFlatSparse( getPredictiveCells() ); + predictiveCells.setSparse( getPredictiveCells() ); } vector TemporalMemory::getWinnerCells() const { return winnerCells_; } @@ -707,7 +707,7 @@ vector TemporalMemory::getWinnerCells() const { return winnerCells_; } void TemporalMemory::getWinnerCells(SDR &winnerCells) const { NTA_CHECK( winnerCells.size == numberOfCells() ); - winnerCells.setFlatSparse( getWinnerCells() ); + winnerCells.setSparse( getWinnerCells() ); } vector TemporalMemory::getActiveSegments() const diff --git a/src/nupic/regions/SPRegion.cpp b/src/nupic/regions/SPRegion.cpp index fe303f74bb..0d20344877 100644 --- a/src/nupic/regions/SPRegion.cpp +++ b/src/nupic/regions/SPRegion.cpp @@ -748,10 +748,10 @@ size_t SPRegion::getParameterArrayCount(const std::string &name, Int64 index) { } else if (name == "spatialPoolerOutput") { return getOutput("bottomUpOut")->getData().getCount(); } else if (name == "spInputNonZeros") { - const SDR_flatSparse_t& v = getInput("bottomUpIn")->getData().getSDR()->getFlatSparse(); + const SDR_sparse_t& v = getInput("bottomUpIn")->getData().getSDR()->getSparse(); return v.size(); } else if (name == "spOutputNonZeros") { - const SDR_flatSparse_t& v = getInput("bottomUpOut")->getData().getSDR()->getFlatSparse(); + const SDR_sparse_t& v = getInput("bottomUpOut")->getData().getSDR()->getSparse(); return v.size(); } return 0; diff --git a/src/nupic/types/Sdr.cpp b/src/nupic/types/Sdr.cpp index 275079e53c..9f05c235c9 100644 --- a/src/nupic/types/Sdr.cpp +++ b/src/nupic/types/Sdr.cpp @@ -17,6 +17,9 @@ /** @file * Implementation of the SparseDistributedRepresentation class + * Also Known As "SDR" class + * + * SDR implementation in C++, refer to Sdr.hpp for detailed comments. */ #include "nupic/types/Sdr.hpp" @@ -27,17 +30,11 @@ using namespace std; namespace nupic { -// SDR implementation in .cpp, refer to .hpp for detailed comments - -/** - * SparseDistributedRepresentation class - * Also known as "SDR" class - */ void SparseDistributedRepresentation::clear() const { - dense_valid = false; - flatSparse_valid = false; - sparse_valid = false; + dense_valid = false; + sparse_valid = false; + coordinates_valid = false; } void SparseDistributedRepresentation::do_callbacks() const { @@ -56,36 +53,36 @@ namespace nupic { do_callbacks(); } - void SparseDistributedRepresentation::setFlatSparseInplace() const { + void SparseDistributedRepresentation::setSparseInplace() const { // Check data is valid. #ifdef NTA_ASSERTIONS_ON - NTA_ASSERT(flatSparse_.size() <= size); - for(auto idx : flatSparse_) { + NTA_ASSERT(sparse_.size() <= size); + for(auto idx : sparse_) { NTA_ASSERT(idx < size); } #endif // Set the valid flags. clear(); - flatSparse_valid = true; + sparse_valid = true; do_callbacks(); } - void SparseDistributedRepresentation::setSparseInplace() const { + void SparseDistributedRepresentation::setCoordinatesInplace() const { // Check data is valid. #ifdef NTA_ASSERTIONS_ON - NTA_ASSERT(sparse_.size() == dimensions.size()); + NTA_ASSERT(coordinates_.size() == dimensions.size()); for(UInt dim = 0; dim < dimensions.size(); dim++) { - const auto coord_vec = sparse_[dim]; + const auto &coord_vec = coordinates_[dim]; NTA_ASSERT(coord_vec.size() <= size); - NTA_ASSERT(coord_vec.size() == sparse_[0].size()); // All coordinate vectors have same size. - for(auto idx : coord_vec) { + NTA_ASSERT(coord_vec.size() == coordinates_[0].size()); // All coordinate vectors have same size. + for(const auto &idx : coord_vec) { NTA_ASSERT(idx < dimensions[dim]); } } #endif // Set the valid flags. clear(); - sparse_valid = true; + coordinates_valid = true; do_callbacks(); } @@ -124,37 +121,37 @@ namespace nupic { // Initialize the dense array storage, when it's needed. dense_valid = false; // Initialize the flatSparse array, nothing to do. - flatSparse_valid = true; - // Initialize the index tuple. - sparse_.assign( dimensions.size(), {} ); sparse_valid = true; + // Initialize the index tuple. + coordinates_.assign( dimensions.size(), {} ); + coordinates_valid = true; } - SparseDistributedRepresentation::SparseDistributedRepresentation( const SparseDistributedRepresentation &value ) + SparseDistributedRepresentation::SparseDistributedRepresentation( + const SparseDistributedRepresentation &value ) : SparseDistributedRepresentation( value.dimensions ) { setSDR( value ); } SparseDistributedRepresentation::~SparseDistributedRepresentation() { deconstruct(); } - void SparseDistributedRepresentation::zero() { - flatSparse_.clear(); - setFlatSparseInplace(); + sparse_.clear(); + setSparseInplace(); } + void SparseDistributedRepresentation::setDense( SDR_dense_t &value ) { NTA_ASSERT(value.size() == size); dense_.swap( value ); setDenseInplace(); } - SDR_dense_t& SparseDistributedRepresentation::getDense() const { if( !dense_valid ) { // Convert from flatSparse to dense. dense_.assign( size, 0 ); - for(const auto idx : getFlatSparse()) { + for(const auto &idx : getSparse()) { dense_[idx] = 1; } dense_valid = true; @@ -164,36 +161,38 @@ namespace nupic { Byte SparseDistributedRepresentation::at(const vector &coordinates) const { UInt flat = 0; - NTA_ASSERT(coordinates.size() == dimensions.size()) << "SDR: coordinates must have same dimensions as SDR"; + NTA_ASSERT(coordinates.size() == dimensions.size()) + << "SDR::at() coordinates must have same dimensions as SDR!"; for(UInt i = 0; i < dimensions.size(); i++) { - NTA_ASSERT( coordinates[i] < dimensions[i] ); + NTA_ASSERT( coordinates[i] < dimensions[i] ) + << "SDR::at() coordinates out of bounds!"; flat *= dimensions[i]; flat += coordinates[i]; } return getDense()[flat]; } - void SparseDistributedRepresentation::setFlatSparse( SDR_flatSparse_t &value ) { - flatSparse_.swap( value ); - setFlatSparseInplace(); - } + void SparseDistributedRepresentation::setSparse( SDR_sparse_t &value ) { + sparse_.swap( value ); + setSparseInplace(); + } - SDR_flatSparse_t& SparseDistributedRepresentation::getFlatSparse() const { - if( !flatSparse_valid ) { - flatSparse_.clear(); // Clear out any old data. - if( sparse_valid ) { - // Convert from sparse to flatSparse. - const auto &sparse = getSparse(); - const auto num_nz = size ? sparse[0].size() : 0; - flatSparse_.reserve( num_nz ); - for(UInt nz = 0; nz < num_nz; nz++) { + SDR_sparse_t& SparseDistributedRepresentation::getSparse() const { + if( !sparse_valid ) { + sparse_.clear(); // Clear out any old data. + if( coordinates_valid ) { + // Convert from coordinates to flat-sparse. + const auto &coords = getCoordinates(); + const auto num_nz = size ? coords[0].size() : 0u; + sparse_.reserve( num_nz ); + for(UInt nz = 0; nz < num_nz; ++nz) { UInt flat = 0; - for(UInt dim = 0; dim < dimensions.size(); dim++) { + for(UInt dim = 0; dim < dimensions.size(); ++dim) { flat *= dimensions[dim]; - flat += sparse[dim][nz]; + flat += coords[dim][nz]; } - flatSparse_.push_back(flat); + sparse_.push_back(flat); } } else if( dense_valid ) { @@ -201,39 +200,39 @@ namespace nupic { const auto &dense = getDense(); for(UInt idx = 0; idx < size; idx++) if( dense[idx] != 0 ) - flatSparse_.push_back( idx ); + sparse_.push_back( idx ); } else NTA_THROW << "SDR has no data!"; - flatSparse_valid = true; + sparse_valid = true; } - return flatSparse_; + return sparse_; } - void SparseDistributedRepresentation::setSparse( SDR_sparse_t &value ) { - sparse_.swap( value ); - setSparseInplace(); - } + void SparseDistributedRepresentation::setCoordinates( SDR_coordinate_t &value ) { + coordinates_.swap( value ); + setCoordinatesInplace(); + } - SDR_sparse_t& SparseDistributedRepresentation::getSparse() const { - if( !sparse_valid ) { + SDR_coordinate_t& SparseDistributedRepresentation::getCoordinates() const { + if( !coordinates_valid ) { // Clear out any old data. - for( auto& vec : sparse_ ) { + for( auto& vec : coordinates_ ) { vec.clear(); } - // Convert from flatSparse to sparse. - for( auto idx : getFlatSparse() ) { - for(UInt dim = (UInt)(dimensions.size() - 1); dim > 0; dim--) { - auto dim_sz = dimensions[dim]; - sparse_[dim].push_back( idx % dim_sz ); + // Convert from sparse to coordinates. + for( auto idx : getSparse() ) { + for(UInt dim = (UInt)(dimensions.size() - 1); dim > 0; --dim) { + const auto dim_sz = dimensions[dim]; + coordinates_[dim].push_back( idx % dim_sz ); idx /= dim_sz; } - sparse_[0].push_back(idx); + coordinates_[0].push_back(idx); } - sparse_valid = true; + coordinates_valid = true; } - return sparse_; + return coordinates_; } @@ -245,21 +244,20 @@ namespace nupic { if( dense_valid ) { dense_.assign( value.dense_.begin(), value.dense_.end() ); } - flatSparse_valid = value.flatSparse_valid; - if( flatSparse_valid ) { - flatSparse_.assign( value.flatSparse_.begin(), value.flatSparse_.end() ); - } sparse_valid = value.sparse_valid; if( sparse_valid ) { + sparse_.assign( value.sparse_.begin(), value.sparse_.end() ); + } + coordinates_valid = value.coordinates_valid; + if( coordinates_valid ) { for(UInt dim = 0; dim < dimensions.size(); dim++) - sparse_[dim].assign( value.sparse_[dim].begin(), value.sparse_[dim].end() ); + coordinates_[dim].assign( value.coordinates_[dim].begin(), value.coordinates_[dim].end() ); } - // method. Subclasses may override these getters and ignore the valid - // flags... - if( !dense_valid and !flatSparse_valid and !sparse_valid ) { - const auto data = value.getFlatSparse(); - flatSparse_.assign( data.begin(), data.end() ); - flatSparse_valid = true; + // Subclasses may override these getters and ignore the valid flags... + if( !dense_valid and !sparse_valid and !coordinates_valid ) { + const auto data = value.getSparse(); + sparse_.assign( data.begin(), data.end() ); + sparse_valid = true; } do_callbacks(); } @@ -282,17 +280,16 @@ namespace nupic { randomize( sparsity, rng ); } - void SparseDistributedRepresentation::randomize(Real sparsity, Random &rng) { NTA_ASSERT( sparsity >= 0.0f and sparsity <= 1.0f ); UInt nbits = (UInt) std::round( size * sparsity ); - SDR_flatSparse_t range( size ); - iota( range.begin(), range.end(), 0 ); - flatSparse_.resize( nbits ); + SDR_sparse_t range( size ); + iota( range.begin(), range.end(), 0u ); + sparse_.resize( nbits ); rng.sample( range.data(), size, - flatSparse_.data(), nbits); - setFlatSparseInplace(); + sparse_.data(), nbits); + setSparseInplace(); } @@ -301,7 +298,6 @@ namespace nupic { addNoise( fractionNoise, rng ); } - void SparseDistributedRepresentation::addNoise(Real fractionNoise, Random &rng) { NTA_ASSERT( fractionNoise >= 0. and fractionNoise <= 1. ); NTA_CHECK( ( 1 + fractionNoise) * getSparsity() <= 1. ); @@ -309,7 +305,7 @@ namespace nupic { UInt num_move_bits = (UInt) std::round( fractionNoise * getSum() ); vector turn_off( num_move_bits , 0 ); rng.sample( - (UInt*) getFlatSparse().data(), getSum(), + (UInt*) getSparse().data(), getSum(), (UInt*) turn_off.data(), num_move_bits); auto& dns = getDense(); @@ -366,12 +362,11 @@ namespace nupic { writeVector( dimensions ); // Store the data in the flat-sparse format. - writeVector( getFlatSparse() ); + writeVector( getSparse() ); outStream << "~SDR" << endl; } - void SparseDistributedRepresentation::load(std::istream &inStream) { auto readVector = [&inStream] (vector &vec) { //TODO add to Serializable @@ -379,7 +374,7 @@ namespace nupic { UInt size; inStream >> size; vec.reserve( size ); - for( UInt i = 0; i < size; i++ ) { + for( UInt i = 0; i < size; ++i ) { UInt elem; inStream >> elem; vec.push_back( elem ); @@ -402,11 +397,11 @@ namespace nupic { for(UInt dim : dimensions) size_ *= dim; // Initialize sparse tuple. - sparse_.assign( dimensions.size(), {} ); + coordinates_.assign( dimensions.size(), {} ); // Read the data. - readVector( flatSparse_ ); - setFlatSparseInplace(); + readVector( sparse_ ); + setSparseInplace(); // Consume the end marker. inStream >> marker; @@ -427,7 +422,6 @@ namespace nupic { return index; } - void SparseDistributedRepresentation::removeCallback(UInt index) { NTA_CHECK( index < callbacks.size() ) << "SparseDistributedRepresentation::removeCallback, Invalid Handle!"; @@ -449,7 +443,6 @@ namespace nupic { return index; } - void SparseDistributedRepresentation::removeDestroyCallback(UInt index) { NTA_CHECK( index < destroyCallbacks.size() ) << "SparseDistributedRepresentation::removeDestroyCallback, Invalid Handle!"; diff --git a/src/nupic/types/Sdr.hpp b/src/nupic/types/Sdr.hpp index 1eca332416..8b11ae2860 100644 --- a/src/nupic/types/Sdr.hpp +++ b/src/nupic/types/Sdr.hpp @@ -36,8 +36,8 @@ using namespace std; namespace nupic { typedef vector SDR_dense_t; -typedef vector SDR_flatSparse_t; -typedef vector> SDR_sparse_t; +typedef vector SDR_sparse_t; +typedef vector> SDR_coordinate_t; typedef function SDR_callback_t; /** @@ -50,7 +50,7 @@ typedef function SDR_callback_t; * represent the state of a group of neurons or their associated processes. * * This class automatically converts between the commonly used SDR data formats: - * which are dense, sparse, and flat-sparse. Converted values are cached by + * which are dense, sparse, and coordinates. Converted values are cached by * this class, so getting a value in one format many times incurs no extra * performance cost. Assigning to the SDR via a setter method will clear these * cached values and cause them to be recomputed as needed. @@ -59,19 +59,19 @@ typedef function SDR_callback_t; * the bits in the SDR. This format allows random-access queries of the SDRs * values. * - * Sparse Flat Index Format: Contains the indices of only the true values in + * Sparse Index Format: Contains the indices of only the true values in * the SDR. This is a list of the indices, indexed into the flattened SDR. * This format allows for quickly accessing all of the true bits in the SDR. * - * Sparse Index Format: Contains the indices of only the true values in the - * SDR. This is a list of lists: the outter 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. + * Coordinate Format: Contains the indices of only the true values in the + * SDR. This is a list of lists: the outter list contains an entry for each + * dimension in the SDR. The inner lists contain the coordinates of each true + * bit in that dimension. 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. * - * Flat Formats: This class uses C-order throughout, meaning that when iterating - * through the SDR, the last/right-most index changes fastest. + * Array Memory Layout: This class uses C-order throughout, meaning that when + * iterating through the SDR, the last/right-most index changes fastest. * * Example usage: * @@ -83,19 +83,19 @@ typedef function SDR_callback_t; * X.setDense({ 0, 1, 0, * 0, 1, 0, * 0, 0, 1 }); - * X.setFlatSparse({ 1, 4, 8 }); - * X.setSparse({{ 0, 1, 2,}, { 1, 1, 2 }}); + * X.setSparse({ 1, 4, 8 }); + * X.setCoordinates({{ 0, 1, 2,}, { 1, 1, 2 }}); * * // Access data in any format, SDR will automatically convert data formats. - * X.getDense() -> { 0, 1, 0, 0, 1, 0, 0, 0, 1 } - * X.getSparse() -> {{ 0, 1, 2 }, {1, 1, 2}} - * x.getFlatSparse() -> { 1, 4, 8 } + * X.getDense() -> { 0, 1, 0, 0, 1, 0, 0, 0, 1 } + * X.getCoordinates() -> {{ 0, 1, 2 }, {1, 1, 2}} + * x.getSparse() -> { 1, 4, 8 } * * // Data format conversions are cached, and when an SDR value changes the * // cache is cleared. - * X.setFlatSparse({}); // Assign new data to the SDR, clearing the cache. - * X.getDense(); // This line will convert formats. - * X.getDense(); // This line will resuse the result of the previous line + * X.setSparse({}); // Assign new data to the SDR, clearing the cache. + * X.getDense(); // This line will convert formats. + * X.getDense(); // This line will resuse the result of the previous line * * * Avoiding Copying: To avoid copying call the setter methods with the correct @@ -104,11 +104,11 @@ typedef function SDR_callback_t; * can be modified and reassigned to the SDR, or the caller can allocate their * own data vectors as one of the following types: * vector aka SDR_dense_t - * vector aka SDR_flatSparse_t - * vector> aka SDR_sparse_t + * vector aka SDR_sparse_t + * vector> aka SDR_coordinate_t * - * Example Usage: - * X.zero(); + * Example Usage With Out Copying: + * SDR X( {3, 3} ); * SDR_dense_t newData({ 1, 0, 0, 1, 0, 0, 1, 0, 0 }); * X.setDense( newData ); * // X now points to newData, and newData points to X's old data. @@ -119,7 +119,7 @@ typedef function SDR_callback_t; * dense[2] = true; * // Notify the SDR of the changes, even if using the SDR's own data inplace. * X.setDense( dense ); - * X.getFlatSparse() -> { 2 } + * X.getSparse() -> { 2 } */ class SparseDistributedRepresentation : public Serializable { @@ -128,19 +128,21 @@ class SparseDistributedRepresentation : public Serializable UInt size_; protected: - // internal representation in given data format (not all must match at a time), - // see *_valid below + /** + * Internal representations in each data format. Not all must match at a + * time, see *_valid below. + */ mutable SDR_dense_t dense_; - mutable SDR_flatSparse_t flatSparse_; mutable SDR_sparse_t sparse_; + mutable SDR_coordinate_t coordinates_; /** * These flags remember which data formats are up-to-date and which formats * need to be updated. */ mutable bool dense_valid; - mutable bool flatSparse_valid; mutable bool sparse_valid; + mutable bool coordinates_valid; private: /** @@ -172,23 +174,23 @@ class SparseDistributedRepresentation : public Serializable /** * Update the SDR to reflect the value currently inside of the dense array. * Use this method after modifying the dense buffer inplace, in order to - * propigate any changes to the sparse & flatSparse formats. + * propigate any changes to the sparse & coordinate formats. */ virtual void setDenseInplace() const; /** * Update the SDR to reflect the value currently inside of the flatSparse * vector. Use this method after modifying the flatSparse vector inplace, in - * order to propigate any changes to the dense & sparse formats. + * order to propigate any changes to the dense & coordinate formats. */ - virtual void setFlatSparseInplace() const; + virtual void setSparseInplace() const; /** * Update the SDR to reflect the value currently inside of the sparse * vector. Use this method after modifying the sparse vector inplace, in - * order to propigate any changes to the dense & flatSparse formats. + * order to propigate any changes to the dense & sparse formats. */ - virtual void setSparseInplace() const; + virtual void setCoordinatesInplace() const; /** * Destroy this SDR. Makes SDR unusable, should error or clearly fail if @@ -261,7 +263,6 @@ class SparseDistributedRepresentation : public Serializable setDense(value.data()); } - /** * Copy a new value into the SDR, overwritting the current value. * @@ -303,8 +304,7 @@ class SparseDistributedRepresentation : public Serializable * * @param value A sparse vector to swap into the SDR. */ - void setFlatSparse( SDR_flatSparse_t &value ); - + void setSparse( SDR_sparse_t &value ); /** * Copy a vector of sparse indices of true values. These indicies are into @@ -313,12 +313,11 @@ class SparseDistributedRepresentation : public Serializable * @param value A vector of flat indices to copy into the SDR. */ template - void setFlatSparse( const vector &value ) { - flatSparse_.assign( value.begin(), value.end() ); - setFlatSparseInplace(); + void setSparse( const vector &value ) { + sparse_.assign( value.begin(), value.end() ); + setSparseInplace(); } - /** * Copy an array of sparse indices of true values. These indicies are into * the flattened SDR space. This overwrites the SDR's current value. @@ -327,73 +326,71 @@ class SparseDistributedRepresentation : public Serializable * @param num_values The number of elements in the 'value' array. */ template - void setFlatSparse( const T *value, const UInt num_values ) { - flatSparse_.assign( value, value + num_values ); - setFlatSparseInplace(); + void setSparse( const T *value, const UInt num_values ) { + sparse_.assign( value, value + num_values ); + setSparseInplace(); } - /** * Gets the current value of the SDR. The result of this method call is * saved inside of this SDR until the SDRs value changes. After modifying - * the flatSparse vector you MUST call sdr.setFlatSparse() in order to - * notify the SDR that its flatSparse vector has changed and its cached data - * is out of date. + * the sparse vector you MUST call sdr.setSparse() in order to notify the + * SDR that its flatSparse vector has changed and its cached data is out of + * date. * * @returns A reference to a vector of the indices of the true values in the * flattened SDR. */ - virtual SDR_flatSparse_t& getFlatSparse() const; + virtual SDR_sparse_t& getSparse() const; /** - * Swap a list of indices into the SDR, replacing the SDRs current value. - * These indices are into the SDR space with dimensions. The outter list is - * indexed using an index into the sdr.dimensions list. The inner lists are - * indexed in parallel, they contain the coordinates of the true values in + * Swap a list of coordinates into the SDR, replacing the SDRs current + * value. These are indices into the SDR space with dimensions. This + * accepts a list of lists, containing the coordinates of the true values in * the SDR. * * This method is fast since it swaps the vector content, however it does * modify its argument! * - * @param value A vector> containing the coordinates of the - * true values to swap into the SDR. + * @param value A vector> containing the coordinates of the true + * values to swap into the SDR. The outter list is indexed using an index + * into the sdr.dimensions list. The inner lists are indexed in parallel. */ - void setSparse( SDR_sparse_t &value ); + void setCoordinates( SDR_coordinate_t &value ); /** - * Copy a list of indices into the SDR, overwritting the SDRs current value. - * These indices are into the SDR space with dimensions. The outter list is - * indexed using an index into the sdr.dimensions list. The inner lists are - * indexed in parallel, they contain the coordinates of the true values in + * Copy a list of coordinates into the SDR, overwritting the SDRs current + * value. These are indices into the SDR space with dimensions. This + * accepts a list of lists, containing the coordinates of the true values in * the SDR. * * @param value A list of lists containing the coordinates of the true - * values to copy into the SDR. + * values to copy into the SDR. The outter list is indexed using an index + * into the sdr.dimensions list. The inner lists are indexed in parallel. */ template - void setSparse( const vector> &value ) { + void setCoordinates( const vector> &value ) { NTA_ASSERT(value.size() == dimensions.size()); for(UInt dim = 0; dim < dimensions.size(); dim++) { - sparse_[dim].clear(); - sparse_[dim].resize(value[dim].size()); + coordinates_[dim].clear(); + coordinates_[dim].resize(value[dim].size()); + // Use an explicit type cast. Otherwise Microsoft Visual Studio will + // print an excessive number of warnings. Do NOT replace this with: + // coordinates_[dim].assign(value[dim].cbegin(), value[dim].cend()); for (UInt i = 0; i < value[dim].size(); i++) - sparse_[dim][i] = (UInt)value[dim][i]; - // you will probably want to do this differently... - // but I need to explictly cast during the copy. - //sparse_[dim].assign(value[dim].cbegin(), value[dim].cend()); + coordinates_[dim][i] = (UInt)value[dim][i]; } - setSparseInplace(); + setCoordinatesInplace(); } - /** * Gets the current value of the SDR. The result of this method call is * saved inside of this SDR until the SDRs value changes. * * @returns A reference to a list of lists which contain the coordinates of - * the true values in the SDR. + * the true values in the SDR. */ - virtual SDR_sparse_t& getSparse() const; + virtual SDR_coordinate_t& getCoordinates() const; /** * Deep Copy the given SDR to this SDR. This overwrites the current value of @@ -410,7 +407,7 @@ class SparseDistributedRepresentation : public Serializable * @returns The number of true values in the SDR. */ inline UInt getSum() const - { return (UInt)getFlatSparse().size(); } + { return (UInt)getSparse().size(); } /** * Calculates the sparsity of the SDR, which is the fraction of bits which @@ -474,7 +471,7 @@ class SparseDistributedRepresentation : public Serializable stream << ", "; } stream << " ) "; - auto data = sdr.getFlatSparse(); + auto data = sdr.getSparse(); std::sort( data.begin(), data.end() ); for( UInt i = 0; i < data.size(); i++ ) { stream << data[i]; diff --git a/src/nupic/types/SdrProxy.hpp b/src/nupic/types/SdrProxy.hpp index 395eaddd68..e9e1a284ca 100644 --- a/src/nupic/types/SdrProxy.hpp +++ b/src/nupic/types/SdrProxy.hpp @@ -44,10 +44,10 @@ class SDR_ReadOnly_ : public SDR void setDenseInplace() const override { NTA_THROW << _error_message; } - void setFlatSparseInplace() const override - { NTA_THROW << _error_message; } void setSparseInplace() const override { NTA_THROW << _error_message; } + void setCoordinatesInplace() const override + { NTA_THROW << _error_message; } void setSDR( const SparseDistributedRepresentation &value ) override { NTA_THROW << _error_message; } void load(std::istream &inStream) override @@ -74,8 +74,8 @@ class SDR_ReadOnly_ : public SDR * // Convert SDR dimensions from (4 x 4) to (8 x 2) * SDR A( { 4, 4 }) * SDR_Proxy B( A, { 8, 2 }) - * A.setSparse( {1, 1, 2}, {0, 1, 2}} ) - * auto sparse = B.getSparse() -> {{2, 2, 5}, {0, 1, 0}} + * A.setCoordinates( {1, 1, 2}, {0, 1, 2}} ) + * B.getCoordinates() -> {{2, 2, 5}, {0, 1, 0}} * * SDR_Proxy partially supports the Serializable interface. SDR_Proxies can be * saved but can not be loaded. @@ -118,24 +118,24 @@ class SDR_Proxy : public SDR_ReadOnly_ return parent->getDense(); } - SDR_flatSparse_t& getFlatSparse() const override { + SDR_sparse_t& getSparse() const override { NTA_CHECK( parent != nullptr ) << "Parent SDR has been destroyed!"; - return parent->getFlatSparse(); + return parent->getSparse(); } - SDR_sparse_t& getSparse() const override { + SDR_coordinate_t& getCoordinates() const override { NTA_CHECK( parent != nullptr ) << "Parent SDR has been destroyed!"; if( dimensions.size() == parent->dimensions.size() && equal( dimensions.begin(), dimensions.end(), parent->dimensions.begin() )) { // All things equal, prefer reusing the parent's cached value. - return parent->getSparse(); + return parent->getCoordinates(); } else { - // Don't override getSparse(). It will call either getDense() or - // getFlatSparse() to get its data, and will use this proxies + // Don't override getCoordinates(). It will call either getDense() or + // getSparse() to get its data, and will use this proxies // dimensions. - return SDR::getSparse(); + return SDR::getCoordinates(); } } @@ -326,12 +326,12 @@ class SDR_Concatenation : public SDR_ReadOnly_ * // Setup 2 SDRs to hold the inputs. * SDR A({ 10 }); * SDR B({ 10 }); - * A.setFlatSparse( {2, 3, 4, 5}); - * B.setFlatSparse({0, 1, 2, 3}); + * A.setSparse( {2, 3, 4, 5}); + * B.setSparse({0, 1, 2, 3}); * * // Calculate the logical intersection * SDR_Intersection X(A, B); - * X.getFlatSparse() -> {2, 3} + * X.getSparse() -> {2, 3} * * // Assignments to the input SDRs are propigated to the SDR_Intersection * B.zero(); diff --git a/src/nupic/utils/SdrMetrics.hpp b/src/nupic/utils/SdrMetrics.hpp index b364e27819..97da50a6c8 100644 --- a/src/nupic/utils/SdrMetrics.hpp +++ b/src/nupic/utils/SdrMetrics.hpp @@ -252,7 +252,7 @@ class SDR_ActivationFrequency : public SDR_MetricsHelper_ { for(auto &value : activationFrequency_) value *= decay; - const auto &sparse = dataSource.getFlatSparse(); + const auto &sparse = dataSource.getSparse(); for(const auto &idx : sparse) activationFrequency_[idx] += alpha; } @@ -398,7 +398,7 @@ class SDR_Overlap : public SDR_MetricsHelper_ { max_ = -1234.56789f; mean_ = 1234.56789f; variance_ = 1234.56789f; - previous_.getFlatSparse(); + previous_.getSparse(); } void callback(SDR &dataSource, Real alpha) override { diff --git a/src/test/unit/algorithms/SpatialPoolerTest.cpp b/src/test/unit/algorithms/SpatialPoolerTest.cpp index 9fed69fa58..ebe90bffa0 100644 --- a/src/test/unit/algorithms/SpatialPoolerTest.cpp +++ b/src/test/unit/algorithms/SpatialPoolerTest.cpp @@ -813,7 +813,7 @@ TEST(SpatialPoolerTest, testAdaptSynapses) { SDR input1({8}); input1.setDense(SDR_dense_t{1, 0, 0, 1, 1, 0, 1, 0}); - activeColumns.setFlatSparse(SDR_flatSparse_t({ 0, 1, 2 })); + activeColumns.setSparse(SDR_sparse_t({ 0, 1, 2 })); for (UInt column = 0; column < numColumns; column++) { sp.setPotential(column, potentialArr1[column]); @@ -858,7 +858,7 @@ TEST(SpatialPoolerTest, testAdaptSynapses) { sp.setPermanence(column, permanencesArr2[column]); } - activeColumns.setFlatSparse(activeColumnsArr2, 3); + activeColumns.setSparse(activeColumnsArr2, 3); sp.adaptSynapses_(input2, activeColumns); for (UInt column = 0; column < numColumns; column++) { diff --git a/src/test/unit/algorithms/TemporalMemoryTest.cpp b/src/test/unit/algorithms/TemporalMemoryTest.cpp index 6392e3e54e..a34d3d7890 100644 --- a/src/test/unit/algorithms/TemporalMemoryTest.cpp +++ b/src/test/unit/algorithms/TemporalMemoryTest.cpp @@ -1548,7 +1548,7 @@ TEST(TemporalMemoryTest, testExtraActive) { Random rng( i + 99u ); // Use deterministic seeds for unit tests. auto &sdr = pattern[i]; sdr.randomize( 0.10f, rng ); - auto &data = sdr.getFlatSparse(); + auto &data = sdr.getSparse(); std::sort(data.begin(), data.end()); } @@ -1584,14 +1584,14 @@ TEST(TemporalMemoryTest, testExtraActive) { predictedColumns.erase( predictedColumns.begin() + i-- ); } // Calculate TM output - const auto &sparse = x.getFlatSparse(); + const auto &sparse = x.getSparse(); tm.compute(sparse.size(), sparse.data(), true); extraActive = tm.getActiveCells(); extraWinners = tm.getWinnerCells(); // Calculate Anomaly of current input based on prior predictions. anom = algorithms::anomaly::computeRawAnomalyScore( - x.getFlatSparse(), predictedColumns); + x.getSparse(), predictedColumns); } } ASSERT_LT( anom, 0.05f ); @@ -1605,7 +1605,7 @@ TEST(TemporalMemoryTest, testExtraActive) { auto predictedCells = tm.getPredictiveCells(); ASSERT_TRUE( predictedCells.empty() ); // No predictions, numActive < threshold // Calculate TM output - const auto &sparse = x.getFlatSparse(); + const auto &sparse = x.getSparse(); tm.compute(sparse.size(), sparse.data(), true); } } diff --git a/src/test/unit/ntypes/ArrayTest.cpp b/src/test/unit/ntypes/ArrayTest.cpp index 2c1c8b5105..d5ea1a53dc 100644 --- a/src/test/unit/ntypes/ArrayTest.cpp +++ b/src/test/unit/ntypes/ArrayTest.cpp @@ -579,7 +579,7 @@ TEST_F(ArrayTest, testArrayBasefunctions) { EXPECT_EQ(m.getCount(), 100u); std::vector row = a.asVector(); - SDR_flatSparse_t &v = a.getSDR()->getFlatSparse(); + SDR_sparse_t &v = a.getSDR()->getSparse(); EXPECT_EQ(v.size(), 10u); diff --git a/src/test/unit/types/SdrProxyTest.cpp b/src/test/unit/types/SdrProxyTest.cpp index faf9bbc322..ff019066de 100644 --- a/src/test/unit/types/SdrProxyTest.cpp +++ b/src/test/unit/types/SdrProxyTest.cpp @@ -26,9 +26,9 @@ using namespace nupic; TEST(SdrProxyTest, TestProxyExamples) { SDR A( { 4, 4 }); SDR_Proxy B( A, { 8, 2 }); - A.setSparse(SDR_sparse_t({{1, 1, 2}, {0, 1, 2}})); - auto sparse = B.getSparse(); - ASSERT_EQ(sparse, SDR_sparse_t({{2, 2, 5}, {0, 1, 0}})); + A.setCoordinates(SDR_coordinate_t({{1, 1, 2}, {0, 1, 2}})); + auto coords = B.getCoordinates(); + ASSERT_EQ(coords, SDR_coordinate_t({{2, 2, 5}, {0, 1, 0}})); } TEST(SdrProxyTest, TestProxyConstructor) { @@ -55,10 +55,10 @@ TEST(SdrProxyTest, TestProxyConstructor) { SDR_Proxy *K = new SDR_Proxy( A ); delete K; SDR_Proxy *L = new SDR_Proxy( A ); - L->getSparse(); + L->getCoordinates(); delete L; delete G; - I->getSparse(); + I->getCoordinates(); delete I; delete J; A.getDense(); @@ -75,21 +75,21 @@ TEST(SdrProxyTest, TestProxyDeconstructor) { SDR_Proxy *D = new SDR_Proxy( *C, {4, 3} ); SDR_Proxy *E = new SDR_Proxy( *C, {2, 6} ); D->getDense(); - E->getSparse(); + E->getCoordinates(); // Test subtree deletion delete C; ASSERT_ANY_THROW( D->getDense() ); - ASSERT_ANY_THROW( E->getSparse() ); + ASSERT_ANY_THROW( E->getCoordinates() ); ASSERT_ANY_THROW( new SDR_Proxy( *E ) ); delete D; // Test rest of tree is OK. - B->getFlatSparse(); + B->getSparse(); A->zero(); - B->getFlatSparse(); + B->getSparse(); // Test delete root. delete A; ASSERT_ANY_THROW( B->getDense() ); - ASSERT_ANY_THROW( E->getSparse() ); + ASSERT_ANY_THROW( E->getCoordinates() ); // Cleanup remaining Proxies. delete B; delete E; @@ -101,8 +101,8 @@ TEST(SdrProxyTest, TestProxyThrows) { SDR *C = &B; ASSERT_ANY_THROW( C->setDense( SDR_dense_t( 10, 1 ) )); - ASSERT_ANY_THROW( C->setSparse( SDR_sparse_t({ {0}, {0} }) )); - ASSERT_ANY_THROW( C->setFlatSparse( SDR_flatSparse_t({ 0, 1, 2 }) )); + ASSERT_ANY_THROW( C->setCoordinates( SDR_coordinate_t({ {0}, {0} }) )); + ASSERT_ANY_THROW( C->setSparse( SDR_sparse_t({ 0, 1, 2 }) )); SDR X({10}); ASSERT_ANY_THROW( C->setSDR( X )); ASSERT_ANY_THROW( C->randomize(0.10f) ); @@ -118,24 +118,24 @@ TEST(SdrProxyTest, TestProxyGetters) { ASSERT_EQ( C->getDense(), SDR_dense_t({ 0, 1, 0, 0, 1, 0 }) ); // Test getting flat sparse - A.setSparse( SDR_sparse_t({ {0, 1}, {0, 1} })); - ASSERT_EQ( C->getSparse(), SDR_sparse_t({ {0, 2}, {0, 0} }) ); + A.setCoordinates( SDR_coordinate_t({ {0, 1}, {0, 1} })); + ASSERT_EQ( C->getCoordinates(), SDR_coordinate_t({ {0, 2}, {0, 0} }) ); // Test getting sparse - A.setFlatSparse( SDR_flatSparse_t({ 2, 3 })); - ASSERT_EQ( C->getFlatSparse(), SDR_flatSparse_t({ 2, 3 }) ); + A.setSparse( SDR_sparse_t({ 2, 3 })); + ASSERT_EQ( C->getSparse(), SDR_sparse_t({ 2, 3 }) ); // Test getting sparse, a second time. - A.setFlatSparse( SDR_flatSparse_t({ 2, 3 })); - ASSERT_EQ( C->getSparse(), SDR_sparse_t({ {1, 1}, {0, 1} }) ); + A.setSparse( SDR_sparse_t({ 2, 3 })); + ASSERT_EQ( C->getCoordinates(), SDR_coordinate_t({ {1, 1}, {0, 1} }) ); // Test getting sparse, when the parent SDR already has sparse computed and // the dimensions are the same. A.zero(); SDR_Proxy D( A ); SDR *E = &D; - A.setSparse( SDR_sparse_t({ {0, 1}, {0, 1} })); - ASSERT_EQ( E->getSparse(), SDR_sparse_t({ {0, 1}, {0, 1} }) ); + A.setCoordinates( SDR_coordinate_t({ {0, 1}, {0, 1} })); + ASSERT_EQ( E->getCoordinates(), SDR_coordinate_t({ {0, 1}, {0, 1} }) ); } TEST(SdrProxyTest, TestSaveLoad) { @@ -158,13 +158,13 @@ TEST(SdrProxyTest, TestSaveLoad) { // Test flat data SDR flat({ 3, 3 }); SDR_Proxy f( flat ); - flat.setFlatSparse(SDR_flatSparse_t({ 1, 4, 8 })); + flat.setSparse(SDR_sparse_t({ 1, 4, 8 })); f.save( outfile ); // Test index data SDR index({ 3, 3 }); SDR_Proxy x( index ); - index.setSparse(SDR_sparse_t({ + index.setCoordinates(SDR_coordinate_t({ { 0, 1, 2 }, { 1, 1, 2 }})); x.save( outfile ); diff --git a/src/test/unit/types/SdrTest.cpp b/src/test/unit/types/SdrTest.cpp index 30b4e42b1e..b8fb34b13f 100644 --- a/src/test/unit/types/SdrTest.cpp +++ b/src/test/unit/types/SdrTest.cpp @@ -38,19 +38,19 @@ TEST(SdrTest, TestConstructor) { SDR b(b_dims); ASSERT_EQ( b.size, 3ul ); ASSERT_EQ( b.dimensions, b_dims ); - ASSERT_EQ( b.getSparse().size(), 1ul ); + ASSERT_EQ( b.getCoordinates().size(), 1ul ); // zero initialized ASSERT_EQ( b.getDense(), vector({0, 0, 0}) ); - ASSERT_EQ( b.getFlatSparse(), vector(0) ); - ASSERT_EQ( b.getSparse(), vector>({{}}) ); + ASSERT_EQ( b.getSparse(), vector(0) ); + ASSERT_EQ( b.getCoordinates(), vector>({{}}) ); // Test 3-D vector c_dims = {11u, 15u, 3u}; SDR c(c_dims); ASSERT_EQ( c.size, 11u * 15u * 3u ); ASSERT_EQ( c.dimensions, c_dims ); - ASSERT_EQ( c.getSparse().size(), 3ul ); - ASSERT_EQ( c.getFlatSparse().size(), 0ul ); + ASSERT_EQ( c.getCoordinates().size(), 3ul ); + ASSERT_EQ( c.getSparse().size(), 0ul ); // Test dimensions are copied not referenced c_dims.push_back(7); ASSERT_EQ( c.dimensions, vector({11u, 15u, 3u}) ); @@ -66,7 +66,7 @@ TEST(SdrTest, TestConstructorCopy) { SDR a({5}); a.setDense( SDR_dense_t({0, 1, 0, 0, 0})); SDR b(a); - ASSERT_EQ( b.getFlatSparse(), vector({1}) ); + ASSERT_EQ( b.getSparse(), vector({1}) ); ASSERT_TRUE(a == b); } @@ -75,10 +75,10 @@ TEST(SdrTest, TestZero) { a.setDense( vector(16, 1) ); a.zero(); ASSERT_EQ( vector(16, 0), a.getDense() ); - ASSERT_EQ( a.getFlatSparse().size(), 0ul); - ASSERT_EQ( a.getSparse().size(), 2ul); - ASSERT_EQ( a.getSparse().at(0).size(), 0ul); - ASSERT_EQ( a.getSparse().at(1).size(), 0ul); + ASSERT_EQ( a.getSparse().size(), 0ul); + ASSERT_EQ( a.getCoordinates().size(), 2ul); + ASSERT_EQ( a.getCoordinates().at(0).size(), 0ul); + ASSERT_EQ( a.getCoordinates().at(1).size(), 0ul); } TEST(SdrTest, TestSDR_Examples) { @@ -95,19 +95,19 @@ TEST(SdrTest, TestSDR_Examples) { 0, 1, 0, 0, 0, 1 })); ASSERT_EQ( data, X.getDense() ); - X.setFlatSparse(SDR_flatSparse_t({ 1, 4, 8 })); + X.setSparse(SDR_sparse_t({ 1, 4, 8 })); ASSERT_EQ( data, X.getDense() ); - X.setSparse(SDR_sparse_t({{ 0, 1, 2,}, { 1, 1, 2 }})); + X.setCoordinates(SDR_coordinate_t({{ 0, 1, 2,}, { 1, 1, 2 }})); ASSERT_EQ( data, X.getDense() ); // Access data in any format, SDR will automatically convert data formats. ASSERT_EQ( X.getDense(), SDR_dense_t({ 0, 1, 0, 0, 1, 0, 0, 0, 1 }) ); - ASSERT_EQ( X.getSparse(), SDR_sparse_t({{ 0, 1, 2 }, {1, 1, 2}}) ); - ASSERT_EQ( X.getFlatSparse(), SDR_flatSparse_t({ 1, 4, 8 }) ); + ASSERT_EQ( X.getCoordinates(), SDR_coordinate_t({{ 0, 1, 2 }, {1, 1, 2}}) ); + ASSERT_EQ( X.getSparse(), SDR_sparse_t({ 1, 4, 8 }) ); // Data format conversions are cached, and when an SDR value changes the // cache is cleared. - X.setFlatSparse(SDR_flatSparse_t({})); // Assign new data to the SDR, clearing the cache. + X.setSparse(SDR_sparse_t({})); // Assign new data to the SDR, clearing the cache. X.getDense(); // This line will convert formats. X.getDense(); // This line will resuse the result of the previous line @@ -129,7 +129,7 @@ TEST(SdrTest, TestSDR_Examples) { dense[2] = true; X.setDense( dense ); // Notify the SDR of the changes. after = X.getDense().data(); - ASSERT_EQ( X.getFlatSparse(), SDR_flatSparse_t({ 2 }) ); + ASSERT_EQ( X.getSparse(), SDR_sparse_t({ 2 }) ); ASSERT_EQ( before, after ); } @@ -174,81 +174,81 @@ TEST(SdrTest, TestSetDenseInplace) { ASSERT_EQ( a.getDense(), a_data ); } -TEST(SdrTest, TestSetFlatSparseVec) { +TEST(SdrTest, TestSetSparseVec) { SDR a({11, 10, 4}); - UInt *before = a.getFlatSparse().data(); + UInt *before = a.getSparse().data(); auto vec = vector(a.size, 1); UInt *data = vec.data(); for(UInt i = 0; i < a.size; i++) vec[i] = i; - a.setFlatSparse( vec ); - UInt *after = a.getFlatSparse().data(); + a.setSparse( vec ); + UInt *after = a.getSparse().data(); ASSERT_NE( before, after ); ASSERT_EQ( after, data ); } -TEST(SdrTest, TestSetFlatSparsePtr) { +TEST(SdrTest, TestSetSparsePtr) { SDR a({11, 10, 4}); auto vec = vector(a.size, 1); for(UInt i = 0; i < a.size; i++) vec[i] = i; a.zero(); - a.setFlatSparse( (UInt*) vec.data(), a.size ); - ASSERT_EQ( a.getFlatSparse(), vec ); - ASSERT_NE( a.getFlatSparse().data(), vec.data()); // true copy not a reference + a.setSparse( (UInt*) vec.data(), a.size ); + ASSERT_EQ( a.getSparse(), vec ); + ASSERT_NE( a.getSparse().data(), vec.data()); // true copy not a reference } -TEST(SdrTest, TestSetFlatSparseInplace) { +TEST(SdrTest, TestSetSparseInplace) { // Test both mutable & inplace methods at the same time, which is the intended use case. SDR a({10, 10}); a.zero(); - auto& a_data = a.getFlatSparse(); + auto& a_data = a.getSparse(); ASSERT_EQ( a_data, vector(0) ); a_data.push_back(0); - a.setFlatSparse( a_data ); - ASSERT_EQ( a.getFlatSparse().data(), a.getFlatSparse().data() ); - ASSERT_EQ( a.getFlatSparse(), a.getFlatSparse() ); - ASSERT_EQ( a.getFlatSparse().data(), a_data.data() ); - ASSERT_EQ( a.getFlatSparse(), a_data ); - ASSERT_EQ( a.getFlatSparse(), vector(1) ); + a.setSparse( a_data ); + ASSERT_EQ( a.getSparse().data(), a.getSparse().data() ); + ASSERT_EQ( a.getSparse(), a.getSparse() ); + ASSERT_EQ( a.getSparse().data(), a_data.data() ); + ASSERT_EQ( a.getSparse(), a_data ); + ASSERT_EQ( a.getSparse(), vector(1) ); a_data.clear(); - a.setFlatSparse( a_data ); + a.setSparse( a_data ); ASSERT_EQ( a.getDense(), vector(a.size, 0) ); } -TEST(SdrTest, TestSetSparse) { +TEST(SdrTest, TestSetCoordinates) { SDR a({4, 1, 3}); - void *before = a.getSparse().data(); + void *before = a.getCoordinates().data(); auto vec = vector>({ { 0, 1, 2, 0 }, { 0, 0, 0, 0 }, { 0, 1, 2, 1 } }); void *data = vec.data(); - a.setSparse( vec ); - void *after = a.getSparse().data(); + a.setCoordinates( vec ); + void *after = a.getCoordinates().data(); ASSERT_EQ( after, data ); ASSERT_NE( before, after ); } -TEST(SdrTest, TestSetSparseCopy) { +TEST(SdrTest, TestSetCoordinatesCopy) { SDR a({ 3, 3 }); - void *before = a.getSparse().data(); + void *before = a.getCoordinates().data(); auto vec = vector>({ { 0.0f, 1.0f, 2.0f }, { 1.0f, 1.0f, 2.0f } }); void *data = vec.data(); - a.setSparse( vec ); - void *after = a.getSparse().data(); + a.setCoordinates( vec ); + void *after = a.getCoordinates().data(); ASSERT_EQ( before, after ); // Data copied from vec into sdr's buffer ASSERT_NE( after, data ); // Data copied from vec into sdr's buffer - ASSERT_EQ( a.getFlatSparse(), SDR_flatSparse_t({ 1, 4, 8 })); + ASSERT_EQ( a.getSparse(), SDR_sparse_t({ 1, 4, 8 })); } -TEST(SdrTest, TestSetSparseInplace) { +TEST(SdrTest, TestSetCoordinatesInplace) { // Test both mutable & inplace methods at the same time, which is the intended use case. SDR a({10, 10}); a.zero(); - auto& a_data = a.getSparse(); + auto& a_data = a.getCoordinates(); ASSERT_EQ( a_data, vector>({{}, {}}) ); a_data[0].push_back(0); a_data[1].push_back(0); @@ -256,17 +256,17 @@ TEST(SdrTest, TestSetSparseInplace) { a_data[1].push_back(7); a_data[0].push_back(7); a_data[1].push_back(1); - a.setSparse( a_data ); + a.setCoordinates( a_data ); ASSERT_EQ( a.getSum(), 3ul ); // I think some of these check the same things but thats ok. - ASSERT_EQ( (void*) a.getSparse().data(), (void*) a.getSparse().data() ); - ASSERT_EQ( a.getSparse(), a.getSparse() ); - ASSERT_EQ( a.getSparse().data(), a_data.data() ); - ASSERT_EQ( a.getSparse(), a_data ); - ASSERT_EQ( a.getFlatSparse(), vector({0, 37, 71}) ); // Check data ok + ASSERT_EQ( (void*) a.getCoordinates().data(), (void*) a.getCoordinates().data() ); + ASSERT_EQ( a.getCoordinates(), a.getCoordinates() ); + ASSERT_EQ( a.getCoordinates().data(), a_data.data() ); + ASSERT_EQ( a.getCoordinates(), a_data ); + ASSERT_EQ( a.getSparse(), vector({0, 37, 71}) ); // Check data ok a_data[0].clear(); a_data[1].clear(); - a.setSparse( a_data ); + a.setCoordinates( a_data ); ASSERT_EQ( a.getDense(), vector(a.size, 0) ); } @@ -276,32 +276,32 @@ TEST(SdrTest, TestSetSDR) { // Test dense assignment works a.setDense(SDR_dense_t({1, 1, 1, 1, 1})); b.setSDR(a); - ASSERT_EQ( b.getFlatSparse(), vector({0, 1, 2, 3, 4}) ); + ASSERT_EQ( b.getSparse(), vector({0, 1, 2, 3, 4}) ); // Test flat sparse assignment works - a.setFlatSparse(SDR_flatSparse_t({0, 1, 2, 3, 4})); + a.setSparse(SDR_sparse_t({0, 1, 2, 3, 4})); b.setSDR(a); ASSERT_EQ( b.getDense(), vector({1, 1, 1, 1, 1}) ); // Test sparse assignment works - a.setSparse(SDR_sparse_t({{0, 1, 2, 3, 4}})); + a.setCoordinates(SDR_coordinate_t({{0, 1, 2, 3, 4}})); b.setSDR(a); ASSERT_EQ( b.getDense(), vector({1, 1, 1, 1, 1}) ); } -TEST(SdrTest, TestGetDenseFromFlatSparse) { +TEST(SdrTest, TestGetDenseFromSparse) { // Test zeros SDR z({4, 4}); - z.setFlatSparse(SDR_flatSparse_t({})); + z.setSparse(SDR_sparse_t({})); ASSERT_EQ( z.getDense(), vector(16, 0) ); // Test ones SDR nz({4, 4}); - nz.setFlatSparse(SDR_flatSparse_t( + nz.setSparse(SDR_sparse_t( {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15})); ASSERT_EQ( nz.getDense(), vector(16, 1) ); // Test 1-D SDR d1({30}); - d1.setFlatSparse(SDR_flatSparse_t({1, 29, 4, 5, 7})); + d1.setSparse(SDR_sparse_t({1, 29, 4, 5, 7})); vector ans(30, 0); ans[1] = 1; ans[29] = 1; @@ -312,7 +312,7 @@ TEST(SdrTest, TestGetDenseFromFlatSparse) { // Test 3-D SDR d3({10, 10, 10}); - d3.setFlatSparse(SDR_flatSparse_t({0, 5, 50, 55, 500, 550, 555, 999})); + d3.setSparse(SDR_sparse_t({0, 5, 50, 55, 500, 550, 555, 999})); vector ans2(1000, 0); ans2[0] = 1; ans2[5] = 1; @@ -325,10 +325,10 @@ TEST(SdrTest, TestGetDenseFromFlatSparse) { ASSERT_EQ( d3.getDense(), ans2 ); } -TEST(SdrTest, TestGetDenseFromSparse) { +TEST(SdrTest, TestGetDenseFromCoordinates) { // Test simple 2-D SDR a({3, 3}); - a.setSparse(SDR_sparse_t({{1, 0, 2}, {2, 0, 2}})); + a.setCoordinates(SDR_coordinate_t({{1, 0, 2}, {2, 0, 2}})); vector ans(9, 0); ans[0] = 1; ans[5] = 1; @@ -337,29 +337,29 @@ TEST(SdrTest, TestGetDenseFromSparse) { // Test zeros SDR z({99, 1}); - z.setSparse(SDR_sparse_t({{}, {}})); + z.setCoordinates(SDR_coordinate_t({{}, {}})); ASSERT_EQ( z.getDense(), vector(99, 0) ); } -TEST(SdrTest, TestGetFlatSparseFromDense) { +TEST(SdrTest, TestGetSparseFromDense) { // Test simple 2-D SDR. SDR a({3, 3}); a.zero(); auto dense = a.getDense(); dense[5] = 1; dense[8] = 1; a.setDense(dense); - ASSERT_EQ(a.getFlatSparse().at(0), 5ul); - ASSERT_EQ(a.getFlatSparse().at(1), 8ul); + ASSERT_EQ(a.getSparse().at(0), 5ul); + ASSERT_EQ(a.getSparse().at(1), 8ul); // Test zero'd SDR. a.setDense( vector(a.size, 0) ); - ASSERT_EQ( a.getFlatSparse().size(), 0ul ); + ASSERT_EQ( a.getSparse().size(), 0ul ); } -TEST(SdrTest, TestGetFlatSparseFromSparse) { +TEST(SdrTest, TestGetSparseFromCoordinates) { // Test simple 2-D SDR. SDR a({3, 3}); a.zero(); - auto& index = a.getSparse(); + auto& index = a.getCoordinates(); ASSERT_EQ( index.size(), 2ul ); ASSERT_EQ( index[0].size(), 0ul ); ASSERT_EQ( index[1].size(), 0ul ); @@ -372,53 +372,53 @@ TEST(SdrTest, TestGetFlatSparseFromSparse) { // Insert flat index 5 index.at(0).push_back(1); index.at(1).push_back(2); - a.setSparse( index ); - ASSERT_EQ(a.getFlatSparse().at(0), 4ul); - ASSERT_EQ(a.getFlatSparse().at(1), 8ul); - ASSERT_EQ(a.getFlatSparse().at(2), 5ul); + a.setCoordinates( index ); + ASSERT_EQ(a.getSparse().at(0), 4ul); + ASSERT_EQ(a.getSparse().at(1), 8ul); + ASSERT_EQ(a.getSparse().at(2), 5ul); // Test zero'd SDR. - a.setSparse(SDR_sparse_t( {{}, {}} )); - ASSERT_EQ( a.getFlatSparse().size(), 0ul ); + a.setCoordinates(SDR_coordinate_t( {{}, {}} )); + ASSERT_EQ( a.getSparse().size(), 0ul ); } -TEST(SdrTest, TestGetSparseFromFlat) { +TEST(SdrTest, TestGetCoordinatesFromSparse) { // Test simple 2-D SDR. SDR a({3, 3}); a.zero(); - auto& index = a.getSparse(); + auto& index = a.getCoordinates(); ASSERT_EQ( index.size(), 2ul ); ASSERT_EQ( index[0].size(), 0ul ); ASSERT_EQ( index[1].size(), 0ul ); - a.setFlatSparse(SDR_flatSparse_t({ 4, 8, 5 })); - ASSERT_EQ( a.getSparse(), vector>({ + a.setSparse(SDR_sparse_t({ 4, 8, 5 })); + ASSERT_EQ( a.getCoordinates(), vector>({ { 1, 2, 1 }, { 1, 2, 2 } }) ); // Test zero'd SDR. - a.setFlatSparse(SDR_flatSparse_t( { } )); - ASSERT_EQ( a.getSparse(), vector>({{}, {}}) ); + a.setSparse(SDR_sparse_t( { } )); + ASSERT_EQ( a.getCoordinates(), vector>({{}, {}}) ); } -TEST(SdrTest, TestGetSparseFromDense) { +TEST(SdrTest, TestGetCoordinatesFromDense) { // Test simple 2-D SDR. SDR a({3, 3}); a.zero(); auto dense = a.getDense(); dense[5] = 1; dense[8] = 1; a.setDense(dense); - ASSERT_EQ( a.getSparse(), vector>({ + ASSERT_EQ( a.getCoordinates(), vector>({ { 1, 2 }, { 2, 2 }}) ); // Test zero'd SDR. a.setDense( vector(a.size, 0) ); - ASSERT_EQ( a.getSparse()[0].size(), 0ul ); - ASSERT_EQ( a.getSparse()[1].size(), 0ul ); + ASSERT_EQ( a.getCoordinates()[0].size(), 0ul ); + ASSERT_EQ( a.getCoordinates()[1].size(), 0ul ); } TEST(SdrTest, TestAt) { SDR a({3, 3}); - a.setFlatSparse(SDR_flatSparse_t( {4, 5, 8} )); + a.setSparse(SDR_sparse_t( {4, 5, 8} )); ASSERT_TRUE( a.at( {1, 1} )); ASSERT_TRUE( a.at( {1, 2} )); ASSERT_TRUE( a.at( {2, 2} )); @@ -523,7 +523,7 @@ TEST(SdrTest, TestRandomize) { vector af( af_test.size, 0 ); for( UInt i = 0; i < iterations; i++ ) { af_test.randomize( sparsity ); - for( auto idx : af_test.getFlatSparse() ) + for( auto idx : af_test.getSparse() ) af[ idx ] += 1; } for( auto f : af ) { @@ -593,9 +593,9 @@ TEST(SdrTest, TestEquality) { test_cases.push_back( new SDR({ 3, 3 })); test_cases.back()->setDense(SDR_dense_t({0, 1, 0, 0, 1, 0, 0, 0, 1})); test_cases.push_back( new SDR({ 3, 3 })); - test_cases.back()->setFlatSparse(SDR_flatSparse_t({0,})); + test_cases.back()->setSparse(SDR_sparse_t({0,})); test_cases.push_back( new SDR({ 3, 3 })); - test_cases.back()->setFlatSparse(SDR_flatSparse_t({3, 4, 6})); + test_cases.back()->setSparse(SDR_sparse_t({3, 4, 6})); // Check that SDRs equal themselves for(UInt x = 0; x < test_cases.size(); x++) { @@ -633,12 +633,12 @@ TEST(SdrTest, TestSaveLoad) { // Test flat data SDR flat({ 3, 3 }); - flat.setFlatSparse(SDR_flatSparse_t({ 1, 4, 8 })); + flat.setSparse(SDR_sparse_t({ 1, 4, 8 })); flat.save( outfile ); // Test index data SDR index({ 3, 3 }); - index.setSparse(SDR_sparse_t({ + index.setCoordinates(SDR_coordinate_t({ { 0, 1, 2 }, { 1, 1, 2 }})); index.save( outfile ); @@ -754,12 +754,12 @@ TEST(SdrTest, TestIntersectionExampleUsage) { // Setup 2 SDRs to hold the inputs. SDR A({ 10u }); SDR B({ 10u }); - A.setFlatSparse(SDR_flatSparse_t( {2, 3, 4, 5})); - B.setFlatSparse(SDR_flatSparse_t({0, 1, 2, 3})); + A.setSparse(SDR_sparse_t( {2, 3, 4, 5})); + B.setSparse(SDR_sparse_t({0, 1, 2, 3})); // Calculate the logical intersection SDR_Intersection X(A, B); - ASSERT_EQ(X.getFlatSparse(), SDR_flatSparse_t({2, 3})); + ASSERT_EQ(X.getSparse(), SDR_sparse_t({2, 3})); // Assignments to the input SDRs are propigated to the SDR_Intersection B.zero(); From 4a4befc6f0fdd6d8153138e2848e1234cd44ee4e Mon Sep 17 00:00:00 2001 From: ctrl-z-9000-times Date: Sat, 2 Mar 2019 11:58:30 -0500 Subject: [PATCH 14/16] SDR rename to sparse & coordinates: fix python unit tests --- bindings/py/tests/SDR_test.py | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/bindings/py/tests/SDR_test.py b/bindings/py/tests/SDR_test.py index e67946118b..bf02ce71c9 100644 --- a/bindings/py/tests/SDR_test.py +++ b/bindings/py/tests/SDR_test.py @@ -38,24 +38,24 @@ def testExampleUsage(self): [0, 1, 0], [0, 0, 1]] assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] ) - assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) - assert( list(X.flatSparse) == [ 1, 4, 8 ] ) - X.sparse = [[0, 1, 2], [1, 1, 2]] + assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) + assert( list(X.sparse) == [ 1, 4, 8 ] ) + X.coordinates = [[0, 1, 2], [1, 1, 2]] assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] ) - assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) - assert( list(X.flatSparse) == [ 1, 4, 8 ] ) - X.flatSparse = [ 1, 4, 8 ] + assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) + assert( list(X.sparse) == [ 1, 4, 8 ] ) + X.sparse = [ 1, 4, 8 ] # 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. assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] ) - assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) - assert( list(X.flatSparse) == [ 1, 4, 8 ] ) + assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] ) + assert( list(X.sparse) == [ 1, 4, 8 ] ) # Data format conversions are cached, and when an SDR value changes the # cache is cleared. - X.flatSparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache. + 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 @@ -64,7 +64,7 @@ def testExampleUsage(self): data[ 0, 4] = 1 data[444, 444] = 1 X.dense = data - assert(list(X.flatSparse) == [ 4, 444444 ]) + assert(list(X.sparse) == [ 4, 444444 ]) def testConstructor(self): A = SDR((103,)) @@ -87,7 +87,7 @@ def testConstructor(self): def testZero(self): A = SDR((103,)) - A.flatSparse = list(range(20)) + A.sparse = list(range(20)) A.zero() assert( np.sum( A.dense ) == 0 ) @@ -102,7 +102,7 @@ def testDense(self): assert(A.dense[0] + A.dense[99] == 2) # Test modify in-place A.dense = A.dense - assert(set(A.flatSparse) == set((0, 99))) + assert(set(A.sparse) == set((0, 99))) # Test dense dimensions assert(B.dense.shape == (100, 100, 1)) # No crash with dimensions @@ -153,45 +153,45 @@ def testDenseInplace(self): assert( inplace_time < copy_time / 3 ) - def testFlatSparse(self): + def testSparse(self): A = SDR((103,)) B = SDR((100, 100, 1)) - A.flatSparse - B.flatSparse = [1,2,3,4] - assert(all(B.flatSparse == np.array([1,2,3,4]))) + A.sparse + B.sparse = [1,2,3,4] + assert(all(B.sparse == np.array([1,2,3,4]))) - B.flatSparse = [] + B.sparse = [] assert( not B.dense.any() ) # Test wrong dimensions assigned C = SDR( 1000 ) C.randomize( .98 ) try: - A.flatSparse = C.flatSparse + A.sparse = C.sparse except RuntimeError: pass else: self.fail() - def testSparse(self): + def testCoordinates(self): A = SDR((103,)) B = SDR((100, 100, 1)) C = SDR((2, 4, 5, 1,1,1,1, 3)) - A.sparse - B.sparse = [[0, 55, 99], [0, 11, 99], [0, 0, 0]] + A.coordinates + B.coordinates = [[0, 55, 99], [0, 11, 99], [0, 0, 0]] assert(B.dense[0, 0, 0] == 1) assert(B.dense[55, 11, 0] == 1) assert(B.dense[99, 99, 0] == 1) C.randomize( .5 ) - assert( len(C.sparse) == len(C.dimensions) ) + assert( len(C.coordinates) == len(C.dimensions) ) # Test wrong dimensions assigned C = SDR((2, 4, 5, 1,1,1,1, 3)) C.randomize( .5 ) try: - A.sparse = C.sparse + A.coordinates = C.coordinates except RuntimeError: pass else: @@ -200,14 +200,14 @@ def testSparse(self): def testSetSDR(self): A = SDR((103,)) B = SDR((103,)) - A.flatSparse = [66] + A.sparse = [66] B.setSDR( A ) assert( B.dense[66] == 1 ) assert( B.getSum() == 1 ) B.dense[77] = 1 B.dense = B.dense A.setSDR( B ) - assert( set(A.flatSparse) == set((66, 77)) ) + assert( set(A.sparse) == set((66, 77)) ) # Test wrong dimensions assigned C = SDR((2, 4, 5, 1,1,1,1, 3)) @@ -326,8 +326,8 @@ def testExampleUsage(self): # Convert SDR dimensions from (4 x 4) to (8 x 2) A = SDR([ 4, 4 ]) B = SDR_Proxy( A, [8, 2]) - A.sparse = ([1, 1, 2], [0, 1, 2]) - assert( (np.array(B.sparse) == ([2, 2, 5], [0, 1, 0]) ).all() ) + A.coordinates = ([1, 1, 2], [0, 1, 2]) + assert( (np.array(B.coordinates) == ([2, 2, 5], [0, 1, 0]) ).all() ) def testLostSDR(self): # You need to keep a reference to the SDR, since SDR class does not use smart pointers. @@ -343,8 +343,8 @@ def testChaining(self): A.dense.fill( 1 ) A.dense = A.dense - assert( len(C.flatSparse) == A.size ) - assert( len(D.flatSparse) == A.size ) + assert( len(C.sparse) == A.size ) + assert( len(D.sparse) == A.size ) del B @pytest.mark.skip(reason="Known issue: https://github.com/htm-community/nupic.cpp/issues/160") @@ -356,10 +356,10 @@ class SdrIntersectionTest(unittest.TestCase): def testExampleUsage(self): A = SDR( 10 ) B = SDR( 10 ) - A.flatSparse = [2, 3, 4, 5] - B.flatSparse = [0, 1, 2, 3] + A.sparse = [2, 3, 4, 5] + B.sparse = [0, 1, 2, 3] X = SDR_Intersection(A, B) - assert((X.flatSparse == [2, 3]).all()) + assert((X.sparse == [2, 3]).all()) B.zero() assert(X.getSparsity() == 0) From 19bfe500d2a69469e0d6a519397ba490d2442bcb Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 18:52:15 +0100 Subject: [PATCH 15/16] CP: resolve merge conflicts with FlatSparse renamed to sparse --- src/nupic/algorithms/ColumnPooler.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index b616ad945b..9c5636bd43 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -222,14 +222,14 @@ class ColumnPooler // : public Serializable SDR_ActivationFrequency PP_AF( proximalInputs.dimensions, 10 * proximalInputs.size); UInt cell = 0u; for(auto inhib = 0u; inhib < inhibitionAreas.size; ++inhib) { - inhibitionAreas.setFlatSparse(SDR_flatSparse_t{ inhib }); + inhibitionAreas.setSparse(SDR_sparse_t{ inhib }); for(auto c = 0u; c < cellsPerInhibitionArea; ++c, ++cell) { for(auto s = 0u; s < proximalSegments; ++s) { auto segment = proximalConnections.createSegment( cell ); // Make synapses. potentialPool( inhibitionAreas, proximalInputs ); - for(const auto presyn : proximalInputs.getFlatSparse() ) { + for(const auto presyn : proximalInputs.getSparse() ) { auto permanence = initProximalPermanence(); proximalConnections.createSynapse( segment, presyn, permanence); } @@ -347,7 +347,7 @@ class ColumnPooler // : public Serializable { // Proximal Feed Forward Excitement rawOverlaps_.assign( proximalConnections.numSegments(), 0.0f ); - proximalConnections.computeActivity(rawOverlaps_, feedForwardInputs.getFlatSparse()); + proximalConnections.computeActivity(rawOverlaps_, feedForwardInputs.getSparse()); // Setup for Boosting const Real denominator = 1.0f / log2( sparsity / proximalSegments ); @@ -412,7 +412,7 @@ class ColumnPooler // : public Serializable auto compare = [&overlaps](const UInt &a, const UInt &b) -> bool {return overlaps[a] > overlaps[b];}; - auto &active = activeCells.getFlatSparse(); + auto &active = activeCells.getSparse(); active.clear(); active.reserve(cellsPerInhibitionArea + numDesired * inhibitionAreas ); @@ -446,7 +446,7 @@ class ColumnPooler // : public Serializable ++iter; } } - activeCells.setFlatSparse( active ); + activeCells.setSparse( active ); } @@ -455,7 +455,7 @@ class ColumnPooler // : public Serializable const SDR &active ) { SDR AF_SDR( AF->dimensions ); auto &activeSegments = AF_SDR.getSparse(); - for(const auto &cell : active.getFlatSparse()) + for(const auto &cell : active.getSparse()) { // Adapt Proximal Segments NTA_CHECK(cell < proximalMaxSegment_.size()) << "cell oob! " << cell << " < " << proximalMaxSegment_.size(); @@ -522,8 +522,8 @@ class DefaultTopology : public Topology_t inputCoords.push_back({ (UInt32)floor(inputCoord) }); } potentialPool.setSparse(inputCoords); - NTA_CHECK(potentialPool.getFlatSparse().size() == 1u); - const auto centerInput = potentialPool.getFlatSparse()[0]; + NTA_CHECK(potentialPool.getSparse().size() == 1u); + const auto centerInput = potentialPool.getSparse()[0]; vector columnInputs; if (wrapAround) { @@ -539,7 +539,7 @@ class DefaultTopology : public Topology_t const UInt numPotential = (UInt)round(columnInputs.size() * potentialPct); const auto selectedInputs = Random().sample(columnInputs, numPotential); - potentialPool.setFlatSparse( selectedInputs ); + potentialPool.setSparse( selectedInputs ); } }; From 089aa7aa60f0dd0d0ae0b79f67ed1ee2a2c1ed88 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 2 Mar 2019 18:58:53 +0100 Subject: [PATCH 16/16] CP: merge conflict --- src/nupic/algorithms/ColumnPooler.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nupic/algorithms/ColumnPooler.cpp b/src/nupic/algorithms/ColumnPooler.cpp index 9c5636bd43..ffc448b600 100644 --- a/src/nupic/algorithms/ColumnPooler.cpp +++ b/src/nupic/algorithms/ColumnPooler.cpp @@ -119,22 +119,29 @@ class ColumnPooler // : public Serializable const vector distalInputDimensions, const vector inhibitionDimensions, UInt cellsPerInhibitionArea, + Real sparsity, + Topology_t potentialPool, UInt proximalSegments, UInt proximalSegmentThreshold, Permanence proximalIncrement, Permanence proximalDecrement, Permanence proximalSynapseThreshold, + UInt distalMaxSegments, UInt distalMaxSynapsesPerSegment, UInt distalSegmentThreshold, + UInt distalSegmentMatch, + UInt distalAddSynapses, Permanence distalIncrement, Permanence distalDecrement, Permanence distalMispredictDecrement, Permanence distalSynapseThreshold, + Real stability_rate, Real fatigue_rate, + Real period, Int seed, bool verbose) { @@ -143,22 +150,29 @@ class ColumnPooler // : public Serializable distalInputDimensions, inhibitionDimensions, cellsPerInhibitionArea, + sparsity, + potentialPool, proximalSegments, proximalSegmentThreshold, proximalIncrement, proximalDecrement, proximalSynapseThreshold, + distalMaxSegments, distalMaxSynapsesPerSegment, distalSegmentThreshold, + distalSegmentMatch, + distalAddSynapses, distalIncrement, distalDecrement, distalMispredictDecrement, distalSynapseThreshold, + stability_rate, fatigue_rate, + period, seed, verbose); @@ -196,10 +210,12 @@ class ColumnPooler // : public Serializable Real period, Int seed, bool verbose) { + proximalInputDimensions_ = proximalInputDimensions; distalInputDimensions_ = distalInputDimensions; inhibitionDimensions_ = inhibitionDimensions; cellsPerInhibitionArea_ = cellsPerInhibitionArea; + proximalSegments_ = proximalSegments; this->sparsity = sparsity; this->proximalSegmentThreshold = proximalSegmentThreshold;