GammaLib  1.7.0.dev
 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-2017 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_FACTOR_VALUE "GOptimizerPar::factor_value(double&)"
39 #define G_FACTOR_MIN "GOptimizerPar::factor_min(double&)"
40 #define G_FACTOR_MAX "GOptimizerPar::factor_max(double&)"
41 #define G_SCALE "GOptimizerPar::scale(double&)"
42 
43 /* __ Macros _____________________________________________________________ */
44 
45 /* __ Coding definitions _________________________________________________ */
46 
47 /* __ Debug definitions __________________________________________________ */
48 
49 
50 /*==========================================================================
51  = =
52  = Constructors/destructors =
53  = =
54  ==========================================================================*/
55 
56 /***********************************************************************//**
57  * @brief Void constructor
58  ***************************************************************************/
60 {
61  // Initialise members
62  init_members();
63 
64  // Return
65  return;
66 }
67 
68 
69 /***********************************************************************//**
70  * @brief Parameter constructor
71  *
72  * @param[in] name Parameter name.
73  * @param[in] value Parameter value.
74  *
75  * Constructs a parameter from a parameter @p name and a parameter @p value.
76  *
77  * The parameter is auto-scaled, which for a @p value that differs from zero
78  * sets the scale factor to @p value and the @p factor_value to unity. For a
79  * @p value of zero, the scale factor will be set to unity and the
80  * @p factor_value will be set to @p value.
81  ***************************************************************************/
82 GOptimizerPar::GOptimizerPar(const std::string& name, const double& value)
83 {
84  // Initialise members
85  init_members();
86 
87  // Set name attribute
88  m_name = name;
89 
90  // Set auto-scaled factor and scale attributes
91  if (value != 0.0) {
92  m_factor_value = 1.0;
93  m_scale = value;
94  }
95  else {
97  m_scale = 1.0;
98  }
99 
100  // Return
101  return;
102 }
103 
104 
105 /***********************************************************************//**
106  * @brief Parameter constructor
107  *
108  * @param[in] name Parameter name.
109  * @param[in] factor Parameter value factor.
110  * @param[in] scale Parameter scaling (non-zero value).
111  *
112  * @exception GException::invalid_argument
113  * Sacle factor of 0 specified.
114  *
115  * Constructs a parameter from a parameter @p name, value @p factor
116  * and @p scale factor. The @p scale factor needs to be a non-zero value.
117  * If the @p scale factor is zero, an exception is thrown.
118  ***************************************************************************/
119 GOptimizerPar::GOptimizerPar(const std::string& name,
120  const double& factor,
121  const double& scale)
122 {
123  // Make sure that scale is not zero
124  if (scale == 0.0) {
125  std::string msg = "Specified a parameter scale factor of 0.\n"
126  "Parameters need a non-zero scale factor.";
128  }
129 
130  // Initialise members
131  init_members();
132 
133  // Set attributes
134  m_name = name;
135  m_factor_value = factor;
136  m_scale = scale;
137 
138  // Return
139  return;
140 }
141 
142 
143 /***********************************************************************//**
144  * @brief Copy constructor
145  *
146  * @param[in] par Function parameter.
147  ***************************************************************************/
149 {
150  // Initialise members
151  init_members();
152 
153  // Copy members
154  copy_members(par);
155 
156  // Return
157  return;
158 }
159 
160 
161 /***********************************************************************//**
162  * @brief Destructor
163  ***************************************************************************/
165 {
166  // Free members
167  free_members();
168 
169  // Return
170  return;
171 }
172 
173 
174 /*==========================================================================
175  = =
176  = Operators =
177  = =
178  ==========================================================================*/
179 
180 /***********************************************************************//**
181  * @brief Assignment operator
182  *
183  * @param[in] par Function parameter.
184  * @return Function parameter.
185  ***************************************************************************/
187 {
188  // Execute only if object is not identical
189  if (this != &par) {
190 
191  // Free members
192  free_members();
193 
194  // Initialise members
195  init_members();
196 
197  // Copy members
198  copy_members(par);
199 
200  } // endif: object was not identical
201 
202  // Return
203  return *this;
204 }
205 
206 
207 /*==========================================================================
208  = =
209  = Public methods =
210  = =
211  ==========================================================================*/
212 
213 /***********************************************************************//**
214  * @brief Clear parameter
215  *
216  * Resets parameter to a clean initial state.
217  ***************************************************************************/
219 {
220  // Free class members
221  free_members();
222 
223  // Initialise members
224  init_members();
225 
226  // Return
227  return;
228 }
229 
230 
231 /***********************************************************************//**
232  * @brief Clone parameter
233  *
234  * @return Pointer to deep copy of parameter.
235  ***************************************************************************/
237 {
238  // Clone parameter
239  return new GOptimizerPar(*this);
240 }
241 
242 
243 /***********************************************************************//**
244  * @brief Set parameter value
245  *
246  * @param[in] value Parameter value.
247  *
248  * Sets the parameter value. The method stores the value factor which is
249  * obtained by dividing the @p value by the scale factor.
250  *
251  * The method calls factor_value() for assigning the value factor, and this
252  * method will verify that the value lies within the specified boundaries.
253  ***************************************************************************/
254 void GOptimizerPar::value(const double& value)
255 {
256  // Set value factor. The GOptimizerPar class makes sure that m_scale is
257  // never 0, so no test is needed here
258  factor_value(value / m_scale);
259 
260  // Return
261  return;
262 }
263 
264 
265 /***********************************************************************//**
266  * @brief Set parameter error
267  *
268  * @param[in] error Parameter error.
269  *
270  * Sets the parameter error. The method stores the error factor which is
271  * obtained by dividing the @p error by the scale factor.
272  ***************************************************************************/
273 void GOptimizerPar::error(const double& error)
274 {
275  // Set error factor. The GOptimizerPar class makes sure that m_scale is
276  // never 0, so no test is needed here
277  factor_error(error / m_scale);
278 
279  // Return
280  return;
281 }
282 
283 
284 /***********************************************************************//**
285  * @brief Set parameter gradient
286  *
287  * @param[in] gradient Parameter gradient.
288  *
289  * Sets the parameter gradient. The method stores the gradient factor which
290  * is obtained by multiplying @p gradient by the scale factor.
291  ***************************************************************************/
292 void GOptimizerPar::gradient(const double& gradient)
293 {
294  // Set gradient factor.
295  factor_gradient(gradient * m_scale);
296 
297  // Return
298  return;
299 }
300 
301 
302 /***********************************************************************//**
303  * @brief Set minimum parameter boundary
304  *
305  * @param[in] min Parameter minimum.
306  *
307  * Sets the minimum parameter boundary. The method stores the minimum
308  * boundary factor which is obtained by dividing @p min by the scale factor.
309  ***************************************************************************/
310 void GOptimizerPar::min(const double& min)
311 {
312  // Set minimum boundary factor. The GOptimizerPar class makes sure that
313  // m_scale is never 0, so no test is needed here
314  factor_min(min / m_scale);
315 
316  // Return
317  return;
318 }
319 
320 
321 /***********************************************************************//**
322  * @brief Set maximum parameter boundary
323  *
324  * @param[in] max Parameter maximum.
325  *
326  * Sets the maximum parameter boundary. The method stores the maximum
327  * boundary factor which is obtained by dividing @p max by the scale factor.
328  ***************************************************************************/
329 void GOptimizerPar::max(const double& max)
330 {
331  // Set maximum boundary factor. The GOptimizerPar class makes sure that
332  // m_scale is never 0, so no test is needed here
333  factor_max(max / m_scale);
334 
335  // Return
336  return;
337 }
338 
339 
340 /***********************************************************************//**
341  * @brief Set minimum and maximum parameter boundaries
342  *
343  * @param[in] min Parameter minimum.
344  * @param[in] max Parameter maximum.
345  *
346  * Sets the minimum and maximum parameter boundaries. The method calls the
347  * min() and max() methods to set the boundaries.
348  ***************************************************************************/
349 void GOptimizerPar::range(const double& min, const double& max)
350 {
351  // Set minimum and maximum
352  this->min(min);
353  this->max(max);
354 
355  // Return
356  return;
357 }
358 
359 
360 /***********************************************************************//**
361  * @brief Set parameter value factor
362  *
363  * @param[in] value Value factor.
364  *
365  * @exception GException::invalid_argument
366  * Parameter @p value outside [min,max] boundaries.
367  *
368  * Sets the value factor of the parameter. The method makes sure that
369  * none of the boundaries is violated. Otherwise, exceptions are thrown.
370  ***************************************************************************/
371 void GOptimizerPar::factor_value(const double& value)
372 {
373  // If there is a minimum boundary and if value is below this boundary
374  // then throw an exception
375  if (m_has_min && value < m_factor_min) {
376  std::string msg = "Specified value factor "+gammalib::str(value)+
377  " is smaller than the minimum boundary "+
380  }
381 
382  // If there is a maximum boundary and if value is above this boundary
383  // then throw an exception
384  if (m_has_max && value > m_factor_max) {
385  std::string msg = "Specified value factor "+gammalib::str(value)+
386  " is larger than the maximum boundary "+
389  }
390 
391  // Assign value
393 
394  // Return
395  return;
396 }
397 
398 
399 /***********************************************************************//**
400  * @brief Set parameter minimum factor
401  *
402  * @param[in] min Minimum factor.
403  *
404  * @exception GException::invalid_argument
405  * Parameter @p min larger than value factor.
406  *
407  * Sets the minimum boundary factor of the parameter. The method makes
408  * sure that the minimum is not larger than the actual value factor.
409  * Otherwise, an exception is thrown.
410  ***************************************************************************/
411 void GOptimizerPar::factor_min(const double& min)
412 {
413  // Check if minimum is larger than value
414  if (min > m_factor_value) {
415  std::string msg = "Specified minimum factor "+gammalib::str(min)+
416  " is larger than the value factor "+
419  }
420 
421  // Assign minimum factor
422  m_factor_min = min;
423 
424  // Flag that minimum was set
425  m_has_min = true;
426 
427  // Return
428  return;
429 }
430 
431 
432 /***********************************************************************//**
433  * @brief Set parameter maximum factor
434  *
435  * @param[in] max Maximum factor.
436  *
437  * @exception GException::invalid_argument
438  * Parameter @p max smaller than value factor.
439  *
440  * Sets the maximum boundary factor of the parameter. The method makes
441  * sure that the maximum is not smaller than the actual value factor.
442  * Otherwise, an exception is thrown.
443  ***************************************************************************/
444 void GOptimizerPar::factor_max(const double& max)
445 {
446  // Check if maximum is smaller than value
447  if (max < m_factor_value) {
448  std::string msg = "Specified maximum factor "+gammalib::str(max)+
449  " is smaller than the value factor "+
452  }
453 
454  // Assign maximum
455  m_factor_max = max;
456 
457  // Flag that maximum was set
458  m_has_max = true;
459 
460  // Return
461  return;
462 }
463 
464 
465 /***********************************************************************//**
466  * @brief Set parameter minimum and maximum factors
467  *
468  * @param[in] min Minimum factor.
469  * @param[in] max Maximum factor.
470  *
471  * Sets the minimum and maximum boundary factors. The method calls the
472  * factor_min() and factor_max() methods which perform validity checking
473  * of the arguments.
474  ***************************************************************************/
475 void GOptimizerPar::factor_range(const double& min, const double& max)
476 {
477  // Set minimum and maximum
478  factor_min(min);
479  factor_max(max);
480 
481  // Return
482  return;
483 }
484 
485 
486 /***********************************************************************//**
487  * @brief Set scale factor
488  *
489  * @param[in] scale Scale factor.
490  *
491  * @exception GException::invalid_argument
492  * Sacle factor of 0 specified.
493  *
494  * Sets the scale factor of the parameter. All parameter attributes are
495  * rescaled accordingly.
496  *
497  * Special care is taken for value boundaries, that need swaping if the scale
498  * factor changes its sign. In case of sign change the following logic applies:
499  * - if minimum and maximum boundaries are set they are swapped
500  * - if only a minimum boundary exists it will be replaced by a maximum boundary
501  * - if only a maximum boundary exists it will be replaced by a minimum boundary
502  *
503  * An exception is thrown if a scale factor of 0 is specified.
504  ***************************************************************************/
505 void GOptimizerPar::scale(const double& scale)
506 {
507  // Make sure that scale is not zero
508  if (scale == 0.0) {
509  std::string msg = "Specified parameter scale factor of 0.\n"
510  "Parameters need a non-zero scale factor.";
512  }
513 
514  // Set rescaling
515  double rescale = m_scale/scale;
516 
517  // Set new scale factor
518  m_scale = scale;
519 
520  // Set values, error, gradient, min and max
521  m_factor_value *= rescale;
522  m_factor_error *= rescale;
523  m_factor_gradient *= rescale;
524  if (m_has_min) {
525  m_factor_min *= rescale;
526  }
527  if (m_has_max) {
528  m_factor_max *= rescale;
529  }
530 
531  // Takes care of boundaries in case of sign change
532  if (rescale < 0.0) {
533  if (m_has_min && m_has_max) {
534  double swap = m_factor_min;
536  m_factor_max = swap;
537  }
538  else if (m_has_min) {
540  m_has_max = true;
541  m_factor_min = 0.0;
542  m_has_min = false;
543  }
544  else if (m_has_max) {
546  m_has_min = true;
547  m_factor_max = 0.0;
548  m_has_max = false;
549  }
550  }
551 
552  // Return
553  return;
554 }
555 
556 
557 /***********************************************************************//**
558  * @brief Autoscale parameter
559  *
560  * Sets the value factor to unity and the scale factor to the real value
561  * of the parameter. The method will also adjust the error factor and
562  * gradient factor, as well as the minimum and maximum factors if they
563  * exist.
564  *
565  * Special care is taken for value boundaries, that need swaping if the scale
566  * factor changes its sign. In case of sign change the following logic applies:
567  * - if minimum and maximum boundaries are set they are swapped
568  * - if only a minimum boundary exists it will be replaced by a maximum boundary
569  * - if only a maximum boundary exists it will be replaced by a minimum boundary
570  *
571  * The method does nothing if the actual value factor is zero.
572  ***************************************************************************/
574 {
575  // Get value
576  double value = this->value();
577 
578  // Continue only if the value is non-zero
579  if (value != 0.0) {
580 
581  // Get the renormalization factor
582  double renormalization = m_scale / value;
583 
584  // Set the new scale factor to the actual value
585  m_scale = value;
586 
587  // Renormalize values, error, gradient, min and max
588  m_factor_value *= renormalization;
589  m_factor_error *= renormalization;
590  m_factor_gradient /= renormalization;
591  if (m_has_min) {
592  m_factor_min *= renormalization;
593  }
594  if (m_has_max) {
595  m_factor_max *= renormalization;
596  }
597 
598  // Takes care of boundaries in case of sign change
599  if (renormalization < 0.0) {
600  if (m_has_min && m_has_max) {
601  double swap = m_factor_min;
603  m_factor_max = swap;
604  }
605  else if (m_has_min) {
607  m_has_max = true;
608  m_factor_min = 0.0;
609  m_has_min = false;
610  }
611  else if (m_has_max) {
613  m_has_min = true;
614  m_factor_max = 0.0;
615  m_has_max = false;
616  }
617  }
618 
619  } // endif: value was non-zero
620 
621  // Return
622  return;
623 }
624 
625 
626 /***********************************************************************//**
627  * @brief Print parameter information
628  *
629  * @param[in] chatter Chattiness (defaults to NORMAL).
630  * @return String with parameter information.
631  ***************************************************************************/
632 std::string GOptimizerPar::print(const GChatter& chatter) const
633 {
634  // Initialise result string
635  std::string result;
636 
637  // Continue only if chatter is not silent
638  if (chatter != SILENT) {
639 
640  // Append parameter name
641  result.append(gammalib::parformat(" "+name()));
642 
643  // Append value
644  result.append(gammalib::str(value()));
645 
646  // For free parameters, append statistical uncertainty
647  if (m_free) {
648  result.append(" +/- "+gammalib::str(error()));
649  }
650 
651  // Append parameter limites if they exist
652  if (m_has_min && m_has_max) {
653  result.append(" ["+gammalib::str(min()) + ","+gammalib::str(max())+"]");
654  }
655  else if (m_has_min) {
656  result.append(" ["+gammalib::str(min()) + ",infty[");
657  }
658  else if (m_has_max) {
659  result.append(" ]-infty,"+gammalib::str(max())+"]");
660  }
661 
662  // Append parameter unit
663  result.append(" "+m_unit);
664 
665  // Signal if parameter was free or fixed
666  if (m_free) {
667  result.append(" (free");
668  }
669  else {
670  result.append(" (fixed");
671  }
672 
673  // Append parameter scale
674  result.append(",scale="+gammalib::str(m_scale));
675 
676  // Signal if parameter has analytic gradient
677  if (m_has_grad) {
678  result.append(",gradient)");
679  }
680  else {
681  result.append(")");
682  }
683 
684  } // endif: chatter was not silent
685 
686  // Return result
687  return result;
688 }
689 
690 
691 /*==========================================================================
692  = =
693  = Private methods =
694  = =
695  ==========================================================================*/
696 
697 /***********************************************************************//**
698  * @brief Initialise class members
699  ***************************************************************************/
701 {
702  // Initialise members
703  m_name.clear();
704  m_unit.clear();
705  m_factor_value = 0.0;
706  m_factor_error = 0.0;
707  m_factor_gradient = 0.0;
708  m_factor_min = 0.0;
709  m_factor_max = 0.0;
710  m_scale = 1.0;
711  m_free = true;
712  m_has_min = false;
713  m_has_max = false;
714  m_has_grad = false;
715 
716  // Return
717  return;
718 }
719 
720 
721 /***********************************************************************//**
722  * @brief Copy class members
723  *
724  * @param[in] par Model parameter.
725  ***************************************************************************/
727 {
728  // Copy members
729  m_name = par.m_name;
730  m_unit = par.m_unit;
736  m_scale = par.m_scale;
737  m_free = par.m_free;
738  m_has_min = par.m_has_min;
739  m_has_max = par.m_has_max;
740  m_has_grad = par.m_has_grad;
741 
742  // Return
743  return;
744 }
745 
746 
747 /***********************************************************************//**
748  * @brief Delete class members
749  ***************************************************************************/
751 {
752  // Return
753  return;
754 }
const double & factor_error(void) const
Return parameter error factor.
GOptimizerPar * clone(void) const
Clone parameter.
const double & factor_gradient(void) const
Return parameter gradient factor.
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 parameter minimum and maximum factors.
GOptimizerPar(void)
Void constructor.
double max(void) const
Return parameter maximum boundary.
#define G_FACTOR_VALUE
double m_factor_min
Parameter minimum factor.
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:843
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 boundary factor.
void autoscale(void)
Autoscale parameter.
GOptimizerPar & operator=(const GOptimizerPar &par)
Assignment operator.
bool m_has_min
Parameter has minimum boundary.
double m_factor_value
Parameter value factor.
void clear(void)
Clear parameter.
double m_factor_error
Uncertainty in parameter value factor.
GChatter
Definition: GTypemaps.hpp:33
std::string m_name
Parameter name.
double m_factor_max
Parameter maximum factor.
bool m_has_max
Parameter has maximum boundary.
double max(const GVector &vector)
Computes maximum vector element.
Definition: GVector.cpp:872
void free_members(void)
Delete class members.
const double & factor_min(void) const
Return parameter minimum boundary factor.
void init_members(void)
Initialise class members.
#define G_CONSTRUCT
void range(const double &min, const double &max)
Set minimum and maximum parameter boundaries.
double value(void) const
Return parameter value.
Exception handler interface definition.
Optimizer parameter class interface definition.
double error(void) const
Return parameter error.
double m_factor_gradient
Function gradient factor.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1022
void copy_members(const GOptimizerPar &par)
Copy class members.
std::string print(const GChatter &chatter=NORMAL) const
Print parameter information.
const double & factor_value(void) const
Return parameter value factor.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413
virtual ~GOptimizerPar(void)
Destructor.
Optimizer parameter class.