DiSMEC++
dismec::HyperParameterBase Class Reference

Base class for all objects that have adjustable hyper-parameters. More...

#include <hyperparams.h>

Inheritance diagram for dismec::HyperParameterBase:
anonymous_namespace{hyperparams.cpp}::NestedTestObject anonymous_namespace{hyperparams.cpp}::TestObject dismec::solvers::BacktrackingLineSearch dismec::solvers::CGMinimizer dismec::solvers::Minimizer anonymous_namespace{minimizer.cpp}::MockMinimizer dismec::solvers::NewtonWithLineSearch dismec::solvers::NullOptimizer

Classes

struct  HyperParamData
 This structure collects the Getter and Setter functions. This is what we store in the variant. More...
 

Public Types

using hyper_param_t = std::variant< long, double >
 

Public Member Functions

 HyperParameterBase ()=default
 
virtual ~HyperParameterBase ()=default
 
 HyperParameterBase (const HyperParameterBase &)=default
 
 HyperParameterBase (HyperParameterBase &&)=default
 
HyperParameterBaseoperator= (HyperParameterBase &&)=default
 
HyperParameterBaseoperator= (const HyperParameterBase &)=default
 
void set_hyper_parameter (const std::string &name, long value)
 
void set_hyper_parameter (const std::string &name, double value)
 
hyper_param_t get_hyper_parameter (const std::string &name) const
 
std::vector< std::string > get_hyper_parameter_names () const
 Returns a vector that lists all hyper parameter names. More...
 

Protected Member Functions

template<class U , class S >
void declare_hyper_parameter (std::string name, U S::*pointer)
 
template<class U , class S >
void declare_hyper_parameter (std::string name, U(S::*getter)() const, void(S::*setter)(U))
 Declares an constrained hyper-parameter with explicit getter and setter function. More...
 
template<class T , class S >
void declare_sub_object (const std::string &name, T S::*object)
 Declares a sub-object that also contains hyper-parameters. More...
 

Private Types

using hyper_param_ptr_t = std::variant< HyperParamData< long >, HyperParamData< double > >
 

Private Member Functions

template<class D >
void declare_hyper_parameter (std::string name, HyperParamData< D > data)
 

Private Attributes

std::unordered_map< std::string, hyper_param_ptr_tm_HyperParameters
 

Detailed Description

Base class for all objects that have adjustable hyper-parameters.

This class defines a common interface for all objects with adjustable hyper-parameters, and provides the implementation. Derived classes only have to declare their hyper-parameters in the constructor using the declare_hyper_parameter functions, and the rest is handled by this class.

This is some fairly complicated C++ magic; however, if you only want to modify the solver algorithms or objective functions, then this class should not need to be touched. Using is should be fairly straightforward, though:

Usage: The intent of this class is to provide a unified interface and implementation to objects that expose some sort of hyper-parameters which we would like to read from a config file or the command line. In that case, make you class (called Object here) derive from HyperParameterBase. This will provide the functions set_hyper_parameter and get_hyper_parameter to query and update hyper-parameter values based on a string name.

How do you define which hyper-parameters exist? This is what the protected declare_hyper_parameter functions are for. These should be called in the constructor of your class, and declare a name for each hyper-parameter you want to use. The HyperParameterBase object does not manage the storage of the hyper-parameter values, just access to it. This is deliberate, as looking up a hyper-parameter by name might be a costly operation, so the actual Object, which anyways knows exactly which hyper-parameters it has, should not do. Instead, the hyper-parameters are stored as part of the Object class. For example, consider

class Object: public HyperParameterBase {
double A;
int B;
int get_b() const { return B; }
void set_b(int value) { check_value(value); B = value };
// ...
}

In this case, A is a parameter which presumably can take on any valid double value, whereas the values of B should fulfill the check_value function. The corresponding constructor could look like this:

Object::Object() {
declare_hyper_parameter("A", Object::A);
declare_hyper_parameter("B", &Object::get_b, &Object::set_b);
}
void declare_hyper_parameter(std::string name, U S::*pointer)
Definition: hyperparams.h:117

Implementation Details: Internally, the hyper-parameters are stored as a map that maps hyper-parameter names to getter and setter functions. These functions take as first argument a pointer to the object, the setter as second argument the target value. The reason why we give the getters/setters a pointer to the object, instead of having them modify the values directly, is that the latter would break after copy/move operations on HyperParameterBase, whereas in this way we do not need to disable copy and move.

Even though the class itself provides no virtual functions, its destructor is declared virtual. This enables RTTI, which we use to check consistency of the supplied this pointers.

The magic happens in the declare_hyper_parameter functions. These construct the function objects, based on member pointers or pointers-to-member-function. See their documentation for details.

Definition at line 83 of file hyperparams.h.

Member Typedef Documentation

◆ hyper_param_ptr_t

using dismec::HyperParameterBase::hyper_param_ptr_t = std::variant<HyperParamData<long>, HyperParamData<double> >
private

Definition at line 233 of file hyperparams.h.

◆ hyper_param_t

using dismec::HyperParameterBase::hyper_param_t = std::variant<long, double>

Definition at line 85 of file hyperparams.h.

Constructor & Destructor Documentation

◆ HyperParameterBase() [1/3]

dismec::HyperParameterBase::HyperParameterBase ( )
default

◆ ~HyperParameterBase()

virtual dismec::HyperParameterBase::~HyperParameterBase ( )
virtualdefault

◆ HyperParameterBase() [2/3]

dismec::HyperParameterBase::HyperParameterBase ( const HyperParameterBase )
default

◆ HyperParameterBase() [3/3]

dismec::HyperParameterBase::HyperParameterBase ( HyperParameterBase &&  )
default

Member Function Documentation

◆ declare_hyper_parameter() [1/3]

template<class D >
void dismec::HyperParameterBase::declare_hyper_parameter ( std::string  name,
HyperParamData< D >  data 
)
inlineprivate

The internal declare_hyper_parameter function, adds the HP data to the map and checks that the names are unique.

Definition at line 226 of file hyperparams.h.

References m_HyperParameters.

◆ declare_hyper_parameter() [2/3]

template<class U , class S >
void dismec::HyperParameterBase::declare_hyper_parameter ( std::string  name,
U S::*  pointer 
)
inlineprotected

Declares an unconstrained hyper-parameter. The getter and setter functions are created automatically and read from/write to the given member variable.

Template Parameters
UThe type of the hyper-parameter. Has to be one of long, double
SThe class into which the pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds.
Parameters
nameName of the hyper-parameter.
pointerPointer to member of the class which stores the value of the hyper-parameter.

statically, we can only test whether whether the class S is derived from HyperParameterBase, but not if it is actually consistent with the this pointer. However, this static assert should catch almost all erroneous uses. The rest will be caught at runtime in the dynamic_cast check

OK, we know we are consistent, generate the getter and setter functions. I think technically we could get away with using static_cast here, since we know that self is actually of type S, but I think having the explicit dynamic_cast helps to emphasize what is happening.

and insert them into the map

Definition at line 117 of file hyperparams.h.

Referenced by dismec::solvers::BacktrackingLineSearch::BacktrackingLineSearch(), dismec::solvers::CGMinimizer::CGMinimizer(), declare_hyper_parameter(), declare_sub_object(), and dismec::solvers::NewtonWithLineSearch::NewtonWithLineSearch().

◆ declare_hyper_parameter() [3/3]

template<class U , class S >
void dismec::HyperParameterBase::declare_hyper_parameter ( std::string  name,
U(S::*)() const  getter,
void(S::*)(U)  setter 
)
inlineprotected

Declares an constrained hyper-parameter with explicit getter and setter function.

Template Parameters
UThe type of the hyper-parameter. Has to be one of long, double.
SThe class into which the member function pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds.
Parameters
nameName of the hyper-parameter.
getterPointer to member of the class which reads the value of the hyper-parameter.
setterPointer to member of the class which sets the value of the hyper-parameter.

Definition at line 152 of file hyperparams.h.

References declare_hyper_parameter().

◆ declare_sub_object()

template<class T , class S >
void dismec::HyperParameterBase::declare_sub_object ( const std::string &  name,
T S::*  object 
)
inlineprotected

Declares a sub-object that also contains hyper-parameters.

Any hyper-parameter in the sub-object will be also added to this object, where the name is prefixed by the name parameter given to this function. At the point of this function call, the sub-object must exist and have its hyper-paramters already initialized.

Template Parameters
SThe class into which the member function pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds.

Definition at line 179 of file hyperparams.h.

References declare_hyper_parameter(), m_HyperParameters, and dismec::types::visit().

Referenced by dismec::solvers::NewtonWithLineSearch::NewtonWithLineSearch().

◆ get_hyper_parameter()

auto HyperParameterBase::get_hyper_parameter ( const std::string &  name) const

Gets the value of the named hyper-parameter. Since we cannot know the exact type, we return a variant.

Definition at line 10 of file hyperparams.cpp.

References dismec::types::visit().

◆ get_hyper_parameter_names()

std::vector< std::string > HyperParameterBase::get_hyper_parameter_names ( ) const

Returns a vector that lists all hyper parameter names.

Definition at line 29 of file hyperparams.cpp.

References m_HyperParameters.

◆ operator=() [1/2]

HyperParameterBase& dismec::HyperParameterBase::operator= ( const HyperParameterBase )
default

◆ operator=() [2/2]

HyperParameterBase& dismec::HyperParameterBase::operator= ( HyperParameterBase &&  )
default

◆ set_hyper_parameter() [1/2]

void HyperParameterBase::set_hyper_parameter ( const std::string &  name,
double  value 
)

Definition at line 24 of file hyperparams.cpp.

References m_HyperParameters.

◆ set_hyper_parameter() [2/2]

void HyperParameterBase::set_hyper_parameter ( const std::string &  name,
long  value 
)

updates the value of the hyper-parameter with the given name. If the type does not match the internal hyper-parameter type, an exception is throw.

Definition at line 19 of file hyperparams.cpp.

References m_HyperParameters.

Referenced by dismec::HyperParameters::apply().

Member Data Documentation

◆ m_HyperParameters

std::unordered_map<std::string, hyper_param_ptr_t> dismec::HyperParameterBase::m_HyperParameters
private

The documentation for this class was generated from the following files: