GammaLib  2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GOptimizerPar.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GOptimizerPar.cpp - Optimizer parameter class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2013-2020 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GOptimizerPar.cpp
23  * @brief Optimizer parameter class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GException.hpp"
32 #include "GOptimizerPar.hpp"
33 #include "GTools.hpp"
34 
35 /* __ Method name definitions ____________________________________________ */
36 #define G_CONSTRUCT "GOptimizerPar::GOptimizerPar(std::string&, double&,"\
37  " double&)"
38 #define G_MIN "GOptimizerPar::min(double&)"
39 #define G_MAX "GOptimizerPar::max(double&)"
40 #define G_FACTOR_VALUE "GOptimizerPar::factor_value(double&)"
41 #define G_FACTOR_MIN "GOptimizerPar::factor_min(double&)"
42 #define G_FACTOR_MAX "GOptimizerPar::factor_max(double&)"
43 #define G_SCALE "GOptimizerPar::scale(double&)"
44 
45 /* __ Macros _____________________________________________________________ */
46 
47 /* __ Coding definitions _________________________________________________ */
48 
49 /* __ Debug definitions __________________________________________________ */
50 
51 
52 /*==========================================================================
53  = =
54  = Constructors/destructors =
55  = =
56  ==========================================================================*/
57 
58 /***********************************************************************//**
59  * @brief Void constructor
60  ***************************************************************************/
62 {
63  // Initialise members
64  init_members();
65 
66  // Return
67  return;
68 }
69 
70 
71 /***********************************************************************//**
72  * @brief Parameter constructor
73  *
74  * @param[in] name Parameter name.
75  * @param[in] value Parameter value.
76  *
77  * Constructs a parameter from a parameter @p name and a parameter @p value.
78  *
79  * The parameter is auto-scaled, which for a @p value that differs from zero
80  * sets the scale factor to @p value and the @p factor_value to unity. For a
81  * @p value of zero, the scale factor will be set to unity and the
82  * @p factor_value will be set to @p value.
83  ***************************************************************************/
84 GOptimizerPar::GOptimizerPar(const std::string& name, const double& value)
85 {
86  // Initialise members
87  init_members();
88 
89  // Set name attribute
90  m_name = name;
91 
92  // Set auto-scaled factor and scale attributes
93  if (value != 0.0) {
94  m_factor_value = 1.0;
95  m_scale = value;
96  }
97  else {
99  m_scale = 1.0;
100  }
101 
102  // Return
103  return;
104 }
105 
106 
107 /***********************************************************************//**
108  * @brief Parameter constructor
109  *
110  * @param[in] name Parameter name.
111  * @param[in] factor Parameter value factor.
112  * @param[in] scale Parameter scaling (non-zero value).
113  *
114  * @exception GException::invalid_argument
115  * Sacle factor of 0 specified.
116  *
117  * Constructs a parameter from a parameter @p name, value @p factor
118  * and @p scale factor. The @p scale factor needs to be a non-zero value.
119  * If the @p scale factor is zero, an exception is thrown.
120  ***************************************************************************/
121 GOptimizerPar::GOptimizerPar(const std::string& name,
122  const double& factor,
123  const double& scale)
124 {
125  // Make sure that scale is not zero
126  if (scale == 0.0) {
127  std::string msg = "Specified a parameter scale factor of 0.\n"
128  "Parameters need a non-zero scale factor.";
130  }
131 
132  // Initialise members
133  init_members();
134 
135  // Set attributes
136  m_name = name;
137  m_factor_value = factor;
138  m_scale = scale;
139 
140  // Return
141  return;
142 }
143 
144 
145 /***********************************************************************//**
146  * @brief Copy constructor
147  *
148  * @param[in] par Function parameter.
149  ***************************************************************************/
151 {
152  // Initialise members
153  init_members();
154 
155  // Copy members
156  copy_members(par);
157 
158  // Return
159  return;
160 }
161 
162 
163 /***********************************************************************//**
164  * @brief Destructor
165  ***************************************************************************/
167 {
168  // Free members
169  free_members();
170 
171  // Return
172  return;
173 }
174 
175 
176 /*==========================================================================
177  = =
178  = Operators =
179  = =
180  ==========================================================================*/
181 
182 /***********************************************************************//**
183  * @brief Assignment operator
184  *
185  * @param[in] par Function parameter.
186  * @return Function parameter.
187  ***************************************************************************/
189 {
190  // Execute only if object is not identical
191  if (this != &par) {
192 
193  // Free members
194  free_members();
195 
196  // Initialise members
197  init_members();
198 
199  // Copy members
200  copy_members(par);
201 
202  } // endif: object was not identical
203 
204  // Return
205  return *this;
206 }
207 
208 
209 /*==========================================================================
210  = =
211  = Public methods =
212  = =
213  ==========================================================================*/
214 
215 /***********************************************************************//**
216  * @brief Clear parameter
217  *
218  * Resets parameter to a clean initial state.
219  ***************************************************************************/
221 {
222  // Free class members
223  free_members();
224 
225  // Initialise members
226  init_members();
227 
228  // Return
229  return;
230 }
231 
232 
233 /***********************************************************************//**
234  * @brief Clone parameter
235  *
236  * @return Pointer to deep copy of parameter.
237  ***************************************************************************/
239 {
240  // Clone parameter
241  return new GOptimizerPar(*this);
242 }
243 
244 
245 /***********************************************************************//**
246  * @brief Set parameter value
247  *
248  * @param[in] value Parameter value.
249  *
250  * Sets the parameter value. The method stores the value factor which is
251  * obtained by dividing the @p value by the scale factor.
252  *
253  * The method calls factor_value() for assigning the value factor, and this
254  * method will verify that the value lies within the specified boundaries.
255  ***************************************************************************/
256 void GOptimizerPar::value(const double& value)
257 {
258  // Set value factor. The GOptimizerPar class makes sure that m_scale is
259  // never 0, so no test is needed here
260  factor_value(value / m_scale);
261 
262  // Return
263  return;
264 }
265 
266 
267 /***********************************************************************//**
268  * @brief Set parameter error
269  *
270  * @param[in] error Parameter error.
271  *
272  * Sets the parameter error. The method stores the error factor which is
273  * obtained by dividing the @p error by the scale factor.
274  ***************************************************************************/
275 void GOptimizerPar::error(const double& error)
276 {
277  // Set error factor. The GOptimizerPar class makes sure that m_scale is
278  // never 0, so no test is needed here
279  factor_error(error / m_scale);
280 
281  // Return
282  return;
283 }
284 
285 
286 /***********************************************************************//**
287  * @brief Set parameter gradient
288  *
289  * @param[in] gradient Parameter gradient.
290  *
291  * Sets the parameter gradient. The method stores the gradient factor which
292  * is obtained by multiplying @p gradient by the scale factor.
293  ***************************************************************************/
294 void GOptimizerPar::gradient(const double& gradient)
295 {
296  // Set gradient factor.
297  factor_gradient(gradient * m_scale);
298 
299  // Return
300  return;
301 }
302 
303 
304 /***********************************************************************//**
305  * @brief Set minimum parameter boundary
306  *
307  * @param[in] min Minimum parameter boundary.
308  *
309  * @exception GException::invalid_argument
310  * Minimum parameter boundary is larger than the parameter value
311  *
312  * Sets the minimum parameter boundary.
313  ***************************************************************************/
314 void GOptimizerPar::min(const double& min)
315 {
316  // Check if minimum is larger than value
317  if (min > value()) {
318  std::string msg = "Specified minimum parameter value "+
319  gammalib::str(min)+" is larger than the parameter "
320  "value "+gammalib::str(value())+".";
322  }
323 
324  // If scale is negative then set maximum factor boundary
325  if (m_scale < 0) {
326  m_factor_max = min / m_scale;
327  m_has_factor_max = true;
328  }
329 
330  // ... otherwise set minimum factor boundary
331  else {
332  m_factor_min = min / m_scale;
333  m_has_factor_min = true;
334  }
335 
336  // Return
337  return;
338 }
339 
340 
341 /***********************************************************************//**
342  * @brief Set maximum parameter boundary
343  *
344  * @param[in] max Maximum parameter boundary.
345  *
346  * @exception GException::invalid_argument
347  * Maximum parameter boundary is smaller than the parameter value
348  *
349  * Sets the maximum parameter boundary.
350  ***************************************************************************/
351 void GOptimizerPar::max(const double& max)
352 {
353  // Check if maximum is smaller than value
354  if (max < value()) {
355  std::string msg = "Specified maximum parameter value "+
356  gammalib::str(max)+" is smaller than the parameter "
357  "value "+gammalib::str(value())+".";
359  }
360 
361  // If scale is negative then set minimum factor boundary
362  if (m_scale < 0) {
363  m_factor_min = max / m_scale;
364  m_has_factor_min = true;
365  }
366 
367  // ... otherwise set maximum factor boundary
368  else {
369  m_factor_max = max / m_scale;
370  m_has_factor_max = true;
371  }
372 
373  // Return
374  return;
375 }
376 
377 
378 /***********************************************************************//**
379  * @brief Set parameter value factor
380  *
381  * @param[in] value Value factor.
382  *
383  * @exception GException::invalid_argument
384  * Parameter @p value outside [min,max] boundaries.
385  *
386  * Sets the value factor of the parameter. The method makes sure that
387  * none of the boundaries is violated. Otherwise, exceptions are thrown.
388  ***************************************************************************/
389 void GOptimizerPar::factor_value(const double& value)
390 {
391  // If there is a minimum boundary and if value is below this boundary
392  // then throw an exception
393  if (has_factor_min() && (value < factor_min())) {
394  std::string msg = "Specified value factor "+gammalib::str(value)+
395  " is smaller than the minimum boundary "+
396  gammalib::str(factor_min())+".";
398  }
399 
400  // If there is a maximum boundary and if value is above this boundary
401  // then throw an exception
402  if (has_factor_max() && (value > factor_max())) {
403  std::string msg = "Specified value factor "+gammalib::str(value)+
404  " is larger than the maximum boundary "+
405  gammalib::str(factor_max())+".";
407  }
408 
409  // Assign value
411 
412  // Return
413  return;
414 }
415 
416 
417 /***********************************************************************//**
418  * @brief Set minimum parameter boundary factor
419  *
420  * @param[in] min Minimum parameter boundary factor.
421  *
422  * @exception GException::invalid_argument
423  * Minimum parameter boundary factor larger than value factor.
424  *
425  * Sets the minimum boundary factor of the parameter. The method makes
426  * sure that the minimum is not larger than the actual value factor.
427  * Otherwise, an exception is thrown.
428  ***************************************************************************/
429 void GOptimizerPar::factor_min(const double& min)
430 {
431  // Check if minimum is larger than value
432  if (min > m_factor_value) {
433  std::string msg = "Specified minimum factor "+gammalib::str(min)+
434  " is larger than the value factor "+
437  }
438 
439  // Set value and flag
440  m_factor_min = min;
441  m_has_factor_min = true;
442 
443  // Return
444  return;
445 }
446 
447 
448 /***********************************************************************//**
449  * @brief Set maximum parameter boundary factor
450  *
451  * @param[in] max Maximum parameter boundary factor.
452  *
453  * @exception GException::invalid_argument
454  * Maximum parameter boundary factor smaller than value factor.
455  *
456  * Sets the maximum boundary factor of the parameter. The method makes
457  * sure that the maximum is not smaller than the actual value factor.
458  * Otherwise, an exception is thrown.
459  ***************************************************************************/
460 void GOptimizerPar::factor_max(const double& max)
461 {
462  // Check if maximum is smaller than value
463  if (max < m_factor_value) {
464  std::string msg = "Specified maximum factor "+gammalib::str(max)+
465  " is smaller than the value factor "+
468  }
469 
470  // Set value and flag
471  m_factor_max = max;
472  m_has_factor_max = true;
473 
474  // Return
475  return;
476 }
477 
478 
479 /***********************************************************************//**
480  * @brief Set minimum and maximum parameter boundary factors
481  *
482  * @param[in] min Minimum parameter boundary factor.
483  * @param[in] max Maximum parameter boundary factor.
484  *
485  * Sets the minimum and maximum parameter boundary factors. The method calls
486  * the factor_min() and factor_max() methods which perform validity checking
487  * of the arguments.
488  ***************************************************************************/
489 void GOptimizerPar::factor_range(const double& min, const double& max)
490 {
491  // Set minimum and maximum
492  factor_min(min);
493  factor_max(max);
494 
495  // Return
496  return;
497 }
498 
499 
500 /***********************************************************************//**
501  * @brief Set scale factor
502  *
503  * @param[in] scale Scale factor.
504  *
505  * @exception GException::invalid_argument
506  * Sacle factor of 0 specified.
507  *
508  * Sets the scale factor of the parameter. All parameter attributes are
509  * rescaled accordingly.
510  *
511  * An exception is thrown if a scale factor of 0 is specified.
512  ***************************************************************************/
513 void GOptimizerPar::scale(const double& scale)
514 {
515  // Make sure that scale is not zero
516  if (scale == 0.0) {
517  std::string msg = "Specified parameter scale factor of 0.\n"
518  "Parameters need a non-zero scale factor.";
520  }
521 
522  // Set rescaling
523  double rescale = m_scale/scale;
524 
525  // Set new scale factor
526  m_scale = scale;
527 
528  // Set values, error, gradient, min and max
529  m_factor_value *= rescale;
530  m_factor_error *= rescale;
531  m_factor_gradient /= rescale;
532  m_factor_min *= rescale;
533  m_factor_max *= rescale;
534 
535  // If re-scaling changes sign then swap minimum and maximum boundary
536  if (rescale < 0.0) {
537 
538  // Store maximum in swap space
539  bool bswap = m_has_factor_max;
540  double dswap = m_factor_max;
541 
542  // Set maximum
545 
546  // Set minimum
547  m_has_factor_min = bswap;
548  m_factor_min = dswap;
549  }
550 
551  // Return
552  return;
553 }
554 
555 
556 /***********************************************************************//**
557  * @brief Autoscale parameter
558  *
559  * Sets the value factor to unity and the scale factor to the real value
560  * of the parameter. The method will also adjust the error factor and
561  * gradient factor, as well as the minimum and maximum factors if they
562  * exist.
563  *
564  * The method does nothing if the actual value factor is zero.
565  ***************************************************************************/
567 {
568  // Get value
569  double value = this->value();
570 
571  // Continue only if the value is non-zero
572  if (value != 0.0) {
573 
574  // Re-scale to value
575  this->scale(value);
576 
577  } // endif: value was non-zero
578 
579  // Return
580  return;
581 }
582 
583 
584 /***********************************************************************//**
585  * @brief Print parameter information
586  *
587  * @param[in] chatter Chattiness.
588  * @return String with parameter information.
589  ***************************************************************************/
590 std::string GOptimizerPar::print(const GChatter& chatter) const
591 {
592  // Initialise result string
593  std::string result;
594 
595  // Continue only if chatter is not silent
596  if (chatter != SILENT) {
597 
598  // Append parameter name
599  result.append(gammalib::parformat(" "+name()));
600 
601  // Append value
602  result.append(gammalib::str(value()));
603 
604  // For free parameters, append statistical uncertainty
605  if (m_free) {
606  result.append(" +/- "+gammalib::str(error()));
607  }
608 
609  // Append parameter limites if they exist
610  if (has_min() && has_max()) {
611  result.append(" ["+gammalib::str(min()) + ","+gammalib::str(max())+"]");
612  }
613  else if (has_min()) {
614  result.append(" ["+gammalib::str(min()) + ",infty[");
615  }
616  else if (has_max()) {
617  result.append(" ]-infty,"+gammalib::str(max())+"]");
618  }
619 
620  // Append parameter unit
621  result.append(" "+m_unit);
622 
623  // Signal if parameter was free or fixed
624  if (m_free) {
625  result.append(" (free");
626  }
627  else {
628  result.append(" (fixed");
629  }
630 
631  // Append parameter scale
632  result.append(",scale="+gammalib::str(m_scale));
633 
634  // Signal if parameter has analytic gradient
635  if (m_has_grad) {
636  result.append(",gradient)");
637  }
638  else {
639  result.append(")");
640  }
641 
642  } // endif: chatter was not silent
643 
644  // Return result
645  return result;
646 }
647 
648 
649 /*==========================================================================
650  = =
651  = Private methods =
652  = =
653  ==========================================================================*/
654 
655 /***********************************************************************//**
656  * @brief Initialise class members
657  ***************************************************************************/
659 {
660  // Initialise members
661  m_name.clear();
662  m_unit.clear();
663  m_factor_value = 0.0;
664  m_factor_error = 0.0;
665  m_factor_gradient = 0.0;
666  m_factor_min = 0.0;
667  m_factor_max = 0.0;
668  m_scale = 1.0;
669  m_free = true;
670  m_has_factor_min = false;
671  m_has_factor_max = false;
672  m_has_grad = false;
673 
674  // Return
675  return;
676 }
677 
678 
679 /***********************************************************************//**
680  * @brief Copy class members
681  *
682  * @param[in] par Model parameter.
683  ***************************************************************************/
685 {
686  // Copy members
687  m_name = par.m_name;
688  m_unit = par.m_unit;
694  m_scale = par.m_scale;
695  m_free = par.m_free;
698  m_has_grad = par.m_has_grad;
699 
700  // Return
701  return;
702 }
703 
704 
705 /***********************************************************************//**
706  * @brief Delete class members
707  ***************************************************************************/
709 {
710  // Return
711  return;
712 }
const double & factor_error(void) const
Return parameter factor error.
GOptimizerPar * clone(void) const
Clone parameter.
const double & factor_gradient(void) const
Return parameter factor gradient.
bool has_factor_max(void) const
Signal if parameter has maximum factor boundary.
const std::string & name(void) const
Return parameter name.
double gradient(void) const
Return parameter gradient.
bool m_free
Parameter is free.
void factor_range(const double &min, const double &max)
Set minimum and maximum parameter boundary factors.
GOptimizerPar(void)
Void constructor.
bool has_factor_min(void) const
Signal if parameter has minimum factor boundary.
double max(void) const
Return parameter maximum boundary.
#define G_FACTOR_VALUE
double m_factor_min
Parameter minimum factor value.
Gammalib tools definition.
bool m_has_grad
Parameter has analytic gradient.
#define G_SCALE
double min(const GVector &vector)
Computes minimum vector element.
Definition: GVector.cpp:886
std::string m_unit
Parameter unit.
double min(void) const
Return parameter minimum boundary.
const double & scale(void) const
Return parameter scale.
double m_scale
Parameter scaling (true = factor * scale)
const double & factor_max(void) const
Return parameter maximum factor boundary.
void autoscale(void)
Autoscale parameter.
GOptimizerPar & operator=(const GOptimizerPar &par)
Assignment operator.
double m_factor_value
Parameter factor value.
void clear(void)
Clear parameter.
#define G_MIN
double m_factor_error
Uncertainty in parameter factor value.
GChatter
Definition: GTypemaps.hpp:33
std::string m_name
Parameter name.
double m_factor_max
Parameter maximum factor value.
bool has_max(void) const
Signal if parameter has maximum boundary.
double max(const GVector &vector)
Computes maximum vector element.
Definition: GVector.cpp:915
void free_members(void)
Delete class members.
const double & factor_min(void) const
Return parameter minimum factor boundary.
void init_members(void)
Initialise class members.
#define G_CONSTRUCT
double value(void) const
Return parameter value.
bool has_min(void) const
Signal if parameter has minimum boundary.
Exception handler interface definition.
Optimizer parameter class interface definition.
bool m_has_factor_max
Parameter has maximum factor boundary.
double error(void) const
Return parameter error.
#define G_MAX
double m_factor_gradient
Function factor gradient.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
void copy_members(const GOptimizerPar &par)
Copy class members.
bool m_has_factor_min
Parameter has minimum factor boundary.
std::string print(const GChatter &chatter=NORMAL) const
Print parameter information.
const double & factor_value(void) const
Return parameter factor value.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
virtual ~GOptimizerPar(void)
Destructor.
Optimizer parameter class.