Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,23 @@ jobs:
run: ./cgraphitti -c ../Testing/RegressionTesting/configfiles/test-medium-connected-long.xml
- name: verify test-medium-connected-long
run: ../Testing/RegressionTesting/compare_matrices ../Testing/RegressionTesting/GoodOutput/Cpu/test-medium-connected-long-out.xml ../Testing/RegressionTesting/TestOutput/test-medium-connected-long-out.xml

# Growth-to-STDP integration: serialize a grown network, then deserialize it as the
# input for an STDP simulation and verify the STDP output. This is a sequential,
# dependent pipeline (the STDP run consumes the growth run's checkpoint), so it cannot
# be part of the parallel single-simulation tests above.
# The unit tests below check that the import mechanism itself behaves (the STDP run keeps
# its own classes and receives every grown edge); the regression run after them checks that
# the resulting simulation output has not changed.
- id: gs_unit
name: run growth-to-STDP unit tests
run: ./run_growth_stdp_test.sh

- id: gs_source
name: run growth source for growth-to-STDP
run: ./cgraphitti -c ../Testing/RegressionTesting/configfiles/test-growth-stdp-source.xml -s ../Testing/RegressionTesting/TestOutput/test-growth-stdp-checkpoint.xml
- id: gs_stdp
name: run STDP from grown network
run: ./cgraphitti -c ../Testing/RegressionTesting/configfiles/test-growth-stdp.xml -d ../Testing/RegressionTesting/TestOutput/test-growth-stdp-checkpoint.xml
- name: verify growth-to-STDP
run: ../Testing/RegressionTesting/compare_matrices ../Testing/RegressionTesting/GoodOutput/Cpu/test-growth-stdp-out.xml ../Testing/RegressionTesting/TestOutput/test-growth-stdp-out.xml
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ serialFullTest
serialFirstHalfTest
serialSecondHalfTest
serialFileAccessTest
growthStdpSourceTest
growthStdpImportTest
core
# core is generated by GDB during debugging

Expand Down
24 changes: 24 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,30 @@ target_link_libraries(serialFirstHalfTest combinedLib)
target_link_libraries(serialSecondHalfTest stdc++fs)
target_link_libraries(serialSecondHalfTest combinedLib)

#------- GROWTH-TO-STDP INTEGRATION TESTS --------------------
# Like the serialization tests above, each of these runs a simulation from start to finish and so
# needs its own executable. growthStdpImportTest consumes the checkpoint written by
# growthStdpSourceTest, so they must run in that order; run_growth_stdp_test.sh sequences them.

add_executable(growthStdpSourceTest
Testing/RunTests.cpp
Testing/UnitTesting/GrowthToStdpSourceTest.cpp)

add_executable(growthStdpImportTest
Testing/RunTests.cpp
Testing/UnitTesting/GrowthToStdpImportTest.cpp)

# Links the Googletest framework to each of the growth-to-STDP test executables.
target_link_libraries(growthStdpSourceTest gtest gtest_main)
target_link_libraries(growthStdpImportTest gtest gtest_main)

# Link the combined library and filesystem support to the respective test executables.
target_link_libraries(growthStdpSourceTest stdc++fs)
target_link_libraries(growthStdpSourceTest combinedLib)

target_link_libraries(growthStdpImportTest stdc++fs)
target_link_libraries(growthStdpImportTest combinedLib)

# commenting out serialFileAccessTest until issue-754 is resolved
# add_executable(serialFileAccessTest
# Testing/RunTests.cpp
Expand Down
6 changes: 6 additions & 0 deletions Simulator/Core/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ Connections &Model::getConnections() const
return *connections_;
}

/// Replaces the Connections subgraph with a new instance, taking ownership.
void Model::setConnections(unique_ptr<Connections> connections)
{
connections_ = std::move(connections);
}

/// Get the Layout class object.
/// @return Pointer to the Layout class object.
Layout &Model::getLayout() const
Expand Down
7 changes: 7 additions & 0 deletions Simulator/Core/Model.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class Model {
/// Returns reference to Connections
Connections &getConnections() const;

/// Replaces the Connections subgraph with a new instance, taking ownership.
///
/// Used when deserializing a growth checkpoint into a different (e.g. STDP) model:
/// after the checkpoint is loaded, the grown topology is imported into a freshly
/// constructed Connections object and installed here. See Serializer::deserialize().
void setConnections(unique_ptr<Connections> connections);

/// Returns reference to Layout
Layout &getLayout() const;

Expand Down
78 changes: 78 additions & 0 deletions Simulator/Core/Serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@
*/

#include "Serializer.h"
#include "AllEdges.h"
#include "ConnGrowth.h"
#include "Connections.h"
#include "Factory.h"
#include "GPUModel.h"
#include "Model.h"
#include "OperationManager.h"
#include "ParameterManager.h"
#include <fstream>

// About CEREAL_XML_STRING_VALUE
Expand All @@ -36,6 +41,67 @@
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>

namespace {

/// Imports the grown network topology from a deserialized ConnGrowth checkpoint into a
/// freshly constructed Connections object of the type requested by the current run's
/// configuration file (for example ConnStatic with AllSTDPSynapses).
///
/// This enables the output network of a growth simulation to be used as the starting
/// point ("input") for a subsequent STDP simulation: only the edge source, destination,
/// weight, and type are carried over. The restored vertices/layout and global simulation
/// state (RNG, simulation step) are left untouched.
///
/// @param connectionClassName Connections class named in the current configuration file.
void importGrowthTopology(const string &connectionClassName)
{
Simulator &simulator = Simulator::getInstance();
Model &model = simulator.getModel();

// Edges grown during the checkpointed growth simulation (still owned by the model).
AllEdges &grownEdges = model.getConnections().getEdges();

// Build the Connections/Edges objects requested by the current configuration file.
unique_ptr<Connections> importedConnections
= Factory<Connections>::getInstance().createType(connectionClassName);
if (importedConnections == nullptr) {
throw runtime_error("Deserialization topology import: unknown Connections class '"
+ connectionClassName + "'");
}

AllEdges &importedEdges = importedConnections->getEdges();
importedEdges.setupEdges();
// Populate per-edge parameters (e.g. STDP constants) from the configuration file so that
// addEdge()/createEdge() initialize the new edges with the correct values.
importedEdges.loadParameters();

BGFLOAT deltaT = simulator.getDeltaT();
BGSIZE importedCount = 0;
for (BGSIZE iEdg = 0; iEdg < grownEdges.inUse_.size(); iEdg++) {
if (grownEdges.inUse_[iEdg] == 0) {
continue;
}
int srcVertex = grownEdges.sourceVertexIndex_[iEdg];
int destVertex = grownEdges.destVertexIndex_[iEdg];
edgeType type = grownEdges.type_[iEdg];
BGSIZE newEdg = importedEdges.addEdge(type, srcVertex, destVertex, deltaT);
importedEdges.W_[newEdg] = grownEdges.W_[iEdg];
++importedCount;
}

// Install the new connection subgraph (destroys the checkpoint's ConnGrowth) and rebuild
// its edge index map from the imported edges.
model.setConnections(std::move(importedConnections));
model.getConnections().createEdgeIndexMap();

log4cplus::Logger consoleLogger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("console"));
LOG4CPLUS_INFO(consoleLogger, "Imported " << importedCount << " grown edges into a "
<< connectionClassName
<< " network for the current simulation.");
}

} // namespace

/// Deserializes all member variables of the
/// Connections, Layout, Edges, Vertices, and associated helper classes.
///
Expand Down Expand Up @@ -66,6 +132,18 @@ bool Serializer::deserialize()
return false;
}

// If a growth checkpoint is being loaded into a non-growth (e.g. STDP) configuration,
// carry over only the grown topology rather than resuming the growth model. This is what
// enables using a growth simulation's output network as the input for an STDP simulation.
string connectionClassName;
ParameterManager::getInstance().getStringByXpath("//ConnectionsParams/@class",
connectionClassName);
bool checkpointIsGrowth
= dynamic_cast<ConnGrowth *>(&simulator.getModel().getConnections()) != nullptr;
if (checkpointIsGrowth && connectionClassName != "ConnGrowth") {
importGrowthTopology(connectionClassName);
}

// Deserialization rebuilds Connections/Layout subgraphs (and nested edges_/vertices_
// unique_ptrs). Constructors register OperationManager callbacks via std::bind(this, ...),
// but destroyed objects leave stale entries that segfault on the next executeOperation().
Expand Down
37 changes: 37 additions & 0 deletions Testing/RegressionTesting/GoodOutput/Cpu/test-growth-stdp-out.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" standalone="no"?>
<Matrix name="x_Location" type="complete" rows="1" columns="100" multiplier="1.0">
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
</Matrix>
<Matrix name="y_Location" type="complete" rows="1" columns="100" multiplier="1.0">
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9
</Matrix>
<Matrix name="vertexTypeMap" type="complete" rows="1" columns="100" multiplier="1.0">
2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 2 2 2 2
</Matrix>
<Matrix name="Neuron_7" type="complete" rows="1" columns="6" multiplier="1.0">
102695 104216 126232 162426 188819 190770
</Matrix>
<Matrix name="Neuron_11" type="complete" rows="1" columns="6" multiplier="1.0">
100007 116938 135037 151070 172143 185912
</Matrix>
<Matrix name="Neuron_14" type="complete" rows="1" columns="13" multiplier="1.0">
100749 109075 116463 118598 122407 138333 140142 141758 148424 151342 168901 183717 191945
</Matrix>
<Matrix name="Neuron_41" type="complete" rows="1" columns="9" multiplier="1.0">
102754 108353 110406 125856 162410 173350 179751 182987 186910
</Matrix>
<Matrix name="Neuron_44" type="complete" rows="1" columns="17" multiplier="1.0">
109677 114613 117544 119338 132427 138054 143270 150357 158933 164963 173002 174424 183694 186887 189155 190274 194910
</Matrix>
<Matrix name="Neuron_67" type="complete" rows="1" columns="25" multiplier="1.0">
107554 115269 116826 120492 122455 130386 132229 134708 141253 147423 149068 156490 158588 163903 167668 169617 171811 174424 175946 178047 179248 184349 186009 187713 195563
</Matrix>
<Matrix name="Neuron_71" type="complete" rows="1" columns="3" multiplier="1.0">
190761 193391 199116
</Matrix>
<Matrix name="Neuron_74" type="complete" rows="1" columns="25" multiplier="1.0">
103180 105295 116474 118786 123459 130782 132936 134262 137969 149350 152549 153678 155363 161192 162146 167142 170557 172113 174395 187966 189555 192201 195336 198036 199650
</Matrix>
<Matrix name="Neuron_97" type="complete" rows="1" columns="26" multiplier="1.0">
109044 111981 113415 116004 117654 127890 129016 129973 132523 139506 144408 145703 150069 154906 155673 158397 161765 163873 165357 169303 170739 172134 180880 187211 189009 192370
</Matrix>
114 changes: 114 additions & 0 deletions Testing/RegressionTesting/configfiles/test-growth-stdp-source.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Growth simulation that produces the input network for the growth-to-STDP regression
test. Run with `-s` to serialize the grown network; the resulting checkpoint is then
deserialized by test-growth-stdp.xml. The start radius is large enough that neighboring
neurons on the grid overlap and edges are grown within a single short epoch, keeping the
regression fast while still exercising a non-trivial grown topology. -->
<BGSimParams>
<SimInfoParams name="SimInfoParams">
<graphmlFile name="graphmlFile">../configfiles/graphs/test-small.graphml</graphmlFile>
<SimParams name="SimParams">
<epochDuration name="epochDuration">10.0</epochDuration>
<numEpochs name="numEpochs">1</numEpochs>
</SimParams>
<SimConfig name="SimConfig">
<maxFiringRate name="maxFiringRate">200</maxFiringRate>
<maxEdgesPerVertex name="maxEdgesPerVertex">200</maxEdgesPerVertex>
</SimConfig>
<RNGConfig name="RNGConfig">
<InitRNGSeed name="InitRNGSeed">1</InitRNGSeed>
<NoiseRNGSeed class="Norm" name="NoiseRNGSeed">1</NoiseRNGSeed>
</RNGConfig>
</SimInfoParams>

<ModelParams>
<VerticesParams class="AllLIFNeurons" name="VerticesParams">
<Iinject name="Iinject">
<min name="min">13.5e-09</min>
<max name="max">13.5e-09</max>
</Iinject>
<Inoise name="Inoise">
<min name="min">1.0e-09</min>
<max name="max">1.5e-09</max>
</Inoise>
<Vthresh name="Vthresh">
<min name="min">15.0e-03</min>
<max name="max">15.0e-03</max>
</Vthresh>
<Vresting name="Vresting">
<min name="min">0.0</min>
<max name="max">0.0</max>
</Vresting>
<Vreset name="Vreset">
<min name="min">13.5e-03</min>
<max name="max">13.5e-03</max>
</Vreset>
<Vinit name="Vinit">
<min name="min">13.0e-03</min>
<max name="max">13.0e-03</max>
</Vinit>
<starter_vthresh name="starter_vthresh">
<min name="min">13.565e-3</min>
<max name="max">13.655e-3</max>
</starter_vthresh>
<starter_vreset name="starter_vreset">
<min name="min">13.0e-3</min>
<max name="max">13.0e-3</max>
</starter_vreset>
</VerticesParams>

<EdgesParams class="AllDSSynapses" name="EdgesParams">
<tau name="tau">
<ii name="ii">6e-3</ii>
<ie name="ie">6e-3</ie>
<ei name="ei">3e-3</ei>
<ee name="ee">3e-3</ee>
</tau>
<delay name="delay">
<ii name="ii">0.8e-3</ii>
<ie name="ie">0.8e-3</ie>
<ei name="ei">0.8e-3</ei>
<ee name="ee">1.5e-3</ee>
</delay>
<U name="U">
<ii name="ii">0.32</ii>
<ie name="ie">0.25</ie>
<ei name="ei">0.05</ei>
<ee name="ee">0.5</ee>
</U>
<D name="D">
<ii name="ii">0.144</ii>
<ie name="ie">0.7</ie>
<ei name="ei">0.125</ei>
<ee name="ee">1.1</ee>
</D>
<F name="F">
<ii name="ii">0.06</ii>
<ie name="ie">0.02</ie>
<ei name="ei">1.2</ei>
<ee name="ee">0.05</ee>
</F>
</EdgesParams>

<ConnectionsParams class="ConnGrowth" name="ConnectionsParams">
<!-- Growth parameters -->
<GrowthParams name="GrowthParams">
<epsilon name="epsilon">0.60</epsilon>
<beta name="beta">0.10</beta>
<rho name="rho">0.0001</rho>
<targetRate name="targetRate">1.0</targetRate>
<minRadius name="minRadius">0.1</minRadius>
<startRadius name="startRadius">0.6</startRadius>
</GrowthParams>
</ConnectionsParams>

<LayoutParams class="LayoutNeuro" name="LayoutParams">
</LayoutParams>

<RecorderParams class="XmlRecorder" name="RecorderParams">
<RecorderFiles name="RecorderFiles">
<resultFileName name="resultFileName">../Testing/RegressionTesting/TestOutput/test-growth-stdp-source-out.xml</resultFileName>
</RecorderFiles>
</RecorderParams>
</ModelParams>
</BGSimParams>
Loading
Loading