From e9d6cbd8028d02dbfe0a891089682a5bb03a7a3e Mon Sep 17 00:00:00 2001 From: Gennady Pospelov <g.pospelov@fz-juelich.de> Date: Thu, 22 Sep 2016 17:08:06 +0200 Subject: [PATCH] New functional test to verify minimizer chain. --- .../Fit/AdjustMinimizerStrategyTest.cpp | 55 +++++++++++++++++++ ...itTest.h => AdjustMinimizerStrategyTest.h} | 17 +++--- Tests/Functional/Fit/ExperimentalFitTest.cpp | 34 ------------ Tests/Functional/Fit/FitParameterPlan.cpp | 22 +++++--- Tests/Functional/Fit/FitParameterPlan.h | 5 +- Tests/Functional/Fit/IMinimizerTest.cpp | 50 ++++++++++------- Tests/Functional/Fit/IMinimizerTest.h | 14 +---- .../Functional/Fit/ObjectiveFunctionPlan.cpp | 3 +- Tests/Functional/Fit/StandardFitsFactory.cpp | 8 +-- 9 files changed, 121 insertions(+), 87 deletions(-) create mode 100644 Tests/Functional/Fit/AdjustMinimizerStrategyTest.cpp rename Tests/Functional/Fit/{ExperimentalFitTest.h => AdjustMinimizerStrategyTest.h} (61%) delete mode 100644 Tests/Functional/Fit/ExperimentalFitTest.cpp diff --git a/Tests/Functional/Fit/AdjustMinimizerStrategyTest.cpp b/Tests/Functional/Fit/AdjustMinimizerStrategyTest.cpp new file mode 100644 index 00000000000..1cc7b8e39ce --- /dev/null +++ b/Tests/Functional/Fit/AdjustMinimizerStrategyTest.cpp @@ -0,0 +1,55 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file Tests/Functional/Fit/AdjustMinimizerStrategyTest.cpp +//! @brief Implements class AdjustMinimizerStrategyTest. +//! +//! @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 "AdjustMinimizerStrategyTest.h" +#include "Units.h" +#include "FitSuite.h" +#include "MinimizerFactory.h" +#include "FitStrategyAdjustMinimizer.h" +#include "MinimizerConstants.h" + + +AdjustMinimizerStrategyTest::AdjustMinimizerStrategyTest() + : IMinimizerTest("undefined", "undefined") +{} + +void AdjustMinimizerStrategyTest::initParameterPlan() +{ + m_parameters.clear(); + m_parameters.push_back(FitParameterPlan("*Height", 1.0 * Units::nanometer, + 5.0 * Units::nanometer, + AttLimits::limited(0.01, 30.0), 0.05)); + m_parameters.push_back(FitParameterPlan("*Radius", 20.0 * Units::nanometer, + 5.0 * Units::nanometer, + AttLimits::limited(0.01, 30.0), 0.05)); + +} + +std::unique_ptr<FitSuite> AdjustMinimizerStrategyTest::createFitSuite() { + std::unique_ptr<FitSuite> result(new FitSuite()); + result->initPrint(10); + + result->addFitStrategy(FitStrategyAdjustMinimizer( + MinimizerNames::Genetic, std::string(), "MaxIterations=2;")); + + result->addFitStrategy(FitStrategyAdjustMinimizer(MinimizerNames::Minuit2, + AlgorithmNames::Migrad)); + + for (size_t i = 0; i < m_parameters.size(); ++i) + result->addFitParameter(m_parameters[i].m_name, + m_parameters[i].m_start_value, + m_parameters[i].m_limits, m_parameters[i].m_step); + return result; +} diff --git a/Tests/Functional/Fit/ExperimentalFitTest.h b/Tests/Functional/Fit/AdjustMinimizerStrategyTest.h similarity index 61% rename from Tests/Functional/Fit/ExperimentalFitTest.h rename to Tests/Functional/Fit/AdjustMinimizerStrategyTest.h index 5df4e31ee00..a961dc31b2e 100644 --- a/Tests/Functional/Fit/ExperimentalFitTest.h +++ b/Tests/Functional/Fit/AdjustMinimizerStrategyTest.h @@ -2,8 +2,8 @@ // // BornAgain: simulate and fit scattering at grazing incidence // -//! @file Tests/Functional/Fit/ExperimentalFitTest.h -//! @brief Declares class ExperimentalFitTest. +//! @file Tests/Functional/Fit/MinimizerStrategyTest.h +//! @brief Declares class MinimizerStrategyTest. //! //! @homepage http://www.bornagainproject.org //! @license GNU General Public License v3 or higher (see COPYING) @@ -18,18 +18,19 @@ #include "IMinimizerTest.h" -//! @class ExperimentalFitTest +//! @class MinimizerStrategyTest //! @ingroup standard_samples -//! @brief Experimental test on the way to refactored minimizers +//! @brief The MinimizerStrategyTest verifies fitting with the chain of minimizers. -class ExperimentalFitTest : public IMinimizerTest +class AdjustMinimizerStrategyTest : public IMinimizerTest { public: - ExperimentalFitTest(); + AdjustMinimizerStrategyTest(); protected: - virtual std::unique_ptr<FitSuite> createFitSuite(); + void initParameterPlan() override; + std::unique_ptr<FitSuite> createFitSuite() override; }; -#endif // EXPERIMENTALFITTEST_H +#endif diff --git a/Tests/Functional/Fit/ExperimentalFitTest.cpp b/Tests/Functional/Fit/ExperimentalFitTest.cpp deleted file mode 100644 index bceb8e90d6f..00000000000 --- a/Tests/Functional/Fit/ExperimentalFitTest.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// ************************************************************************** // -// -// 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 "Minuit2Minimizer.h" -#include "FitSuite.h" - -ExperimentalFitTest::ExperimentalFitTest() - : IMinimizerTest("Minuit2", "Migrad") -{} - -std::unique_ptr<FitSuite> ExperimentalFitTest::createFitSuite() -{ - std::unique_ptr<FitSuite> result(new FitSuite()); - result->initPrint(10); - result->setMinimizer( new Minuit2Minimizer() ); - for (const auto& par: m_parameters) - result->addFitParameter( - par.m_name, par.m_start_value, - AttLimits::lowerLimited(0.01), par.m_start_value/100.); - return result; -} diff --git a/Tests/Functional/Fit/FitParameterPlan.cpp b/Tests/Functional/Fit/FitParameterPlan.cpp index e7c08b08ac4..0f2c8a79a2b 100644 --- a/Tests/Functional/Fit/FitParameterPlan.cpp +++ b/Tests/Functional/Fit/FitParameterPlan.cpp @@ -15,9 +15,22 @@ #include "FitParameterPlan.h" -FitParameterPlan::FitParameterPlan(double start_value, double expected_value, +FitParameterPlan::FitParameterPlan() + : m_name(std::string()) + , m_start_value(0.0) + , m_expected_value(0.0) + , m_limits(AttLimits::limitless()) + , m_step(0.0) + , m_threshold(0.0) +{ + +} + +FitParameterPlan::FitParameterPlan(const std::string &name, double start_value, + double expected_value, const AttLimits &limits, double step) - : m_start_value(start_value) + : m_name(name) + , m_start_value(start_value) , m_expected_value(expected_value) , m_limits(limits) , m_step(step) @@ -25,8 +38,3 @@ FitParameterPlan::FitParameterPlan(double start_value, double expected_value, { } - -FitParameterPlan::~FitParameterPlan() -{ - -} diff --git a/Tests/Functional/Fit/FitParameterPlan.h b/Tests/Functional/Fit/FitParameterPlan.h index d86c610f08c..9910206e28d 100644 --- a/Tests/Functional/Fit/FitParameterPlan.h +++ b/Tests/Functional/Fit/FitParameterPlan.h @@ -26,10 +26,11 @@ class FitParameterPlan { public: - FitParameterPlan(double start_value, double expected_value, + FitParameterPlan(); + FitParameterPlan(const std::string &name, double start_value, double expected_value, const AttLimits &limits, double step); - ~FitParameterPlan(); + std::string m_name; double m_start_value; //!< starting value of fit parameter double m_expected_value; //!< expected value to find in the fit AttLimits m_limits; //!< limits of fit parameter diff --git a/Tests/Functional/Fit/IMinimizerTest.cpp b/Tests/Functional/Fit/IMinimizerTest.cpp index 360173f724e..3d0b746cb1d 100644 --- a/Tests/Functional/Fit/IMinimizerTest.cpp +++ b/Tests/Functional/Fit/IMinimizerTest.cpp @@ -25,13 +25,13 @@ #include <boost/format.hpp> #include <memory> -IMinimizerTest::TestParameter::TestParameter(const std::string &name, - double real_value, - double start_value) - : m_name(name) - , m_real_value(real_value) - , m_start_value(start_value) - , m_found_value(0.0) {} +//IMinimizerTest::TestParameter::TestParameter(const std::string &name, +// double real_value, +// double start_value) +// : m_name(name) +// , m_real_value(real_value) +// , m_start_value(start_value) +// , m_found_value(0.0) {} IMinimizerTest::IMinimizerTest(const std::string& minimizer_name, const std::string& minimizer_algorithm) @@ -41,18 +41,14 @@ IMinimizerTest::IMinimizerTest(const std::string& minimizer_name, , m_sample_builder_name("CylindersInBABuilder") , m_parameter_tolerance(0.01) { - m_parameters.push_back( - TestParameter("*Height", 5.0 * Units::nanometer, 4.5 * Units::nanometer)); - m_parameters.push_back( - TestParameter("*Radius", 5.0 * Units::nanometer, 5.5 * Units::nanometer)); } bool IMinimizerTest::runTest() { + initParameterPlan(); + std::unique_ptr<MultiLayer> sample(createSample()); - for (size_t i = 0; i < m_parameters.size(); ++i) - sample->setParameterValue(m_parameters[i].m_name, m_parameters[i].m_real_value); std::unique_ptr<GISASSimulation> simulation(createSimulation()); simulation->setSample(*sample.get()); @@ -67,34 +63,46 @@ bool IMinimizerTest::runTest() fitSuite->runFit(); std::vector<double> valuesAtMinimum = fitSuite->fitParameters()->values(); - for (size_t i = 0; i < m_parameters.size(); ++i) - m_parameters[i].m_found_value = valuesAtMinimum[i]; // analyze results bool success = true; for (size_t i = 0; i < m_parameters.size(); ++i) { - double diff = std::abs(m_parameters[i].m_found_value - m_parameters[i].m_real_value) - / m_parameters[i].m_real_value; + double foundValue = valuesAtMinimum[i]; + double diff = std::abs(foundValue - m_parameters[i].m_expected_value) + / m_parameters[i].m_expected_value; if (diff > m_parameter_tolerance) success = false; std::cout << boost::format("%|12t| %-10s : %-6.4f (diff %6.4g) %s\n") % - m_parameters[i].m_name % m_parameters[i].m_found_value % diff % + m_parameters[i].m_name % foundValue % diff % (success ? "OK" : "FAILED"); } return success; } +//! Creates plan with initial/real values of fit parameters. + +void IMinimizerTest::initParameterPlan() { + m_parameters.clear(); + m_parameters.push_back(FitParameterPlan("*Height", 4.5 * Units::nanometer, + 5.0 * Units::nanometer, + AttLimits::lowerLimited(0.01), 0.01)); + m_parameters.push_back(FitParameterPlan("*Radius", 5.5 * Units::nanometer, + 5.0 * Units::nanometer, + AttLimits::lowerLimited(0.01), 0.01)); +} + std::unique_ptr<FitSuite> IMinimizerTest::createFitSuite() { std::unique_ptr<FitSuite> result(new FitSuite()); result->initPrint(10); IMinimizer* minimizer = MinimizerFactory::createMinimizer( - m_minimizer_name, m_minimizer_algorithm); + m_minimizer_name, m_minimizer_algorithm); result->setMinimizer(minimizer); + for (size_t i = 0; i < m_parameters.size(); ++i) result->addFitParameter( m_parameters[i].m_name, m_parameters[i].m_start_value, - AttLimits::lowerLimited(0.01), m_parameters[i].m_start_value / 100.); + m_parameters[i].m_limits, m_parameters[i].m_start_value / 100.); return result; } @@ -102,6 +110,8 @@ std::unique_ptr<MultiLayer> IMinimizerTest::createSample() { SampleBuilderFactory builderFactory; std::unique_ptr<MultiLayer> result(builderFactory.createSample(m_sample_builder_name)); + for (size_t i = 0; i < m_parameters.size(); ++i) + result->setParameterValue(m_parameters[i].m_name, m_parameters[i].m_expected_value); return result; } diff --git a/Tests/Functional/Fit/IMinimizerTest.h b/Tests/Functional/Fit/IMinimizerTest.h index 95ec49cb61a..af82f67f50f 100644 --- a/Tests/Functional/Fit/IMinimizerTest.h +++ b/Tests/Functional/Fit/IMinimizerTest.h @@ -18,6 +18,7 @@ #include "IFunctionalTest.h" #include "OutputData.h" +#include "FitParameterPlan.h" #include <memory> class FitSuite; @@ -37,25 +38,16 @@ public: bool runTest() final; - class TestParameter - { - public: - TestParameter(const std::string &name, double real_value, double start_value); - std::string m_name; //!< sample parameter name - double m_real_value; //!< real value to construct the sample - double m_start_value; //!< starting value for the minimizer - double m_found_value; //!< the value found during the fit - }; - void setParameterTolerance(double value) { m_parameter_tolerance = value; } protected: + virtual void initParameterPlan(); virtual std::unique_ptr<FitSuite> createFitSuite(); virtual std::unique_ptr<MultiLayer> createSample(); virtual std::unique_ptr<GISASSimulation> createSimulation(); virtual std::unique_ptr<OutputData<double>> createOutputData(const GISASSimulation* simulation); - std::vector<TestParameter> m_parameters; + std::vector<FitParameterPlan> m_parameters; std::string m_minimizer_name; std::string m_minimizer_algorithm; std::string m_simulation_name; diff --git a/Tests/Functional/Fit/ObjectiveFunctionPlan.cpp b/Tests/Functional/Fit/ObjectiveFunctionPlan.cpp index d8b5f63609f..cccc0353028 100644 --- a/Tests/Functional/Fit/ObjectiveFunctionPlan.cpp +++ b/Tests/Functional/Fit/ObjectiveFunctionPlan.cpp @@ -29,7 +29,8 @@ ObjectiveFunctionPlan::ObjectiveFunctionPlan(const std::string &name, objective_ void ObjectiveFunctionPlan::addParameter(double start_value, double expected_value, const AttLimits &limits, double step) { - m_parameters.push_back(FitParameterPlan(start_value, expected_value, limits, step)); + std::string name = "par"+std::to_string(m_parameters.size()); + m_parameters.push_back(FitParameterPlan(name, start_value, expected_value, limits, step)); } //! Plan for finding rosenbrock function minimum diff --git a/Tests/Functional/Fit/StandardFitsFactory.cpp b/Tests/Functional/Fit/StandardFitsFactory.cpp index dabd05c54e8..d505c3a0303 100644 --- a/Tests/Functional/Fit/StandardFitsFactory.cpp +++ b/Tests/Functional/Fit/StandardFitsFactory.cpp @@ -16,7 +16,7 @@ #include "StandardFitsFactory.h" #include "MinimizerTests.h" #include "RectDetectorFitTest.h" -#include "ExperimentalFitTest.h" +#include "AdjustMinimizerStrategyTest.h" #include "StandaloneFitTest.h" #include <boost/format.hpp> @@ -63,9 +63,9 @@ StandardFitsFactory::StandardFitsFactory() "Fit of rectangular detector, with crop and masks applied"); registerItem( - "ExperimentalFit", - create_new<ExperimentalFitTest>, - "Experimental fit on the way to refactoring"); + "AdjustMinimizerStrategy", + create_new<AdjustMinimizerStrategyTest>, + "Test of minimizer chain: genetic -> minuit2"); registerItem( "StandaloneFit", -- GitLab