// Mutate synapses.
void NetworkHomomorph::mutate()
{
   int     i, j, k, n;
   float   weight;
   Synapse *synapse;

   i = randomNeuron(true);
   n = network->numNeurons;
   for (j = 0; j < n; j++)
   {
      weight = (float)randomizer->RAND_INTERVAL(
         synapseWeightsParm.minimum, synapseWeightsParm.maximum);
      for (k = 0; k < (int)network->synapses[i][j].size(); k++)
      {
         synapse = network->synapses[i][j][k];
         synapse->setWeight(weight);
      }
   }
}
Example #2
0
int run(boost::mpi::environment& env, boost::scoped_ptr<nemo::Network>& net, unsigned ncount, unsigned scount,
		unsigned duration, unsigned nType, unsigned mType, const char* outfile, const char* configFile, const char* logDir) {

	boost::mpi::communicator world;

	boost::filesystem::path logDirPath(logDir);
	boost::filesystem::create_directory(logDirPath);

	std::ostringstream simDir;
	simDir << logDir << "/simulation-p" << world.size() << "-n" << ncount << "-s" << scount << "-nt" << nType << "-mt" << mType;
	boost::filesystem::path simDirPath(simDir.str());
	boost::filesystem::create_directory(simDirPath);

	try {
		if ( world.rank() == nemo::mpi::MASTER ) {
			nemo::Configuration conf(world.rank(), configFile);
			std::cout << "Constructing master..." << std::endl;
			nemo::mpi::Master master(env, world, *net, mType, conf, logDir);

			std::ostringstream filename;
			filename << simDir.str() << "/" << outfile;
			std::ofstream file(filename.str().c_str());

			rng_t rng;
			uirng_t randomNeuron(rng, boost::uniform_int<>(0, ncount - 1));

			master.resetTimer();
			nemo::Simulation::firing_stimulus firingStimulus(10);

			for ( unsigned ms = 0; ms < duration; ++ms ) {
				for ( unsigned i = 0; i < 10; i++ )
					firingStimulus[i] = randomNeuron();

				master.step(firingStimulus);
				const std::vector<unsigned>& firing = master.readFiring();
				file << ms << ": ";
				std::copy(firing.begin(), firing.end(), std::ostream_iterator<unsigned>(file, " "));
				file << std::endl;
			}

			std::ostringstream oss;
			oss << "Simulated " << master.elapsedSimulation() << " ms wall clock time: " << master.elapsedWallclock() << "ms"
					<< std::endl;
			std::cout << oss.str() << std::endl;

			/* Write general stats to simulation folder */
			filename.str("");
			filename.clear();
			filename << simDir.str() << "/general-stats.txt";
			writeStats(filename.str().c_str(), scount, master.elapsedSimulation(), master.elapsedWallclock(), *net, conf);
			master.appendMpiStats(filename.str().c_str());

			/* Write firing counters to simulation folder */
			filename.str("");
			filename.clear();
			filename << simDir.str() << "/firing-counters.txt";
			master.writeFiringCounters(filename.str().c_str());
		}
		else {
			std::cout << "Starting worker " << world.rank() << "..." << std::endl;
			nemo::Configuration conf(world.rank(), configFile);
			if ( conf.stdpEnabled() ) {
				std::cout << "STDP enabled" << std::endl;
				setStandardStdpFunction(conf);
			}
			nemo::mpi::runWorker(env, world, conf, simDir.str().c_str());
		}
	}
	catch (nemo::exception& e) {
		std::cerr << world.rank() << ":" << e.what() << std::endl;
		env.abort(e.errorNumber());
	}
	catch (boost::mpi::exception& e) {
		std::cerr << world.rank() << ": " << e.what() << std::endl;
		env.abort(-1);
	}

	return 0;
}
// Initialize synapse optimization.
void NetworkHomomorph::initOptimize(vector<vector<Synapse *> >& synapses,
                                    vector<vector<float> >&     permutations,
                                    int                         synapseOptimizedPathLength)
{
   int   i, j, k, n, p, q, s;
   bool  forward;
   float weight;

   vector<pair<int, int> > visited;
   Synapse                 *synapse;
   vector<Synapse *>       chemSynapses, elecSynapses;
   vector<vector<float> >  weightRanges;
   vector<float>           weightRange;
   vector<float>           permutation;

   synapses.clear();
   permutations.clear();

   // Randomly select starting neuron with synapse.
   i = randomNeuron();
   n = network->numNeurons;
   for (s = 0; s < n; s++)
   {
      if (i < network->numSensors)
      {
         forward = true;
      }
      else if ((i >= network->numSensors) &&
               (i < (network->numSensors + network->numMotors)))
      {
         forward = false;
      }
      else
      {
         forward = randomizer->RAND_BOOL();
      }
      if (forward)
      {
         for (j = 0; j < n; j++)
         {
            if (network->synapses[i][j].size() > 0)
            {
               break;
            }
         }
         if (j < n)
         {
            break;
         }
      }
      else
      {
         for (j = 0; j < n; j++)
         {
            if (network->synapses[j][i].size() > 0)
            {
               break;
            }
         }
         if (j < n)
         {
            break;
         }
      }
      i++;
      i = (i % n);
   }
   if (s == n)
   {
      return;
   }

   // Select synapse path.
   for (j = 0; j < synapseOptimizedPathLength; j++)
   {
      k = randomizer->RAND_CHOICE(n);
      for (s = 0; s < n; s++)
      {
         if (forward)
         {
            if (network->synapses[i][k].size() > 0)
            {
               for (p = 0, q = (int)visited.size(); p < q; p++)
               {
                  if ((visited[p].first == i) && (visited[p].second == k))
                  {
                     break;
                  }
               }
               if (p == q)
               {
                  visited.push_back(pair<int, int>(i, k));
                  chemSynapses.clear();
                  elecSynapses.clear();
                  for (p = 0, q = (int)network->synapses[i][k].size(); p < q; p++)
                  {
                     synapse = network->synapses[i][k][p];
                     if (synapse->type == Synapse::CHEMICAL)
                     {
                        chemSynapses.push_back(synapse);
                     }
                     else
                     {
                        elecSynapses.push_back(synapse);
                     }
                  }
                  if (chemSynapses.size() > 0)
                  {
                     synapses.push_back(chemSynapses);
                  }
                  if (elecSynapses.size() > 0)
                  {
                     synapses.push_back(elecSynapses);
                  }
                  if ((chemSynapses.size() > 0) || (elecSynapses.size() > 0))
                  {
                     i = k;
                     break;
                  }
               }
            }
         }
         else
         {
            if (network->synapses[k][i].size() > 0)
            {
               for (p = 0, q = (int)visited.size(); p < q; p++)
               {
                  if ((visited[p].first == k) && (visited[p].second == i))
                  {
                     break;
                  }
               }
               if (p == q)
               {
                  visited.push_back(pair<int, int>(k, i));
                  chemSynapses.clear();
                  elecSynapses.clear();
                  for (p = 0, q = (int)network->synapses[k][i].size(); p < q; p++)
                  {
                     synapse = network->synapses[k][i][p];
                     if (synapse->type == Synapse::CHEMICAL)
                     {
                        chemSynapses.push_back(synapse);
                     }
                     else
                     {
                        elecSynapses.push_back(synapse);
                     }
                  }
                  if (chemSynapses.size() > 0)
                  {
                     synapses.push_back(chemSynapses);
                  }
                  if (elecSynapses.size() > 0)
                  {
                     synapses.push_back(elecSynapses);
                  }
                  if ((chemSynapses.size() > 0) || (elecSynapses.size() > 0))
                  {
                     i = k;
                     break;
                  }
               }
            }
         }
         k++;
         k = (k % n);
      }
      if (s == n)
      {
         break;
      }
   }

   if (synapses.size() == 0)
   {
      return;
   }

   // Compose synapse weight permutations.
   for (i = 0, j = (int)synapses.size(); i < j; i++)
   {
      weightRange.clear();
      weight = synapses[i][0]->weight;
      weightRange.push_back(weight);
      if (synapseWeightsParm.maxDelta > 0.0f)
      {
         weight = synapses[i][0]->weight -
                  (float)randomizer->RAND_INTERVAL(0.0f, synapseWeightsParm.maxDelta);
         if (weight < synapseWeightsParm.minimum)
         {
            weight = synapseWeightsParm.minimum;
         }
      }
      weightRange.push_back(weight);
      if (synapseWeightsParm.maxDelta > 0.0f)
      {
         weight = synapses[i][0]->weight +
                  (float)randomizer->RAND_INTERVAL(0.0f, synapseWeightsParm.maxDelta);
         if (weight > synapseWeightsParm.maximum)
         {
            weight = synapseWeightsParm.maximum;
         }
      }
      weightRange.push_back(weight);
      weightRanges.push_back(weightRange);
   }
   permutation.resize((int)synapses.size());
   permuteWeights(weightRanges, permutations, permutation, 0, (int)synapses.size() - 1);
}
Example #4
0
long
benchmark(nemo::Simulation* sim, unsigned n, unsigned m,
				boost::program_options::variables_map& vm, unsigned seconds)
{

	unsigned stdpPeriod = vm["stdp-period"].as<unsigned>();
	float stdpReward = vm["stdp-reward"].as<float>();
	bool csv = vm.count("csv") != 0;
	bool verbose = !csv;
	bool provideFiringStimulus = vm.count("fstim") != 0;
	bool provideCurrentStimulus = vm.count("istim") != 0;
	bool vprobe = vm.count("vprobe") != 0;

	const unsigned MS_PER_SECOND = 1000;

	rng_t rng;
	uirng_t randomNeuron(rng, boost::uniform_int<>(0, n-1));

	sim->resetTimer();

	unsigned t = 0;
	float v = 0;

	/* Run for a few seconds to warm up the network */
	if(verbose)
		std::cout << "Running simulation (warming up)...";
	for(unsigned s=0; s < 5; ++s) {
		for(unsigned ms = 0; ms < MS_PER_SECOND; ++ms, ++t) {
			sim->step();
			if(stdpPeriod && t % stdpPeriod == 0) {
				sim->applyStdp(stdpReward);
			}
		}
	}
	if(verbose)
		std::cout << "[" << sim->elapsedWallclock() << "ms elapsed]";
	sim->resetTimer();

	if(verbose) {
		std::cout << std::endl;
		std::cout << "Running simulation (gathering performance data)...";
	}

	nemo::Simulation::firing_stimulus firingStimulus;
	nemo::Simulation::current_stimulus currentStimulus;

	unsigned long nfired = 0;
	for(unsigned s=0; s < seconds; ++s) {
		if(verbose)
			std::cout << s << " ";
		for(unsigned ms=0; ms<1000; ++ms, ++t) {

			if(provideFiringStimulus) {
				firingStimulus.resize(1);
				firingStimulus[0] = randomNeuron();
			}

			if(provideCurrentStimulus) {
				currentStimulus.resize(1);
				currentStimulus[0] = std::make_pair(randomNeuron(), 0.001f);
			}

			const std::vector<unsigned>& fired = sim->step(firingStimulus, currentStimulus);
			nfired += fired.size();

			if(vprobe) {
				/* Just read a single value. The whole neuron population will be synced */
				v = sim->getMembranePotential(0);
			}

			if(stdpPeriod && t % stdpPeriod == 0) {
				sim->applyStdp(stdpReward);
			}
		}
	}
	long int elapsedWallclock = sim->elapsedWallclock();
	if(verbose)
		std::cout << "[" << elapsedWallclock << "ms elapsed]";
	if(verbose)
		std::cout << std::endl;

	unsigned long narrivals = nfired * m;
	double f = (double(nfired) / n) / double(seconds);

	/* Throughput is measured in terms of the number of spike arrivals per
	 * wall-clock second */
	unsigned long throughput = MS_PER_SECOND * narrivals / elapsedWallclock;
	double speedup = double(seconds*MS_PER_SECOND)/elapsedWallclock;

	if(verbose) {
		std::cout << "Total firings: " << nfired << std::endl;
		std::cout << "Avg. firing rate: " << f << "Hz\n";
		std::cout << "Spike arrivals: " << narrivals << std::endl;
		std::cout << "Approx. throughput: " << throughput/1000000
				<< "Ma/s (million spike arrivals per second)\n";
		std::cout << "Speedup wrt real-time: " << speedup << std::endl;
	}

	if(csv) {
		std::string sep = ", ";
		// raw data
		std::cout << n << sep << m << sep << seconds*MS_PER_SECOND
			<< sep << elapsedWallclock << sep << stdpPeriod << sep << nfired;
		// derived data. Not strictly needed, at least if out-degree is fixed.
		std::cout << sep << narrivals << sep << f << sep << speedup
			<< sep << throughput/1000000 << std::endl;
	}

	return elapsedWallclock;
}