@@ -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+
267362TEST (SingleThreadCpuSuite, NeuronsGettingTest)
268363{
269364 const knp::testing::STestingBack backend;
0 commit comments