Skip to content

Commit 5281273

Browse files
committed
Added test for stdp altai: KasperskyLab#64
1 parent 4e95f67 commit 5281273

1 file changed

Lines changed: 97 additions & 2 deletions

File tree

knp/tests/backend/single_thread_cpu_test.cpp

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ TEST(SingleThreadCpuSuite, SmallestNetwork)
9292
}
9393

9494

95-
TEST(SingleThreadCpuSuite, AdditiveSTDPNetwork)
95+
TEST(SingleThreadCpuSuite, AdditiveSTDPBLIFATNetwork)
9696
{
9797
using STDPDeltaProjection = knp::core::Projection<knp::synapse_traits::AdditiveSTDPDeltaSynapse>;
9898

@@ -176,7 +176,7 @@ TEST(SingleThreadCpuSuite, AdditiveSTDPNetwork)
176176
}
177177

178178

179-
TEST(SingleThreadCpuSuite, ResourceSTDPNetwork)
179+
TEST(SingleThreadCpuSuite, ResourceSTDPBLIFATNetwork)
180180
{
181181
using STDPDeltaProjection = knp::core::Projection<knp::synapse_traits::SynapticResourceSTDPDeltaSynapse>;
182182
using BlifatStdpPopulation = knp::core::Population<knp::neuron_traits::SynapticResourceSTDPBLIFATNeuron>;
@@ -264,6 +264,101 @@ TEST(SingleThreadCpuSuite, ResourceSTDPNetwork)
264264
}
265265

266266

267+
TEST(SingleThreadCpuSuite, ResourceSTDPAltAILIFNetwork)
268+
{
269+
using STDPDeltaProjection = knp::core::Projection<knp::synapse_traits::SynapticResourceSTDPDeltaSynapse>;
270+
using STDP_AltAILIF_Population = knp::core::Population<knp::neuron_traits::SynapticResourceSTDPAltAILIFNeuron>;
271+
272+
// Create an STDP input projection.
273+
auto stdp_input_projection_gen = [](size_t /*index*/) -> std::optional<STDPDeltaProjection::Synapse>
274+
{
275+
return STDPDeltaProjection::Synapse{
276+
{{1.0, 1, knp::synapse_traits::OutputType::EXCITATORY}, {0, 1, 2, 0.1F}}, 0, 0};
277+
};
278+
279+
// Create an STDP loop projection.
280+
auto stdp_synapse_generator = [](size_t /*index*/) -> std::optional<STDPDeltaProjection::Synapse> {
281+
return STDPDeltaProjection::Synapse{{{1.0, 6, knp::synapse_traits::OutputType::EXCITATORY}, {0, 1, 2}}, 0, 0};
282+
};
283+
284+
// Create a single-neuron neural network: input -> input_projection -> population <=> loop_projection.
285+
knp::testing::STestingBack backend;
286+
287+
STDP_AltAILIF_Population population{
288+
knp::core::UID(),
289+
[](uint64_t) -> std::optional<STDP_AltAILIF_Population::NeuronParameters>
290+
{
291+
STDP_AltAILIF_Population::NeuronParameters neuron{{}};
292+
neuron.synaptic_resource_threshold_ = 1;
293+
neuron.free_synaptic_resource_ = 2;
294+
neuron.isi_max_ = 0;
295+
return neuron;
296+
},
297+
1};
298+
auto loop_projection = STDPDeltaProjection{population.get_uid(), population.get_uid(), stdp_synapse_generator, 1};
299+
Projection input_projection =
300+
STDPDeltaProjection{knp::core::UID{false}, population.get_uid(), stdp_input_projection_gen, 1};
301+
const knp::core::UID input_uid = std::visit([](const auto &proj) { return proj.get_uid(); }, input_projection);
302+
303+
backend.load_populations({population});
304+
backend.load_projections({input_projection, loop_projection});
305+
306+
backend._init();
307+
backend.start_learning();
308+
auto endpoint = backend.get_message_bus().create_endpoint();
309+
310+
const knp::core::UID in_channel_uid;
311+
const knp::core::UID out_channel_uid;
312+
313+
// Create input and output.
314+
backend.subscribe<knp::core::messaging::SpikeMessage>(input_uid, {in_channel_uid});
315+
endpoint.subscribe<knp::core::messaging::SpikeMessage>(out_channel_uid, {population.get_uid()});
316+
317+
std::vector<knp::core::Step> results;
318+
319+
for (knp::core::Step step = 0; step < 20; ++step)
320+
{
321+
// Send inputs on steps 0, 5, 10, 15.
322+
if (step % 5 == 0)
323+
{
324+
knp::core::messaging::SpikeMessage message{{in_channel_uid, step}, {0}};
325+
endpoint.send_message(message);
326+
}
327+
backend._step();
328+
size_t msg_count = endpoint.receive_all_messages();
329+
SPDLOG_DEBUG("Received {} messages.", msg_count);
330+
auto output = endpoint.unload_messages<knp::core::messaging::SpikeMessage>(out_channel_uid);
331+
SPDLOG_DEBUG("Unloaded {} messages.", output.size());
332+
// Write the steps on which the network sends a spike.
333+
if (!output.empty()) results.push_back(step);
334+
}
335+
336+
std::vector<float> old_synaptic_weights, new_synaptic_weights;
337+
old_synaptic_weights.reserve(loop_projection.size());
338+
new_synaptic_weights.reserve(loop_projection.size());
339+
340+
std::transform(
341+
loop_projection.begin(), loop_projection.end(), std::back_inserter(old_synaptic_weights),
342+
[](const auto &synapse) { return std::get<knp::core::synapse_data>(synapse).weight_; });
343+
344+
for (auto proj = backend.begin_projections(); proj != backend.end_projections(); ++proj)
345+
{
346+
const auto &prj = std::get<STDPDeltaProjection>(proj->arg_);
347+
if (prj.get_uid() != loop_projection.get_uid()) continue;
348+
349+
std::transform(
350+
prj.begin(), prj.end(), std::back_inserter(new_synaptic_weights),
351+
[](const auto &synapse) { return std::get<knp::core::synapse_data>(synapse).weight_; });
352+
}
353+
354+
// Spikes on steps "5n + 1" (input) and on "previous_spike_n + 6" (positive feedback loop).
355+
const std::vector<knp::core::Step> expected_results = {1, 6, 7, 11, 12, 13, 16, 17, 18, 19};
356+
357+
ASSERT_EQ(results, expected_results);
358+
ASSERT_NE(old_synaptic_weights, new_synaptic_weights);
359+
}
360+
361+
267362
TEST(SingleThreadCpuSuite, NeuronsGettingTest)
268363
{
269364
const knp::testing::STestingBack backend;

0 commit comments

Comments
 (0)