// Toy insect controller. Hand-wired AltAILIF/Delta, NOT a fly connectome. #include #include #include #include #include #include #include #include #include using N=knp::neuron_traits::neuron_parameters; using P=knp::core::Population; using R=knp::core::Projection; constexpr int FRAME=48,ACTIVE=12,FIRST=4,INPUTS=9,RESET=8; // Input: foodL foodR foodFront dangerL dangerR dangerFront wanderL wanderR drive. const int HW[6][INPUTS]={{4,0,0,0,0,0,0,0,0},{0,4,0,0,0,0,0,0,0},{0,0,0,0,8,4,0,0,0},{0,0,0,8,0,2,0,0,0},{0,0,0,0,0,0,4,0,0},{0,0,0,0,0,0,0,4,0}}; // Output: turnLeft turnRight drive. All non-reset magnitudes per cell <=3. const int MW[3][6]={{4,-2,8,-2,2,-2},{-2,4,-2,8,-2,2},{0,0,0,0,0,0}}; const int DW[3][INPUTS]={{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,2,-2,-2,-8,0,0,4}}; int main(int argc,char**argv)try{ std::string mode=argc>1?argv[1]:"cpu";if(mode!="cpu"&&mode!="cuda"&&mode!="gm")throw std::runtime_error("Invalid backend"); auto neuron=[](int thr){N n;n.activation_threshold_=thr;n.negative_activation_threshold_=0;n.is_diff_=true;n.is_reset_=false;n.saturate_=true;n.potential_leak_=0;return n;}; P hp([&](size_t){return neuron(4);},6),mp([&](size_t){return neuron(8);},3);auto hid=hp.get_uid(),mid=mp.get_uid();std::vectorhs,ms,links; auto add=[](auto&v,int i,int o,int w){if(w)v.push_back({{float(w),1,knp::synapse_traits::OutputType::EXCITATORY},size_t(i),size_t(o)});}; for(int h=0;h<6;h++){for(int i=0;istd::optional{return v[i];},v.size());}; auto ih=project(knp::core::UID{false},hid,hs),im=project(knp::core::UID{false},mid,ms),hm=project(hid,mid,links);auto ihid=ih.get_uid(),imid=im.get_uid();std::arrayhu{},mu{};for(auto&s:hs)hu[std::get<1>(s)]=true;for(auto&s:ms)mu[std::get<1>(s)]=true; knp::framework::Network net;net.add_population(std::move(hp));net.add_population(std::move(mp));net.add_projection(std::move(ih));net.add_projection(std::move(im));net.add_projection(std::move(hm));knp::framework::Model model(std::move(net));knp::core::UID hi,mi,ho,mo;model.add_input_channel(hi,ihid);model.add_input_channel(mi,imid);model.add_output_channel(ho,hid);model.add_output_channel(mo,mid); knp::framework::BackendLoader loader;std::shared_ptrbackend; if(mode=="gm"){auto gm=knp::backends::altai::AltAIBackend::create();bool found=false;for(auto&d:gm->get_devices())if(dynamic_cast(d.get())){gm->select_device(std::move(d));found=true;break;}if(!found)throw std::runtime_error("No official GoldenModel");backend=gm;} else backend=loader.load("/home/user/KNP/build/bin/libknp-"+std::string(mode=="cuda"?"altai-cuda":"cpu-single-threaded")+"-backend.so"); std::arrayvalues{},acc{};std::arraycounts{};std::vector>raster;knp::framework::ModelExecutor*ep=nullptr;size_t last=size_t(-1);bool done=false; auto advance=[&](knp::core::Step t){ if(last==t)return;last=t; if(ep&&t){auto collect=[&](auto uid,int offset){for(auto&m:ep->get_loader().get_output_channel(uid).read_some_from_buffer(t-1,t-1)){ int phase=m.header_.send_time_%FRAME;if(phase>=FIRST)for(auto i:m.neuron_indexes_){++counts[offset+i];raster.emplace_back(phase,offset+i);} }};collect(ho,0);collect(mo,6);} if(t%FRAME==0){ if(t){std::cout<<"RESULT {\"hidden\":[";for(int i=0;i<6;i++)std::cout<<(i?",":"")<>v)||v<0||v>15)throw std::runtime_error("Nine integers0..15 required");std::string extra;if(in>>extra)throw std::runtime_error("Extra input");counts.fill(0);acc.fill(0);raster.clear(); } }; size_t rasterstep=size_t(-1);std::vectorinputs; auto input=[&](knp::core::Step t,const auto&used){advance(t);knp::core::messaging::SpikeData data;if(done)return data;int phase=t%FRAME; if(phase==0){for(int i=0;i=FIRST&&phase=15){acc[i]-=15;inputs.push_back(i);}}}for(auto i:inputs)if(used[i])data.push_back(i);} return data; }; knp::framework::ModelExecutor e(model,backend,{{hi,[&](auto t){return input(t,hu);}},{mi,[&](auto t){return input(t,mu);}}});ep=&e;e.start([&](knp::core::Step t){advance(t);return !done;}); }catch(const std::exception&e){std::cerr<<"FLY_ERROR "<