//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Tests/Functional/Mumufit/MinimizerTests.cpp
//! @brief     Implements classes from MinimizerTest family.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Fit/Kernel/Minimizer.h"
#include "Tests/Functional/Mumufit/PlanCases.h"
#include "Tests/GTestWrapper/google_test.h"

bool runMinimizerTest(const std::string& minimizer_name, const std::string& algorithm_name,
                      MinimizerTestPlan& plan, const std::string& options = "")
{
    mumufit::Minimizer minimizer;
    minimizer.setMinimizer(minimizer_name, algorithm_name, options);
    return plan.checkMinimizer(minimizer);
}


TEST(Minimizer, Minuit_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("Minuit2", "Migrad", plan));
}

TEST(Minimizer, Minuit_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("Minuit2", "Migrad", plan));
}

TEST(Minimizer, Minuit_DecayingSin)
{
    DecayingSinPlan plan;
    EXPECT_TRUE(runMinimizerTest("Minuit2", "Migrad", plan));
}

/* known to fail
TEST(Minimizer, SteepestDescent_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "SteepestDescent", plan));
}
*/

TEST(Minimizer, SteepestDescent_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "SteepestDescent", plan));
}

TEST(Minimizer, ConjugateFR_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "ConjugateFR", plan));
}

TEST(Minimizer, ConjugateFR_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "ConjugateFR", plan));
}

TEST(Minimizer, ConjugatePR_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "ConjugatePR", plan));
}

TEST(Minimizer, ConjugatePR_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "ConjugatePR", plan));
}

TEST(Minimizer, Bfgs_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "BFGS", plan));
}

TEST(Minimizer, Bfgs_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "BFGS", plan));
}

TEST(Minimizer, Bfgs2_Rosenbrock)
{
    RosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "BFGS2", plan));
}

TEST(Minimizer, Bfgs2_WoodFour)
{
    WoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLMultiMin", "BFGS2", plan));
}

TEST(Minimizer, GSLSimAn_EasyRosenbrock)
{
    EasyRosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLSimAn", "Simulated annealing", plan));
}

TEST(Minimizer, GSLSimAn_EasyWoodFour)
{
    EasyWoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("GSLSimAn", "Simulated annealing", plan));
}

TEST(Minimizer, Genetic_EasyRosenbrock)
{
    EasyRosenbrockPlan plan;
    EXPECT_TRUE(runMinimizerTest("Genetic", "Genetic", plan, "RandomSeed=1"));
}

TEST(Minimizer, Genetic_EasyWoodFour)
{
    EasyWoodFourPlan plan;
    EXPECT_TRUE(runMinimizerTest("Genetic", "Genetic", plan, "RandomSeed=1"));
}

TEST(Minimizer, Fumili_DecayingSin)
{
    DecayingSinPlan plan;
    EXPECT_TRUE(runMinimizerTest("Minuit2", "Fumili", plan, "MaxFunctionCalls=10000"));
}

TEST(Minimizer, LevenbergMarquardtV3)
{
    DecayingSinPlanV2 plan;
    EXPECT_TRUE(runMinimizerTest("GSLLMA", "Levenberg-Marquardt", plan));
}
