#include <gtest/gtest.h>
#include <json.hpp>
//#define private public
#include <OptimizerEvolutionary.h>
#include <Registration.h>

using namespace mdd;
namespace TEST_OPTIMIZER_EVOLUTION {

    auto regi = Registration();
    
    TEST(OptimizerEvolutionary, OptimizeSimpleFormula) {
        //optimize f(x)=a*b
        IModule::Ptr f1 = regi.generateModule("ModuleMath");
    
        json config = f1->getConfiguration();
        config["configure"]["operation"]["value"] = "multiply";
        f1->configure(config.dump());
        limits limit;
        limit.min = { -10 };
        limit.max = { 10 };
        limit.step = { 1 };
    
        f1->getInput(0)->setLimits() = std::make_shared<limits>(limit);
        f1->getInput(1)->setLimits() = std::make_shared<limits>(limit);
    
        f1->getInput(0)->setOptimizability(true);
        f1->getInput(1)->setOptimizability(true);
        f1->getOutput(0)->setOptimizability(true);
    
        OptimizerEvolutionary optimizer;
        optimizer.connect(f1);
        config = optimizer.getConfiguration();
        config[0]["value"] = 5;
        optimizer.configure(config.dump());
    
        optimizer.setEvaluation("out0");
    
        optimizer.update();
        auto res = optimizer.getBests()[0].dna;
        //std::cout << res.dump() << std::endl;
        EXPECT_EQ(res[0][0]* res[1][0],-100);
    }
    
    TEST(OptimizerEvolutionary, OptimizeSimpleFormulaWithSimpleRestriction) {
        //optimize f(x)=a*b
        IModule::Ptr f1 = regi.generateModule("ModuleMath");
    
        json config = f1->getConfiguration();
        config["configure"]["operation"]["value"] = "multiply";
        f1->configure(config);
        limits limit;
        limit.min = { -10 };
        limit.max = { 10 };
        limit.step = { 1 };
        limit.rule = "val[0] != -10";
    
        f1->getInput(0)->setLimits() = std::make_shared<limits>(limit);
        f1->getInput(1)->setLimits() = std::make_shared<limits>(limit);
    
        f1->getInput(0)->setOptimizability(true);
        f1->getInput(1)->setOptimizability(true);
        f1->getOutput(0)->setOptimizability(true);
    
        OptimizerEvolutionary optimizer;
        optimizer.connect(f1);
        config = optimizer.getConfiguration();
        config["converges"]["value"] = 5;
        optimizer.configure(config);
    
        optimizer.setEvaluation("out0");
    
        optimizer.update();
        auto res = optimizer.getBests()[0].dna;
        //std::cout << res.dump() << std::endl;
        EXPECT_EQ(res[0][0]* res[1][0],-90);
    }
//*/
}