Miind
MPINetworkCode.hpp
Go to the documentation of this file.
1 // Copyright (c) 2005 - 2012 Marc de Kamps
2 // 2012 David-Matthias Sichau
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
9 // and/or other materials provided with the distribution.
10 // * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software
11 // without specific prior written permission.
12 //
13 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
15 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
16 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 //
19 
20 #ifndef MPILIB_MPINETWORK_CODE_HPP_
21 #define MPILIB_MPINETWORK_CODE_HPP_
22 
23 //#include <MPILib/config.hpp>
24 #include <sstream>
25 #include <iostream>
26 #include <cassert>
27 #include <fstream>
37 
38 namespace MPILib {
39 
40 template<class WeightValue, class NodeDistribution>
42 }
43 
44 template<class WeightValue, class NodeDistribution>
46 }
47 
48 template<class WeightValue, class NodeDistribution>
51  NodeType nodeType) {
52 
53  assert(
54  nodeType == EXCITATORY_GAUSSIAN ||
55  nodeType == INHIBITORY_GAUSSIAN ||
56  nodeType == NEUTRAL ||
57  nodeType == EXCITATORY_DIRECT ||
58  nodeType == INHIBITORY_DIRECT);
59 
60  NodeId tempNodeId = getMaxNodeId();
61  if (_nodeDistribution.isLocalNode(tempNodeId)) {
63  NodeDistribution>(alg, nodeType, tempNodeId, _nodeDistribution,
64  _localNodes);
65  _localNodes.insert(std::make_pair(tempNodeId, node));
66  LOG(utilities::logDEBUG2) << "new node generated with id: "
67  << tempNodeId;
68  }
69 
70  nodeIdsType_[tempNodeId] = nodeType;
71 
72  //increment the max NodeId to make sure that it is not assigned twice.
73  incrementMaxNodeId();
74  // wait for all threads to finish
76  return tempNodeId;
77 }
78 
79 template<class WeightValue, class NodeDistribution>
81  NodeId first, NodeId second, const WeightValue& weight) {
82 
83  //Make sure that the node exists and then add the successor
84  if (_nodeDistribution.isLocalNode(first)) {
85  if (_localNodes.count(first) > 0) {
86  _localNodes.find(first)->second.addSuccessor(second);
88  << "make first input of second called first: " << first
89  << "; second: " << second;
90  } else {
91  std::stringstream tempStream;
92  tempStream << "the node " << first << "does not exist on this node";
93  miind_parallel_fail(tempStream.str());
94  }
95  }
96 
97  // Make sure the Dales Law holds
98  if (_nodeDistribution.isLocalNode(first)) {
99  if (isDalesLawSet()) {
100 
101  auto tempNode = _localNodes.find(first)->second;
102 
103  if ((IsExcitatory(tempNode.getNodeType()) && toEfficacy(weight) < 0)
104  || (IsInhibitory(tempNode.getNodeType())
105  && toEfficacy(weight) > 0)) {
106  throw utilities::Exception("Dale's law violated");
107 
108  }
109  }
110 
111  }
112 
113  // Make sure that the second node exist and then set the precursor
114  if (_nodeDistribution.isLocalNode(second)) {
115  if (_localNodes.count(second) > 0) {
116  _localNodes.find(second)->second.addPrecursor(first, weight,
117  nodeIdsType_[second]);
118  } else {
119  std::stringstream tempStream;
120  tempStream << "the node " << second
121  << "does not exist on this node";
122  miind_parallel_fail(tempStream.str());
123  }
124  }
125 
126 }
127 
128 template<class WeightValue, class NodeDistribution>
130  const SimulationRunParameter& simParam) {
131 
132  _i_report = 0;
133  _i_state = 0;
134  _i_simulation = 0;
135 
136  _parameterSimulationRun = simParam;
137 
138  _n_sim_steps = static_cast<unsigned long>(simParam.getTEnd()/simParam.getTStep());
139  _n_report_steps = static_cast<MPILib::Number>(simParam.getTReport()/simParam.getTStep());
140  _n_state_steps = static_cast<MPILib::Number>(simParam.getTState()/simParam.getTStep());
141 
142  this->initializeLogStream(simParam.getLogName());
143 
144  try {
145  //loop over all local nodes!
146  for (auto& it : _localNodes) {
147  it.second.configureSimulationRun(simParam);
148  }
149 
150  } catch (...) {
151  LOG(utilities::logERROR) << "error during configuration";
152  }
153  _stateNetwork.toggleConfigured();
154 }
155 
157 template<class WeightValue, class NodeDistribution>
159 
160  if (_stateNetwork.isConfigured()) {
161  _stateNetwork.toggleConfigured();
162 
163  LOG(utilities::logINFO) << "Starting simulation";
164  try {
165  // the report time must be taken as a hint if the network time step is larger (MdK: 31/08/2017)
166  long count = (_parameterSimulationRun.getTReport() < _parameterSimulationRun.getTStep()) ? \
167  static_cast<long>(_parameterSimulationRun.getTEnd()/_parameterSimulationRun.getTStep()) : \
168  static_cast<long>(_parameterSimulationRun.getTEnd()/_parameterSimulationRun.getTReport());
169 
170  utilities::ProgressBar pb(count);
171  do {
172  do {
173 
175  << "****** one evolve step finished ******";
176 
177  // business as usual: keep evolving, as long as there is nothing to report
178  // or to update
179  updateSimulationTime();
180 
182  for (auto& it : _localNodes)
183  it.second.prepareEvolve();
184 
185  Time t_current = getCurrentSimulationTime()*_parameterSimulationRun.getTStep();
186  //evolve all local nodes
187  for (auto& it : _localNodes)
188  it.second.evolve(t_current);
189 
190 
191  } while (getCurrentSimulationTime() < getCurrentReportTime()
192  && getCurrentSimulationTime() < getCurrentStateTime());
193 
194  // now there is something to report or to update
195  if (getCurrentSimulationTime() >= getCurrentReportTime()) {
196  // there is something to report
197  // CheckPercentageAndLog(CurrentSimulationTime());
198  collectReport(report::RATE);
199  updateReportTime();
200  pb++;
201  }
202 
203  // just a rate or also a state?
204  if (getCurrentSimulationTime() >= getCurrentStateTime()) {
205  // a rate as well as a state
206  collectReport(report::STATE);
207  updateStateTime();
208  }
209 
210 
211  } while (getCurrentSimulationTime() <= getEndTime()); // it is better to test on simulation time (22/04/2017) MdK
212  // write out the final state
213  collectReport(report::STATE);
214  }
215 
217  LOG(utilities::logWARNING) << "NUMBER OF ITERATIONS EXCEEDED\n";
218  _stateNetwork.setResult(NUMBER_ITERATIONS_ERROR);
219  }
220 
221  clearSimulation();
222  LOG(utilities::logINFO) << "Simulation ended, no problems noticed";
223  LOG(utilities::logINFO) << "End time: "
224  << getCurrentSimulationTime() << "\n";
225  }
226 
227 }
228 
229 template<class WeightValue, class NodeDistribution>
231  utilities::MPIProxy().broadcast(_maxNodeId, 0);
232  return _maxNodeId;
233 }
234 
235 template<class WeightValue, class NodeDistribution>
237  if (_nodeDistribution.isMaster()) {
238  _maxNodeId++;
239  }
240 }
241 
242 template<class WeightValue, class NodeDistribution>
244  report::ReportType type) {
245 
246  for (auto& it : _localNodes) {
247  it.second.reportAll(type);
248  }
249 }
250 
251 template<class WeightValue, class NodeDistribution>
253  const std::string & filename) {
254  // resource will be passed on to _stream_log
255  //only if filename is provided
256  if (!filename.empty()) {
257  std::shared_ptr<std::ostream> p_stream(
258  new std::ofstream(filename.c_str()));
259  if (!p_stream)
260  throw utilities::Exception("MPINetwork cannot open log file.");
261  utilities::Log::setStream(p_stream);
262  }
263 }
264 
265 template<class WeightValue, class NodeDistribution>
267 
268  for (auto& it : _localNodes) {
269  it.second.clearSimulation();
270  }
271 
272 }
273 
274 template<class WeightValue, class NodeDistribution>
276  return _isDalesLaw;
277 }
278 
279 template<class WeightValue, class NodeDistribution>
281  _isDalesLaw = b_law;
282 }
283 
284 template<class WeightValue, class NodeDistribution>
286  _i_report += _n_report_steps;
287 }
288 
289 template<class WeightValue, class NodeDistribution>
291  ++_i_simulation;
292 }
293 
294 template<class WeightValue, class NodeDistribution>
296  _i_state += _n_state_steps;
297 }
298 
299 template<class WeightValue, class NodeDistribution>
301  return _n_sim_steps;
302 }
303 
304 template<class WeightValue, class NodeDistribution>
306  return _i_report;
307 }
308 
309 template<class WeightValue, class NodeDistribution>
311  return _i_simulation;
312 }
313 
314 template<class WeightValue, class NodeDistribution>
316  return _i_state;
317 }
318 
319 template<class WeightValue, class NodeDistribution>
320 std::map<NodeId, MPINode<WeightValue, NodeDistribution>> MPINetwork<WeightValue,
321  NodeDistribution>::_localNodes;
322 
323 template<class WeightValue, class NodeDistribution>
325 
326 } //end namespace MPILib
327 
328 #endif //MPILIB_MPINETWORK_CODE_HPP_
NodeType
This determines an MPINode's type, which will be checked when Dale's law is set.
Definition: NodeType.hpp:31
void makeFirstInputOfSecond(NodeId first, NodeId second, const WeightValue &weight)
double toEfficacy(const DelayedConnection &connection)
Indicates that Dale's law should not be checked for this node.
Definition: NodeType.hpp:33
Class for nodes in an MPINetwork.
Definition: MPINode.hpp:51
bool isDalesLawSet() const
bool IsExcitatory(NodeType t)
Test for excitatoryness.
Definition: NodeType.hpp:39
Index getCurrentSimulationTime() const
int addNode(const AlgorithmInterface< WeightValue > &alg, NodeType nodeType)
void setDalesLaw(bool b_law)
void configureSimulation(const SimulationRunParameter &simParam)
#define LOG(level)
Definition: Log.hpp:225
bool IsInhibitory(NodeType t)
Test for inhibitoryness.
Definition: NodeType.hpp:42
unsigned int Number
unsigned int Index
double Time
The interface for all algorithm classes.
Check Dale's law; inhibitory; additive Gaussian noise.
Definition: NodeType.hpp:35
static void setStream(std::shared_ptr< std::ostream > pStream)
Definition: Log.cpp:87
#define miind_parallel_fail(ERROR_MESSAGE)
A representation of the network class. Probably the most central class that a client will use...
Definition: MPINetwork.hpp:126
Index getEndTime() const
unsigned int NodeId
Check Dale's law; excitatory; do not make any attempt to reinterpret input from this node...
Definition: NodeType.hpp:36
Parameter determining how a simulation is run. Specifiying begin and end time, log file names...
void initializeLogStream(const std::string &filename)
Indicates that Dale's law should be checked and that the contribution oof this excitatory node is to ...
Definition: NodeType.hpp:34
void collectReport(report::ReportType type)
static void waitAll()
Index getCurrentReportTime() const
Index getCurrentStateTime() const
MPIProxy_ & MPIProxy()
Definition: MPIProxy.hpp:176
void evolve()
Envolve the network.