PetaVision  Alpha
PVParams.hpp
1 /*
2  * PVParams.hpp
3  *
4  * Created on: Nov 27, 2008
5  * Author: rasmussn
6  */
7 
8 #ifndef PVPARAMS_HPP_
9 #define PVPARAMS_HPP_
10 
11 #include "columns/Communicator.hpp"
12 #include "fileio.hpp"
13 #include "include/pv_common.h"
14 #include "io.hpp"
15 #include "utils/PVAssert.hpp"
16 #include "utils/PVLog.hpp"
17 #include <cstdio>
18 #include <cstring>
19 #include <limits>
20 #include <sstream>
21 
22 // TODO - make MAX_PARAMS dynamic
23 #define MAX_PARAMS 100 // maximum number of parameters in a group
24 
25 #undef HAS_MAIN // define if provides a main function
26 
27 namespace PV {
28 
29 class Parameter {
30  public:
31  Parameter(const char *name, double value);
32  virtual ~Parameter();
33 
34  const char *name() { return paramName; }
35  double value() {
36  hasBeenReadFlag = true;
37  return paramDblValue;
38  }
39  const float *valuePtr() {
40  hasBeenReadFlag = true;
41  return &paramValue;
42  }
43  const double *valueDblPtr() {
44  hasBeenReadFlag = true;
45  return &paramDblValue;
46  }
47  bool hasBeenRead() { return hasBeenReadFlag; }
48  void clearHasBeenRead() { hasBeenReadFlag = false; }
49  void setValue(double v) {
50  paramValue = (float)v;
51  paramDblValue = v;
52  }
53  Parameter *copyParameter() { return new Parameter(paramName, paramDblValue); }
54 
55  private:
56  char *paramName;
57  float paramValue;
58  double paramDblValue;
59  bool hasBeenReadFlag;
60 };
61 
63  public:
64  ParameterArray(int initialSize);
65  virtual ~ParameterArray();
66  int getArraySize() { return arraySize; }
67  const char *name() { return paramName; }
68  int setName(const char *name);
69  const float *getValues(int *sz) {
70  hasBeenReadFlag = true;
71  *sz = arraySize;
72  return values;
73  }
74  const double *getValuesDbl(int *sz) {
75  hasBeenReadFlag = true;
76  *sz = arraySize;
77  return valuesDbl;
78  }
79  int pushValue(double value);
80  void resetArraySize() { arraySize = 0; }
81  bool hasBeenRead() { return hasBeenReadFlag; }
82  void clearHasBeenRead() { hasBeenReadFlag = false; }
83  double peek(int index) { return valuesDbl[index]; }
84  ParameterArray *copyParameterArray();
85 
86  private:
87  bool paramNameSet;
88  char *paramName;
89  int arraySize; // The number of values that have been pushed
90  int bufferSize; // The size of the buffer in memory
91  double *valuesDbl;
92  float *values;
93  bool hasBeenReadFlag;
94 };
95 
97  public:
98  ParameterString(const char *name, const char *value);
99  virtual ~ParameterString();
100 
101  const char *getName() { return paramName; }
102  const char *getValue() {
103  hasBeenReadFlag = true;
104  return paramValue;
105  }
106  bool hasBeenRead() { return hasBeenReadFlag; }
107  void clearHasBeenRead() { hasBeenReadFlag = false; }
108  void setValue(const char *s) {
109  free(paramValue);
110  paramValue = s ? strdup(s) : NULL;
111  }
112  ParameterString *copyParameterString() { return new ParameterString(paramName, paramValue); }
113 
114  private:
115  char *paramName;
116  char *paramValue;
117  bool hasBeenReadFlag;
118 };
119 
121  public:
122  ParameterStack(int maxCount);
123  virtual ~ParameterStack();
124 
125  int push(Parameter *param);
126  Parameter *pop();
127  Parameter *peek(int index) { return parameters[index]; }
128  int size() { return count; }
129 
130  private:
131  int count;
132  int maxCount;
133  Parameter **parameters;
134 };
135 
137  public:
138  ParameterArrayStack(int initialCount);
139  virtual ~ParameterArrayStack();
140  int push(ParameterArray *array);
141  int size() { return count; }
142  ParameterArray *peek(int index) {
143  return index >= 0 && index < count ? parameterArrays[index] : NULL;
144  }
145 
146  private:
147  int count; // Number of ParameterArrays
148  int allocation; // Size of buffer
149  ParameterArray **parameterArrays;
150 };
151 
153  public:
154  ParameterStringStack(int initialCount);
155  virtual ~ParameterStringStack();
156 
157  int push(ParameterString *param);
158  ParameterString *pop();
159  ParameterString *peek(int index) {
160  return index >= 0 && index < count ? parameterStrings[index] : NULL;
161  }
162  int size() { return count; }
163  const char *lookup(const char *targetname);
164 
165  private:
166  int count;
167  int allocation;
168  ParameterString **parameterStrings;
169 };
170 
172  public:
174  char *name,
175  ParameterStack *stack,
176  ParameterArrayStack *array_stack,
177  ParameterStringStack *string_stack,
178  int rank = 0);
179  virtual ~ParameterGroup();
180 
181  const char *name() { return groupName; }
182  const char *getGroupKeyword() { return groupKeyword; }
183  int setGroupKeyword(const char *keyword);
184  int setStringStack(ParameterStringStack *stringStack);
185  int present(const char *name);
186  double value(const char *name);
187  bool arrayPresent(const char *name);
188  const float *arrayValues(const char *name, int *size);
189  const double *arrayValuesDbl(const char *name, int *size);
190  int stringPresent(const char *stringName);
191  const char *stringValue(const char *stringName);
192  int warnUnread();
193  bool hasBeenRead(const char *paramName);
194  int clearHasBeenReadFlags();
195  int pushNumerical(Parameter *param);
196  int pushString(ParameterString *param);
197  int setValue(const char *param_name, double value);
198  int setStringValue(const char *param_name, const char *svalue);
199  ParameterStack *copyStack();
200  ParameterArrayStack *copyArrayStack();
201  ParameterStringStack *copyStringStack();
202 
203  private:
204  char *groupName;
205  char *groupKeyword;
206  ParameterStack *stack;
207  ParameterArrayStack *arrayStack;
208  ParameterStringStack *stringStack;
209  int processRank;
210 };
211 
212 enum SweepType { SWEEP_UNDEF = 0, SWEEP_NUMBER = 1, SWEEP_STRING = 2 };
213 
215  public:
216  ParameterSweep();
217  virtual ~ParameterSweep();
218 
219  int setGroupAndParameter(const char *groupname, const char *paramname);
220  int pushNumericValue(double val);
221  int pushStringValue(const char *sval);
222  int getNumValues() { return numValues; }
223  SweepType getType() { return type; }
224  int getNumericValue(int n, double *val);
225  const char *getStringValue(int n);
226  const char *getGroupName() { return groupName; }
227  const char *getParamName() { return paramName; }
228 
229  private:
230  char *groupName;
231  char *paramName;
232  SweepType type;
233  int numValues;
234  int currentBufferSize;
235  double *valuesNumber;
236  char **valuesString;
237 };
238 
239 class PVParams {
240  public:
241  PVParams(size_t initialSize, Communicator *inIcComm);
242  PVParams(const char *filename, size_t initialSize, Communicator *inIcComm);
243  PVParams(const char *buffer, long int bufferLength, size_t initialSize, Communicator *inIcComm);
244  virtual ~PVParams();
245 
246  bool getParseStatus() { return parseStatus; }
247 
248  template <typename T>
249  void ioParamValueRequired(
250  enum ParamsIOFlag ioFlag,
251  const char *groupName,
252  const char *paramName,
253  T *val);
254  template <typename T>
255  void ioParamValue(
256  enum ParamsIOFlag ioFlag,
257  const char *groupName,
258  const char *paramName,
259  T *val,
260  T defaultValue,
261  bool warnIfAbsent = true);
262  void ioParamString(
263  enum ParamsIOFlag ioFlag,
264  const char *groupName,
265  const char *paramName,
266  char **paramStringValue,
267  const char *defaultValue,
268  bool warnIfAbsent = true);
269 
270  void ioParamStringRequired(
271  enum ParamsIOFlag ioFlag,
272  const char *groupName,
273  const char *paramName,
274  char **paramStringValue);
275  template <typename T>
276  void ioParamArray(
277  enum ParamsIOFlag ioFlag,
278  const char *groupName,
279  const char *paramName,
280  T **paramArrayValue,
281  int *arraysize);
282  template <typename T>
283  void writeParam(const char *paramName, T paramValue);
284  template <typename T>
285  void writeParamArray(const char *paramName, const T *array, int arraysize);
286  void writeParamString(const char *paramName, const char *svalue);
287 
288  int present(const char *groupName, const char *paramName);
289  double value(const char *groupName, const char *paramName);
290  double
291  value(const char *groupName,
292  const char *paramName,
293  double initialValue,
294  bool warnIfAbsent = true);
295  int valueInt(const char *groupName, const char *paramName);
296  int valueInt(
297  const char *groupName,
298  const char *paramName,
299  int initialValue,
300  bool warnIfAbsent = true);
301  bool arrayPresent(const char *groupName, const char *paramName);
302  const float *arrayValues(
303  const char *groupName,
304  const char *paramName,
305  int *arraySize,
306  bool warnIfAbsent = true);
307  const double *arrayValuesDbl(
308  const char *groupName,
309  const char *paramName,
310  int *arraySize,
311  bool warnIfAbsent = true);
312  int stringPresent(const char *groupName, const char *paramStringName);
313  const char *
314  stringValue(const char *groupName, const char *paramStringName, bool warnIfAbsent = true);
315  ParameterGroup *group(const char *groupName);
316  const char *groupNameFromIndex(int index);
317  const char *groupKeywordFromIndex(int index);
318  const char *groupKeywordFromName(const char *name);
319  int warnUnread();
320  bool hasBeenRead(const char *group_name, const char *param_name);
321  bool presentAndNotBeenRead(const char *group_name, const char *param_name);
322  void handleUnnecessaryParameter(const char *group_name, const char *param_name);
323  template <typename T>
324  void handleUnnecessaryParameter(const char *group_name, const char *param_name, T correct_value);
325 
331  void handleUnnecessaryStringParameter(const char *group_name, const char *param_name);
332 
341  void handleUnnecessaryStringParameter(
342  const char *group_name,
343  const char *param_name,
344  const char *correctValue,
345  bool case_insensitive_flag = false);
346 
347  void setPrintLuaStream(FileStream *printLuaStream) { mPrintLuaStream = printLuaStream; }
348  void setPrintParamsStream(FileStream *printParamsStream) {
349  mPrintParamsStream = printParamsStream;
350  }
351  int setParameterSweepValues(int n);
352 
353  void action_pvparams_directive(char *id, double val);
354  void action_parameter_group_name(char *keyword, char *name);
355  void action_parameter_group();
356  void action_parameter_def(char *id, double val);
357  void action_parameter_def_overwrite(char *id, double val);
358  void action_parameter_array(char *id);
359  void action_parameter_array_overwrite(char *id);
360  void action_parameter_array_value(double val);
361  void action_parameter_string_def(const char *id, const char *stringval);
362  void action_parameter_string_def_overwrite(const char *id, const char *stringval);
363  void action_parameter_filename_def(const char *id, const char *stringval);
364  void action_parameter_filename_def_overwrite(const char *id, const char *stringval);
365  void action_include_directive(const char *stringval);
366 
367  void action_parameter_sweep_open(const char *groupname, const char *paramname);
368  void action_parameter_sweep_close();
369  void action_parameter_sweep_values_number(double val);
370  void action_parameter_sweep_values_string(const char *stringval);
371  void action_parameter_sweep_values_filename(const char *stringval);
372 
373  int numberOfGroups() { return numGroups; }
374  int numberOfParameterSweeps() { return numParamSweeps; }
375  int getParameterSweepSize() { return parameterSweepSize; }
376 
377  private:
378  int parseStatus;
379  int numGroups;
380  size_t groupArraySize;
381  ParameterGroup **groups;
382  ParameterStack *stack;
383  ParameterArrayStack *arrayStack;
384  ParameterStringStack *stringStack;
385  bool debugParsing;
386  bool disable;
387  Communicator *icComm;
388  int worldRank;
389  int worldSize;
390 
391  ParameterArray *currentParamArray;
392 
393  int numParamSweeps; // The number of different parameters that are changed during the sweep.
394  ParameterSweep **paramSweeps;
395  ParameterSweep *activeParamSweep;
396  int parameterSweepSize; // The number of parameter value sets in the sweep. Each ParameterSweep
397  // group in the params file must contain the same number of values, which
398  // is sweepSize.
399 
400  char *currGroupKeyword;
401  char *currGroupName;
402 
403  char *currSweepGroupName;
404  char *currSweepParamName;
405 
406  FileStream *mPrintParamsStream = nullptr;
407  FileStream *mPrintLuaStream = nullptr;
408 
409  int initialize(size_t initialSize);
410  int parseFile(const char *filename);
411  void loadParamBuffer(char const *filename, std::string &paramsFileString);
412  int parseBuffer(const char *buffer, long int bufferLength);
413  int setParameterSweepSize();
414  void addGroup(char *keyword, char *name);
415  void addActiveParamSweep(const char *group_name, const char *param_name);
416  void checkDuplicates(const char *paramName);
417  int newActiveParamSweep();
418  int clearHasBeenReadFlags();
419  static char *stripQuotationMarks(const char *s);
420  static char *stripOverwriteTag(const char *s);
421  bool hasSweepValue(const char *paramName);
422  int convertParamToInt(double value);
423 };
424 
425 template <typename T>
426 void PVParams::handleUnnecessaryParameter(
427  const char *group_name,
428  const char *param_name,
429  T correct_value) {
430  int status = PV_SUCCESS;
431  if (present(group_name, param_name)) {
432  if (worldRank == 0) {
433  const char *class_name = groupKeywordFromName(group_name);
434  WarnLog().printf(
435  "%s \"%s\" does not use parameter %s, but it is present in the parameters file.\n",
436  class_name,
437  group_name,
438  param_name);
439  }
440  T params_value = (T)value(
441  group_name,
442  param_name); // marks param as read so that presentAndNotBeenRead doesn't trip up
443  if (params_value != correct_value) {
444  status = PV_FAILURE;
445  if (worldRank == 0) {
446  ErrorLog() << " Value " << params_value << " is inconsistent with correct value "
447  << correct_value << std::endl;
448  }
449  }
450  }
451  MPI_Barrier(icComm->globalCommunicator());
452  if (status != PV_SUCCESS)
453  exit(EXIT_FAILURE);
454 }
455 
456 template <typename T>
457 void PVParams::ioParamValueRequired(
458  enum ParamsIOFlag ioFlag,
459  const char *groupName,
460  const char *paramName,
461  T *paramValue) {
462  switch (ioFlag) {
463  case PARAMS_IO_READ: *paramValue = (T)value(groupName, paramName); break;
464  case PARAMS_IO_WRITE: writeParam(paramName, *paramValue); break;
465  }
466 }
467 
468 template <typename T>
469 void PVParams::ioParamValue(
470  enum ParamsIOFlag ioFlag,
471  const char *groupName,
472  const char *paramName,
473  T *paramValue,
474  T defaultValue,
475  bool warnIfAbsent) {
476  switch (ioFlag) {
477  case PARAMS_IO_READ:
478  *paramValue = (T)value(groupName, paramName, defaultValue, warnIfAbsent);
479  break;
480  case PARAMS_IO_WRITE: writeParam(paramName, *paramValue); break;
481  }
482 }
483 template <typename T>
484 void PVParams::ioParamArray(
485  enum ParamsIOFlag ioFlag,
486  const char *groupName,
487  const char *paramName,
488  T **paramArrayValue,
489  int *arraysize) {
490  if (ioFlag == PARAMS_IO_READ) {
491  const double *paramArray = arrayValuesDbl(groupName, paramName, arraysize);
492  pvAssert(*arraysize >= 0);
493  if (*arraysize > 0) {
494  *paramArrayValue = (T *)calloc((size_t)*arraysize, sizeof(T));
495  FatalIf(
496  paramArrayValue == nullptr,
497  "%s \"%s\": global rank %d process unable to copy array parameter %s: %s\n",
498  groupKeywordFromName(groupName),
499  groupName,
500  icComm->globalCommRank(),
501  paramName,
502  strerror(errno));
503  for (int k = 0; k < *arraysize; k++) {
504  (*paramArrayValue)[k] = (T)paramArray[k];
505  }
506  }
507  else {
508  *paramArrayValue = nullptr;
509  }
510  }
511  else if (ioFlag == PARAMS_IO_WRITE) {
512  writeParamArray(paramName, *paramArrayValue, *arraysize);
513  }
514 }
515 
516 template <typename T>
517 void PVParams::writeParam(const char *paramName, T paramValue) {
518  if (mPrintParamsStream) {
519  pvAssert(mPrintLuaStream);
520  std::stringstream vstr("");
521  if (std::numeric_limits<T>::has_infinity) {
522  if (paramValue == std::numeric_limits<T>::min()) {
523  vstr << "-infinity";
524  }
525  else if (paramValue == std::numeric_limits<T>::max()) {
526  vstr << "infinity";
527  }
528  else {
529  vstr << paramValue;
530  }
531  }
532  else {
533  vstr << paramValue;
534  }
535  mPrintParamsStream->printf(" %-35s = %s;\n", paramName, vstr.str().c_str());
536  mPrintLuaStream->printf(" %-35s = %s;\n", paramName, vstr.str().c_str());
537  }
538 }
539 
540 template <typename T>
541 void PVParams::writeParamArray(const char *paramName, const T *array, int arraysize) {
542  if (mPrintParamsStream) {
543  pvAssert(mPrintLuaStream != nullptr);
544  pvAssert(arraysize >= 0);
545  if (arraysize > 0) {
546  mPrintParamsStream->printf(" %-35s = [", paramName);
547  mPrintLuaStream->printf(" %-35s = {", paramName);
548  for (int k = 0; k < arraysize - 1; k++) {
549  mPrintParamsStream->printf("%f,", (double)array[k]);
550  mPrintLuaStream->printf("%f,", (double)array[k]);
551  }
552  mPrintParamsStream->printf("%f];\n", (double)array[arraysize - 1]);
553  mPrintLuaStream->printf("%f};\n", (double)array[arraysize - 1]);
554  }
555  }
556 }
557 
558 } // end namespace PV
559 
560 #endif /* PVPARAMS_HPP_ */