// Learned nonlinear hidden layer executes as integer AltAILIF/Delta neurons. #include #include #include #include #include #include #include #include #include #include #include using P=knp::core::Population;using R=knp::core::Projection;using N=knp::neuron_traits::neuron_parameters; templatestd::vectorread(const std::filesystem::path&p){std::ifstream f(p,std::ios::binary);if(!f)throw std::runtime_error("Missing file");std::vectorb((std::istreambuf_iterator(f)),{});if(b.size()%sizeof(T))throw std::runtime_error("Truncated file");std::vectorv(b.size()/sizeof(T));std::memcpy(v.data(),b.data(),b.size());return v;} int main(int argc,char**argv)try{ if(argc!=5)throw std::runtime_error("features.bin modeldir cpu|cuda hidden_counts.bin");auto root=std::filesystem::path(argv[2]);auto x=read(argv[1]),w=read(root/"hidden_w.bin"),b=read(root/"hidden_b.bin"),thr=read(root/"hidden_thresholds.bin");constexpr int F=800,H=256,FRAME=72; if(x.empty()||x.size()%F||w.size()!=F*H||b.size()!=H||thr.size()!=H)throw std::runtime_error("Invalid dimensions");size_t count=x.size()/F;for(size_t row=0;row640)throw std::runtime_error("Input outside bounds");norm+=double(a)*a;}if(norm>2063.*2063.)throw std::runtime_error("Input normalization bound violated");} int nb=0,nr=0;std::vectorreset(H);for(int h=0;h65535)throw std::runtime_error("Invalid threshold");double norm=0;for(int f=0;f127)throw std::runtime_error("Invalid weight");norm+=double(z)*z;}int64_t bound=int64_t(std::ceil(2063*std::sqrt(norm)))+std::abs(int64_t(b[h]))+1;if(2*bound>=16777216)throw std::runtime_error("Reset exactness bound exceeded");reset[h]=int(bound);nb=std::max(nb,int((std::abs(int64_t(b[h]))+65534)/65535));nr=std::max(nr,(reset[h]+65534)/65535);} P pop([&](size_t h){N n;n.activation_threshold_=thr[h];n.negative_activation_threshold_=0;n.is_diff_=true;n.is_reset_=false;n.saturate_=true;n.potential_leak_=0;return n;},H);std::vectorsyn; auto add=[&](int i,int h,int a){if(a)syn.push_back({{float(a),1,knp::synapse_traits::OutputType::EXCITATORY},size_t(i),size_t(h)});}; for(int h=0;hstd::optional{return syn[i];},syn.size());auto pid=proj.get_uid(),nid=pop.get_uid();knp::framework::Network net;net.add_population(std::move(pop));net.add_projection(std::move(proj));knp::framework::Model m(std::move(net));knp::core::UID ic,oc;m.add_input_channel(ic,pid);m.add_output_channel(oc,nid); auto gen=[&](knp::core::Step t){knp::core::messaging::SpikeData v;size_t row=t/FRAME;int phase=t%FRAME;if(row>=count)return v;if(phase==0){for(int j=0;jout(count*H); auto collect=[&](size_t t){for(auto&msg:e.get_loader().get_output_channel(oc).read_some_from_buffer(t,t)){size_t i=msg.header_.send_time_/FRAME;int phase=msg.header_.send_time_%FRAME;if(i=5&&phase<69)for(auto h:msg.neuron_indexes_)++out[i*H+h];}}; e.start([&](size_t t){if(t)collect(t-1);return t(out.data()),out.size()*4);f.close();std::cout<<"HIDDEN "<