Skip to content

Commit

Permalink
Random: remove serialization via operator<<
Browse files Browse the repository at this point in the history
replaced by Cereal
  • Loading branch information
breznak committed Apr 23, 2020
1 parent d66c1e9 commit 3995e40
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 148 deletions.
21 changes: 11 additions & 10 deletions bindings/py/cpp_src/bindings/math/py_Random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ namespace htm_ext {
py::class_<Random_t> Random(m, "Random");

Random.def(py::init<htm::UInt64>(), py::arg("seed") = 0)
.def("getUInt32", &Random_t::getUInt32, py::arg("max") = (htm::UInt32)-1l)
.def("getReal64", &Random_t::getReal64)
.def("getSeed", &Random_t::getSeed)
.def("max", &Random_t::max)
.def("min", &Random_t::min)
.def("__eq__", [](Random_t const & self, Random_t const & other) {//wrapping operator==
return self == other;
}, py::is_operator());
.def("getUInt32", &Random_t::getUInt32, py::arg("max") = (htm::UInt32)-1l)
.def("getReal64", &Random_t::getReal64)
.def("getSeed", &Random_t::getSeed)
.def("max", &Random_t::max)
.def("min", &Random_t::min)
.def("__eq__", [](Random_t const & self, Random_t const & other) { return self == other; }, py::is_operator()); //operator==

Random.def_property_readonly_static("MAX32", [](py::object) {
return Random_t::MAX32;
Expand Down Expand Up @@ -149,9 +147,11 @@ namespace htm_ext {
[](const Random_t& r)
{
std::stringstream ss;
ss << r;
cereal::JSONOutputArchive ar( ss );
ar(r); //save r's state to archive (stream) with cereal
return ss.str();
},

[](const std::string& str)
{
if (str.empty())
Expand All @@ -160,8 +160,9 @@ namespace htm_ext {
}

std::stringstream ss(str);
cereal::JSONInputArchive ar( ss );
Random_t r;
ss >> r;
ar(r); //load from stream to Random 'r'

return r;
}
Expand Down
37 changes: 2 additions & 35 deletions src/htm/utils/Random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
/** @file
Random Number Generator implementation
*/
#include <iostream> // for istream, ostream
#include <chrono> // for random seeds

#include <htm/utils/Log.hpp>
#include <htm/utils/Random.hpp>

Expand All @@ -34,7 +31,7 @@ bool Random::operator==(const Random &o) const {

std::random_device rd; //HW RNG, undeterministic, platform dependant. Use only for seeding rng if random seed wanted (seed=0)

Random::Random(UInt64 seed) {
Random::Random(const UInt64 seed) {
if (seed == 0) {
const unsigned int static_seed = rd();
std::mt19937 static_gen(static_seed);
Expand All @@ -49,39 +46,9 @@ Random::Random(UInt64 seed) {
steps_ = 0;
}


namespace htm {
std::ostream &operator<<(std::ostream &outStream, const Random &r) {
outStream << "random-v2" << " ";
outStream << r.seed_ << " ";
outStream << r.steps_ << " ";
outStream << "endrandom-v2" << " ";
return outStream;
}


std::istream &operator>>(std::istream &inStream, Random &r) {
std::string version;

inStream >> version;
NTA_CHECK(version == "random-v2") << "Random() deserializer -- found unexpected version string '"
<< version << "'";
inStream >> r.seed_;
r.gen.seed(static_cast<unsigned int>(r.seed_)); //reseed
inStream >> r.steps_;
r.gen.discard(r.steps_); //advance n steps
//FIXME we could de/serialize directly RNG gen, it should be multi-platform according to standard,
//but on OSX CI it wasn't (25/11/2018). So "hacking" the above instead.
std::string endtag;
inStream >> endtag;
NTA_CHECK(endtag == "endrandom-v2") << "Random() deserializer -- found unexpected end tag '" << endtag << "'";
inStream.ignore(1);

return inStream;
}

// helper function for seeding RNGs across the plugin barrier
UInt32 GetRandomSeed() {
return htm::Random().getUInt32();
return htm::Random(0).getUInt32();
}
} // namespace htm
9 changes: 2 additions & 7 deletions src/htm/utils/Random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ namespace htm {
*/
class Random : public Serializable {
public:
Random(UInt64 seed = 0);
Random(const UInt64 seed = 0);


// Serialization
CerealAdapter;
template<class Archive>
void save_ar(Archive & ar) const {
Expand Down Expand Up @@ -160,8 +161,6 @@ class Random : public Serializable {

protected:
friend class RandomTest;
friend std::ostream &operator<<(std::ostream &, const Random &);
friend std::istream &operator>>(std::istream &, Random &);
friend UInt32 GetRandomSeed();
private:
UInt64 seed_;
Expand All @@ -186,10 +185,6 @@ class Random : public Serializable {
}
};

// serialization/deserialization
std::ostream &operator<<(std::ostream &, const Random &);
std::istream &operator>>(std::istream &, Random &);

// This function returns seeds from the Random singleton in our
// "universe" (application, plugin, python module). If, when the
// Random constructor is called, seeder_ is NULL, then seeder_ is
Expand Down
96 changes: 0 additions & 96 deletions src/test/unit/utils/RandomTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,80 +110,6 @@ TEST(RandomTest, OperatorEquals) {
}


TEST(RandomTest, SerializationDeserialization) {
// test serialization/deserialization
Random r1(862973);
for (int i = 0; i < 100; i++)
r1.getUInt32();

EXPECT_EQ(r1.getUInt32(), 2276275187u) << "Before serialization must be same";
// serialize
std::stringstream ostream;
ostream << r1;

// print out serialization for debugging
std::string x(ostream.str());
// NTA_INFO << "random serialize string: '" << x << "'";
// Serialization should be deterministic and platform independent
const std::string expectedString = "random-v2 862973 101 endrandom-v2 ";
EXPECT_EQ(expectedString, x) << "De/serialization";

// deserialize into r2
std::string s(ostream.str());
std::stringstream ss(s);
Random r2;
ss >> r2;

// r1 and r2 should be identical
EXPECT_EQ(r1, r2) << "load from serialization";
EXPECT_EQ(r2.getUInt32(), 3537119063u) << "Deserialized is not deterministic";
r1.getUInt32(); //move the same number of steps

UInt32 v1, v2;
for (int i = 0; i < 100; i++) {
v1 = r1.getUInt32();
v2 = r2.getUInt32();
EXPECT_EQ(v1, v2) << "serialization";
}
}


TEST(RandomTest, testSerialization2) {
const UInt n=1000;
Random r1(7);
Random r2;

htm::Timer testTimer;
testTimer.start();
for (UInt i = 0; i < n; ++i) {
r1.getUInt32();

// Serialize
ofstream os("random3.stream", ofstream::binary);
os << r1;
os.flush();
os.close();

// Deserialize
ifstream is("random3.stream", ifstream::binary);
is >> r2;
is.close();

// Test
ASSERT_EQ(r1.getUInt32(), r2.getUInt32());
ASSERT_EQ(r1.getUInt32(), r2.getUInt32());
ASSERT_EQ(r1.getUInt32(), r2.getUInt32());
ASSERT_EQ(r1.getUInt32(), r2.getUInt32());
ASSERT_EQ(r1.getUInt32(), r2.getUInt32());
}
testTimer.stop();

remove("random3.stream");

cout << "Random serialization: " << testTimer.getElapsed() << endl;
}


TEST(RandomTest, testSerialization_ar) {
// test serialization/deserialization
const UInt SEED = 862973u;
Expand Down Expand Up @@ -233,28 +159,6 @@ TEST(RandomTest, ReturnInCorrectRange) {
}
}

/*
TEST(RandomTest, getUInt64) {
// tests for getUInt64
Random r1(1);
ASSERT_EQ(2469588189546311528u, r1.getUInt64())
<< "check getUInt64, seed 1, first call";
ASSERT_EQ(2516265689700432462u, r1.getUInt64())
<< "check getUInt64, seed 1, second call";
Random r2(2);
ASSERT_EQ(16668552215174154828u, r2.getUInt64())
<< "check getUInt64, seed 2, first call";
EXPECT_EQ(15684088468973760345u, r2.getUInt64())
<< "check getUInt64, seed 2, second call";
Random r3(7464235991977222558);
EXPECT_EQ(8035066300482877360u, r3.getUInt64())
<< "check getUInt64, big seed, first call";
EXPECT_EQ(623784303608610892u, r3.getUInt64())
<< "check getUInt64, big seed, second call";
}
*/

TEST(RandomTest, getUInt32) {
// tests for getUInt32
Expand Down

0 comments on commit 3995e40

Please sign in to comment.