From fc2dc30969eecf90dd7f65e0535c1f509f889455 Mon Sep 17 00:00:00 2001 From: Gennady Pospelov <g.pospelov@fz-juelich.de> Date: Tue, 9 Aug 2016 13:48:17 +0200 Subject: [PATCH] New ExperimentalFit functional test on the way to minimizer refactoring --- Fit/Minimizer/BasicMinimizer.cpp | 5 ++ Fit/Minimizer/BasicMinimizer.h | 4 ++ Fit/Minimizer/Configurable.cpp | 13 ++++++ Fit/Minimizer/Configurable.h | 5 +- Fit/Minimizer/MinimizerFactory.cpp | 4 +- Fit/Minimizer/MinimizerOption.h | 2 +- Fit/Minimizer/Minuit2Minimizer.cpp | 49 ++++++++++++++++++++ Fit/Minimizer/Minuit2Minimizer.h | 22 +++++++-- Tests/Functional/Fit/CMakeLists.txt | 8 +++- Tests/Functional/Fit/ExperimentalFitTest.cpp | 26 +++++++++++ Tests/Functional/Fit/ExperimentalFitTest.h | 32 +++++++++++++ Tests/Functional/Fit/StandardFitsFactory.cpp | 6 +++ Tests/UnitTests/Fit/CMakeLists.txt | 5 +- 13 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 Tests/Functional/Fit/ExperimentalFitTest.cpp create mode 100644 Tests/Functional/Fit/ExperimentalFitTest.h diff --git a/Fit/Minimizer/BasicMinimizer.cpp b/Fit/Minimizer/BasicMinimizer.cpp index 3c301b13710..62e06ecd28c 100644 --- a/Fit/Minimizer/BasicMinimizer.cpp +++ b/Fit/Minimizer/BasicMinimizer.cpp @@ -37,3 +37,8 @@ void BasicMinimizer::setAlgorithmName(const std::string &algorithmName) m_algorithmName = algorithmName; } +void BasicMinimizer::propagateOptions() +{ + +} + diff --git a/Fit/Minimizer/BasicMinimizer.h b/Fit/Minimizer/BasicMinimizer.h index a7157d52d61..c91dc226f6b 100644 --- a/Fit/Minimizer/BasicMinimizer.h +++ b/Fit/Minimizer/BasicMinimizer.h @@ -28,6 +28,7 @@ class BA_CORE_API_ BasicMinimizer : public IMinimizer public: explicit BasicMinimizer(const std::string &minimizerName, const std::string &algorithmName = std::string()); + virtual ~BasicMinimizer(){} //! Returns name of the minimizer. std::string minimizerName() const; @@ -38,6 +39,9 @@ public: //! Sets minimization algorithm. void setAlgorithmName(const std::string &algorithmName); +protected: + virtual void propagateOptions(); + private: std::string m_minimizerName; std::string m_algorithmName; diff --git a/Fit/Minimizer/Configurable.cpp b/Fit/Minimizer/Configurable.cpp index 56035a128b2..d50eaeebaf5 100644 --- a/Fit/Minimizer/Configurable.cpp +++ b/Fit/Minimizer/Configurable.cpp @@ -33,6 +33,7 @@ Configurable &Configurable::operator=(const Configurable &other) Configurable::option_t Configurable::option(const std::string &optionName) { +// const_cast<option_t >(static_cast<const Configurable*>(this)->option(optionName)); for(auto option: m_options) { if(option->name() == optionName) return option; @@ -42,6 +43,18 @@ Configurable::option_t Configurable::option(const std::string &optionName) + optionName + "'."); } +const Configurable::option_t Configurable::option(const std::string &optionName) const +{ + for(const option_t option: m_options) { + if(option->name() == optionName) + return option; + } + + throw std::runtime_error("Configurable::getOption() -> Error. No option with name '" + + optionName + "'."); + +} + bool Configurable::exists(const std::string &name) { for(auto option: m_options) { diff --git a/Fit/Minimizer/Configurable.h b/Fit/Minimizer/Configurable.h index 4382cf660d0..8d7fa6ce2ba 100644 --- a/Fit/Minimizer/Configurable.h +++ b/Fit/Minimizer/Configurable.h @@ -41,9 +41,10 @@ public: const std::string &description = std::string()); option_t option(const std::string &optionName); + const option_t option(const std::string &optionName) const; template<class T> - T optionValue(const std::string &optionName); + T optionValue(const std::string &optionName) const; //! Sets the value of option. Option should hold same value type already. template<class T> @@ -69,7 +70,7 @@ Configurable::option_t Configurable::addOption(const std::string &optionName, T } template<class T> -T Configurable::optionValue(const std::string &optionName) +T Configurable::optionValue(const std::string &optionName) const { return option(optionName)->get<T>(); } diff --git a/Fit/Minimizer/MinimizerFactory.cpp b/Fit/Minimizer/MinimizerFactory.cpp index b6e39f90bce..f7a4e75103f 100644 --- a/Fit/Minimizer/MinimizerFactory.cpp +++ b/Fit/Minimizer/MinimizerFactory.cpp @@ -109,9 +109,7 @@ IMinimizer* MinimizerFactory::createMinimizer( IMinimizer* result(0); if( minimizer == "Test" ) { - //result = new TrivialMinimizer(); - result = new Minuit2Minimizer(); - + result = new TrivialMinimizer(); /* temporarily disabled } else if( minimizer == "Scan" ) { result = new ScanningMinimizer(); diff --git a/Fit/Minimizer/MinimizerOption.h b/Fit/Minimizer/MinimizerOption.h index fa491366eb3..0fc770958b8 100644 --- a/Fit/Minimizer/MinimizerOption.h +++ b/Fit/Minimizer/MinimizerOption.h @@ -24,7 +24,7 @@ //! @ingroup fitting_internal //! @brief The MinimizerOption class is intended to store a single option for minimization //! algorithm. Int, double, string values are available. -//! Relies on https://github.com/mapbox/variant +//! Relies on https://github.com/mapbox/variant, will be switched to std::variant in C++-17. class BA_CORE_API_ MinimizerOption { diff --git a/Fit/Minimizer/Minuit2Minimizer.cpp b/Fit/Minimizer/Minuit2Minimizer.cpp index ef3e12ea7ac..9735999e65f 100644 --- a/Fit/Minimizer/Minuit2Minimizer.cpp +++ b/Fit/Minimizer/Minuit2Minimizer.cpp @@ -26,6 +26,7 @@ const std::string O_PRINTLEVEL = "PrintLevel"; Minuit2Minimizer::Minuit2Minimizer() : BasicMinimizer(MinimizerNames::Minuit, AlgorithmNames::Migrad) + , m_minuit2_minimizer(new BA_ROOT::Minuit2::Minuit2Minimizer("xxx")) { addOption(O_STRATEGY, 1, "Minimization strategy (0-low, 1-medium, 2-high quality)"); @@ -35,6 +36,13 @@ Minuit2Minimizer::Minuit2Minimizer() "Tolerance on the function value at the minimum."); addOption(O_PRECISION, -1.0, "Relative floating point arithmetic precision."); + addOption(O_PRINTLEVEL, 0, + "Minimizer internal print level."); + +} + +Minuit2Minimizer::~Minuit2Minimizer() +{ } @@ -43,18 +51,59 @@ void Minuit2Minimizer::setStrategy(int value) setOptionValue(O_STRATEGY, value); } +int Minuit2Minimizer::strategy() const +{ + return optionValue<int>(O_STRATEGY); +} + void Minuit2Minimizer::setErrorDefinition(double value) { setOptionValue(O_ERRORDEF, value); } +double Minuit2Minimizer::errorDefinition() const +{ + return optionValue<double>(O_ERRORDEF); +} + void Minuit2Minimizer::setTolerance(double value) { setOptionValue(O_TOLERANCE, value); } +double Minuit2Minimizer::tolerance() const +{ + return optionValue<double>(O_TOLERANCE); +} + void Minuit2Minimizer::setPrecision(double value) { setOptionValue(O_PRECISION, value); } +double Minuit2Minimizer::precision() const +{ + return optionValue<double>(O_PRECISION); +} + +void Minuit2Minimizer::setPrintLevel(int value) +{ + setOptionValue(O_PRINTLEVEL, value); +} + +int Minuit2Minimizer::printLevel() const +{ + return optionValue<int>(O_PRINTLEVEL); +} + +//! Propagate options down to ROOT's Minuit2Minimizer. + +void Minuit2Minimizer::propagateOptions() +{ + m_minuit2_minimizer->SetStrategy(strategy()); + m_minuit2_minimizer->SetErrorDef(errorDefinition()); + m_minuit2_minimizer->SetTolerance(tolerance()); + m_minuit2_minimizer->SetPrecision(precision()); + m_minuit2_minimizer->SetPrintLevel(printLevel()); +} + diff --git a/Fit/Minimizer/Minuit2Minimizer.h b/Fit/Minimizer/Minuit2Minimizer.h index 1c5178445fe..711daca9c70 100644 --- a/Fit/Minimizer/Minuit2Minimizer.h +++ b/Fit/Minimizer/Minuit2Minimizer.h @@ -17,6 +17,8 @@ #define MINUIT2MINIMIZER_H #include "BasicMinimizer.h" +#include "Minuit2/Minuit2Minimizer.h" +#include <memory> //! @class Minuit2Minimizer //! @ingroup fitting_internal @@ -27,38 +29,48 @@ class BA_CORE_API_ Minuit2Minimizer : public BasicMinimizer { public: Minuit2Minimizer(); + ~Minuit2Minimizer(); //! Sets minimization strategy (0-low, 1-medium, 2-high minimization quality). - //! At low quality number of function calls will be economized. Default value is 1. + //! At low quality number of function calls will be economized. + //! Default value is 1. void setStrategy(int value); + int strategy() const; //! Sets error definition factor for parameter error calculation. //! If objective function (OF) is the usual chisquare function and if the user wants the usual //! one-standard-deviation errors, then the error definition should be 1.0. If OF is a //! negative-log-likelihood function, then 0.5. If OF is a chisquare, but the user wants //! two-standard-deviation errors, 4.0. - //! Default value is 1.0 + //! Default value is 1.0. void setErrorDefinition(double value); + double errorDefinition() const; //!< Sets tolerance on the function value at the minimum. //!< Minimization will stop when the estimated vertical distance to the minimum (EDM) is less - //! than 0.001*tolerance*ErrorDef. Here ErrorDef=1 for chi squared fit and ErrorDef=0.5 + //! than 0.001*tolerance*ErrorDef. Here ErrorDef=1.0 for chi squared fit and ErrorDef=0.5 //! for negative log likelihood fit. - //! Default value is 0.01 + //! Default value is 0.01. void setTolerance(double value); + double tolerance() const; //!< Sets relative floating point arithmetic precision. //!< Should be adjusted when the user knows that objectiove function value is not //!< calculated to the nominal machine accuracy. Typical values are between 10^-5 and 10^-14. //! Default value is -1.0 (minimizer specific will be used). void setPrecision(double value); + double precision() const; //! Sets minimizer internal print level. //! Default value is 0 (silent). void setPrintLevel(int value); + int printLevel() const; -private: +protected: + void propagateOptions(); +private: + std::unique_ptr<BA_ROOT::Minuit2::Minuit2Minimizer> m_minuit2_minimizer; }; #endif diff --git a/Tests/Functional/Fit/CMakeLists.txt b/Tests/Functional/Fit/CMakeLists.txt index f9cf473180b..215e1f16154 100644 --- a/Tests/Functional/Fit/CMakeLists.txt +++ b/Tests/Functional/Fit/CMakeLists.txt @@ -11,6 +11,7 @@ set(test_cases Minuit2_Fumili Minuit2_Migrad RectDetectorFit + ExperimentalFit ) # for some reason these flags doesn't propagated here by SetUpWindows.cmake @@ -31,7 +32,12 @@ include_directories( #file(GLOB source_files "*.cpp") #file(GLOB include_files "*.h") -add_executable(FitTest FitTest.cpp IMinimizerTest.cpp IMinimizerTest.h MinimizerTests.cpp MinimizerTests.h RectDetectorFitTest.cpp RectDetectorFitTest.h StandardFitsFactory.cpp StandardFitsFactory.h) +add_executable(FitTest + FitTest.cpp IMinimizerTest.cpp IMinimizerTest.h MinimizerTests.cpp + MinimizerTests.h RectDetectorFitTest.cpp RectDetectorFitTest.h + StandardFitsFactory.cpp StandardFitsFactory.h + ExperimentalFitTest.h ExperimentalFitTest.cpp + ) target_link_libraries(FitTest BornAgainFit BornAgainCore BornAgainTestMachinery) foreach(test_case ${test_cases}) diff --git a/Tests/Functional/Fit/ExperimentalFitTest.cpp b/Tests/Functional/Fit/ExperimentalFitTest.cpp new file mode 100644 index 00000000000..0bdccc17f8f --- /dev/null +++ b/Tests/Functional/Fit/ExperimentalFitTest.cpp @@ -0,0 +1,26 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file Tests/Functional/Fit/ExperimentalFitTest.cpp +//! @brief Implements class ExperimentalFitTest. +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2015 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // + +#include "ExperimentalFitTest.h" +#include "GISASSimulation.h" +#include "Histogram2D.h" +#include "Rectangle.h" +#include "RectangularDetector.h" +#include "Units.h" + +ExperimentalFitTest::ExperimentalFitTest() + : IMinimizerTest("Minuit2", "Migrad") +{ +} diff --git a/Tests/Functional/Fit/ExperimentalFitTest.h b/Tests/Functional/Fit/ExperimentalFitTest.h new file mode 100644 index 00000000000..735d209d637 --- /dev/null +++ b/Tests/Functional/Fit/ExperimentalFitTest.h @@ -0,0 +1,32 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file Tests/Functional/Fit/ExperimentalFitTest.h +//! @brief Declares class ExperimentalFitTest. +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2015 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // + +#ifndef EXPERIMENTALFITTEST_H +#define EXPERIMENTALFITTEST_H + +#include "IMinimizerTest.h" + +//! @class ExperimentalFitTest +//! @ingroup standard_samples +//! @brief Experimental test on the way to refactored minimizers + +class ExperimentalFitTest : public IMinimizerTest +{ +public: + ExperimentalFitTest(); + +}; + +#endif // EXPERIMENTALFITTEST_H diff --git a/Tests/Functional/Fit/StandardFitsFactory.cpp b/Tests/Functional/Fit/StandardFitsFactory.cpp index 920cde1a0c7..d9ecffe09e8 100644 --- a/Tests/Functional/Fit/StandardFitsFactory.cpp +++ b/Tests/Functional/Fit/StandardFitsFactory.cpp @@ -16,6 +16,7 @@ #include "StandardFitsFactory.h" #include "MinimizerTests.h" #include "RectDetectorFitTest.h" +#include "ExperimentalFitTest.h" #include <boost/format.hpp> StandardFitsFactory::StandardFitsFactory() @@ -59,6 +60,11 @@ StandardFitsFactory::StandardFitsFactory() "RectDetectorFit", create_new<RectDetectorFitTest>, "Fit of rectangular detector, with crop and masks applied"); + + registerItem( + "ExperimentalFit", + create_new<ExperimentalFitTest>, + "Experimental fit on the way to refactoring"); } IFunctionalTest* StandardFitsFactory::createTest(const std::string& test_name) diff --git a/Tests/UnitTests/Fit/CMakeLists.txt b/Tests/UnitTests/Fit/CMakeLists.txt index 1eb78612b4e..356d5a8cd8d 100644 --- a/Tests/UnitTests/Fit/CMakeLists.txt +++ b/Tests/UnitTests/Fit/CMakeLists.txt @@ -3,16 +3,15 @@ ############################################################################ include_directories( - ${Boost_INCLUDE_DIRS} ${BornAgainCore_INCLUDE_DIRS} ${BornAgainFit_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIR} - ${GSL_INCLUDE_DIR} + ${RootMinimizers_INCLUDE_DIRS} ) if(BORNAGAIN_OPENMPI) include_directories(${MPI_INCLUDE_PATH}) endif() -#message(WARNING "Some unit tests disabled") WRAP_GTEST(TestFit0 "*.h" ${BornAgainCore_LIBRARY} 0) + -- GitLab