Skip to content

Commit

Permalink
Merge pull request #879 from htm-community/getParameters2
Browse files Browse the repository at this point in the history
fixed getParameters
  • Loading branch information
dkeeney authored Aug 30, 2020
2 parents 68ca06b + 206bb9b commit b79dd3a
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/htm/ntypes/Array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
// constructor A(sdr) - Buffer initialized from SDR
// constructor A(vector) - Buffer initialized from vector
// B = A; - Shallow copy, B has same, type, buffer, size
// B = A.copy() - Creates B as a copy of A.
// B = A.copy() - Creates B as a deep copy of A.
// A.populate(vector) - fills A from vector, with conversion, A retains type.
//
//
Expand Down
58 changes: 29 additions & 29 deletions src/htm/regions/SPRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ SPRegion::SPRegion(const ValueMap &values, Region *region)
dim_ = Dimensions(args_.columnCount);
else
args_.columnCount = (UInt32)dim_.getCount();

args_.inputWidth = 0; // size of the input buffer before initialization

}

Expand Down Expand Up @@ -482,25 +482,6 @@ Spec *SPRegion::createSpec() {
"true", // defaultValue
ParameterSpec::ReadWriteAccess)); // access

/* ---- other parameters ----- */
ns->parameters.add(
"spInputNonZeros",
ParameterSpec("The indices of the non-zero inputs to the spatial pooler",
NTA_BasicType_SDR, // type
0, // elementCount
"", // constraints
"", // defaultValue
ParameterSpec::ReadOnlyAccess)); // access

ns->parameters.add(
"spOutputNonZeros",
ParameterSpec(
"The indices of the non-zero outputs from the spatial pooler",
NTA_BasicType_SDR, // type
0, // elementCount
"", // constraints
"", // defaultValue
ParameterSpec::ReadOnlyAccess)); // access


/* The last group is for parameters that aren't specific to spatial pooler */
Expand All @@ -525,8 +506,8 @@ Spec *SPRegion::createSpec() {

ns->parameters.add("spatialImp",
ParameterSpec("SpatialPooler type or option. not used.",
NTA_BasicType_Byte, // type
0, // elementCount
NTA_BasicType_Str, // type
1, // elementCount
"", // constraints
"", // defaultValue
ParameterSpec::ReadOnlyAccess)); // access
Expand Down Expand Up @@ -730,23 +711,42 @@ bool SPRegion::getParameterBool(const std::string &name, Int64 index) const {
}

// copy the contents of the requested array into the caller's array.
// Allocate the buffer if one is not provided. Convert data types if needed.
// Allocate the buffer in the Array object if one is not provided. Convert data types if needed.
//
// This may be confusing. These 4 'array parameters' were part of the original function set so
// I am keeping them in the function for backward compatibility but they are removed from the
// Spec. Originally getInputData( ) and getOutputData( ) functions did not exist so an app could
// not directly access the input and output buffers. These Array 'parameters' were a way for the
// app to sample the buffer data but this was only available on the SPRegion. Now that we have
// the more generic functions the Array parameters in SPRegion are redundant.
// Also note that 'spInputNonZeros' and 'spOutputNonZeros' were a way to get the sparse arrays
// from the buffers. Now that we have the SDR type there is a better way to get the sparse array.
void SPRegion::getParameterArray(const std::string &name, Int64 index, Array &array) const {
if (name == "spatialPoolerInput") {
array = getInput("bottomUpIn")->getData().copy();
if (!region_->isInitialized())
return;
if (name == "spatialPoolerInput") {
// returns the dense array from the SDR
array = getInput("bottomUpIn")->getData().get_as(NTA_BasicType_UInt32);
} else if (name == "spatialPoolerOutput") {
array = getOutput("bottomUpOut")->getData().copy();
// returns the dense array from the SDR
array = getOutput("bottomUpOut")->getData().get_as(NTA_BasicType_UInt32);
} else if (name == "spInputNonZeros") {
array = getInput("bottomUpIn")->getData().copy();
// returns the sparse array from the SDR
const SDR_sparse_t& v = getInput("bottomUpIn")->getData().getSDR().getSparse();
array = Array(v);
} else if (name == "spOutputNonZeros") {
array = getOutput("bottomUpOut")->getData().copy();
// returns the sparse array from the SDR
const SDR_sparse_t& v = getOutput("bottomUpOut")->getData().getSDR().getSparse();
array = Array(v);
}
else {
this->RegionImpl::getParameterArray(name, index, array);
}
}

size_t SPRegion::getParameterArrayCount(const std::string &name, Int64 index) const {
if (!region_->isInitialized())
return 0;
if (name == "spatialPoolerInput") {
return getInput("bottomUpIn")->getData().getCount();
} else if (name == "spatialPoolerOutput") {
Expand All @@ -755,7 +755,7 @@ size_t SPRegion::getParameterArrayCount(const std::string &name, Int64 index) co
const SDR_sparse_t& v = getInput("bottomUpIn")->getData().getSDR().getSparse();
return v.size();
} else if (name == "spOutputNonZeros") {
const SDR_sparse_t& v = getInput("bottomUpOut")->getData().getSDR().getSparse();
const SDR_sparse_t& v = getOutput("bottomUpOut")->getData().getSDR().getSparse();
return v.size();
}
return 0;
Expand Down
2 changes: 1 addition & 1 deletion src/test/unit/engine/HelloRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ TEST(HelloRegionTest, demo) {
EXPECT_EQ(outputArray.getCount(), testdata[0].size());
const Real64 *buffer = (const Real64 *)outputArray.getBuffer();
for (size_t i = 0; i < outputArray.getCount(); i++)
EXPECT_FLOAT_EQ(buffer[i], testdata[0][i]);
EXPECT_DOUBLE_EQ(buffer[i], testdata[0][i]);
// At this point we have consumed the first buffer from FileInputRegion.

// Serialize
Expand Down
4 changes: 2 additions & 2 deletions src/test/unit/regions/RDSEEncoderRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,9 @@ namespace testing
EXPECT_TRUE(compareParameters(n2region1, parameterMap))
<< "Conflict when comparing RDSEEncoderRegion parameters after restore with before save.";

EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_UInt32))
<< " comparing Output arrays after restore with before save.";
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_UInt32))
<< " comparing NZ out arrays after restore with before save.";


Expand Down
16 changes: 14 additions & 2 deletions src/test/unit/regions/RegionTestUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,20 @@ ::testing::AssertionResult compareParameterArrays(std::shared_ptr<Region> region
Byte *buf8;
Array array1(type);
Array array2(type);
region1->getParameterArray(parameter, array1);
region2->getParameterArray(parameter, array2);
if (region1->isInitialized() && region2->isInitialized()) {
region1->getParameterArray(parameter, array1);
region2->getParameterArray(parameter, array2);
} else if (!region1->isInitialized()) {
return ::testing::AssertionFailure()
<< "Failure: Original region was not intialized but Restored region was initialized.";
} else if (!region2->isInitialized()) {
return ::testing::AssertionFailure()
<< "Failure: Original region was intialized but Restored region was not initialized.";
}
else {
// both are not initialized, so ok
return ::testing::AssertionSuccess();
}

if (type != array1.getType())
return ::testing::AssertionFailure() << "Failure: Original Array1 for parameter '" << parameter
Expand Down
73 changes: 69 additions & 4 deletions src/test/unit/regions/SPRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
static bool verbose = false; // turn this on to print extra stuff for debugging the test.

// The following string should contain a valid expected Spec length - manually verified.
const UInt EXPECTED_SPEC_COUNT = 22u; // The number of parameters expected in the SPRegion Spec
const UInt EXPECTED_SPEC_COUNT = 20u; // The number of parameters expected in the SPRegion Spec

using namespace htm;
namespace testing
Expand Down Expand Up @@ -338,9 +338,9 @@ TEST(SPRegionTest, testSerialization)
EXPECT_TRUE(compareParameters(n2region2, parameterMap))
<< "Conflict when comparing SPRegion parameters after restore with before save.";

EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_UInt32))
<< " comparing Output arrays after restore with before save.";
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_UInt32))
<< " comparing NZ out arrays after restore with before save.";


Expand Down Expand Up @@ -376,8 +376,73 @@ TEST(SPRegionTest, testSerialization)

// cleanup
Directory::removeTree("TestOutputDir", true);
}
}

TEST(SPRegionTest, testGetParameters)
{
Network net;
// create an SP region with default parameters
std::shared_ptr<Region> region1 = net.addRegion("region1", "SPRegion", "{dim: 100}"); // only declare the output size

// before initialization
std::string expected1 = R"({
"columnCount": 0,
"inputWidth": 0,
"potentialRadius": 16,
"potentialPct": 0.500000,
"globalInhibition": true,
"localAreaDensity": 0.050000,
"numActiveColumnsPerInhArea": 0,
"stimulusThreshold": 0,
"synPermInactiveDec": 0.008000,
"synPermActiveInc": 0.050000,
"synPermConnected": 0.100000,
"minPctOverlapDutyCycles": 0.001000,
"dutyCyclePeriod": 1000,
"boostStrength": 0.000000,
"seed": 1,
"spVerbosity": 0,
"wrapAround": true,
"learningMode": 1,
"activeOutputCount": 0,
"spatialImp": null
})";

std::string jsonstr = region1->getParameters();
//VERBOSE << jsonstr << "\n";
EXPECT_STREQ(jsonstr.c_str(), expected1.c_str());


// after initialization
std::string expected2 = R"({
"columnCount": 100,
"inputWidth": 10,
"potentialRadius": 10,
"potentialPct": 0.500000,
"globalInhibition": true,
"localAreaDensity": 0.050000,
"numActiveColumnsPerInhArea": 0,
"stimulusThreshold": 0,
"synPermInactiveDec": 0.008000,
"synPermActiveInc": 0.050000,
"synPermConnected": 0.100000,
"minPctOverlapDutyCycles": 0.001000,
"dutyCyclePeriod": 1000,
"boostStrength": 0.000000,
"seed": 1,
"spVerbosity": 0,
"wrapAround": true,
"learningMode": 1,
"activeOutputCount": 100,
"spatialImp": null
})";

net.link("INPUT", "region1", "", "{dim: 10}", "src", "bottomUpIn"); // declare the input size
net.initialize();
jsonstr = region1->getParameters();
//VERBOSE << jsonstr << "\n";
EXPECT_STREQ(jsonstr.c_str(), expected2.c_str());
}

} // namespace

4 changes: 2 additions & 2 deletions src/test/unit/regions/ScalarEncoderRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ namespace testing
EXPECT_TRUE(compareParameters(n2region1, parameterMap))
<< "Conflict when comparing ScalarSensor parameters after restore with before save.";

EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spatialPoolerOutput", NTA_BasicType_UInt32))
<< " comparing Output arrays after restore with before save.";
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_SDR))
EXPECT_TRUE(compareParameterArrays(n1region2, n2region2, "spOutputNonZeros", NTA_BasicType_UInt32))
<< " comparing NZ out arrays after restore with before save.";


Expand Down
60 changes: 60 additions & 0 deletions src/test/unit/regions/TMRegionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,5 +427,65 @@ TEST(TMRegionTest, testSerialization) {
Directory::removeTree("TestOutputDir", true);
}

TEST(TMRegionTest, testGetParameters) {
Network net;
// create an TM region with default parameters
std::shared_ptr<Region> region1 = net.addRegion("region1", "TMRegion", "");

// before initialization
std::string expected1 = R"({
"numberOfCols": 0,
"cellsPerColumn": 32,
"activationThreshold": 13,
"initialPermanence": 0.210000,
"connectedPermanence": 0.500000,
"minThreshold": 10,
"maxNewSynapseCount": 20,
"permanenceIncrement": 0.100000,
"permanenceDecrement": 0.100000,
"predictedSegmentDecrement": 0.000000,
"maxSegmentsPerCell": 255,
"maxSynapsesPerSegment": 255,
"seed": 42,
"inputWidth": 0,
"learningMode": true,
"activeOutputCount": 0,
"anomaly": -1.000000,
"orColumnOutputs": false
})";

std::string jsonstr = region1->getParameters();
VERBOSE << jsonstr << "\n";
EXPECT_STREQ(jsonstr.c_str(), expected1.c_str());

// after initialization
std::string expected2 = R"({
"numberOfCols": 100,
"cellsPerColumn": 32,
"activationThreshold": 13,
"initialPermanence": 0.210000,
"connectedPermanence": 0.500000,
"minThreshold": 10,
"maxNewSynapseCount": 20,
"permanenceIncrement": 0.100000,
"permanenceDecrement": 0.100000,
"predictedSegmentDecrement": 0.000000,
"maxSegmentsPerCell": 255,
"maxSynapsesPerSegment": 255,
"seed": 42,
"inputWidth": 100,
"learningMode": true,
"activeOutputCount": 0,
"anomaly": -1.000000,
"orColumnOutputs": false
})";

net.link("INPUT", "region1", "", "{dim: 100}", "src", "bottomUpIn"); // declare the input size
net.initialize();
jsonstr = region1->getParameters();
VERBOSE << jsonstr << "\n";
EXPECT_STREQ(jsonstr.c_str(), expected2.c_str());
}


} // namespace testing

0 comments on commit b79dd3a

Please sign in to comment.