// Metaheuristics.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
#include <random>
#include "ObjectiveFunction.h"
#include "BinaryAntColonyAlgoritm.h"
#include "GeneticAlgorithm.h"
#include <fstream>
#include <functional>
#include <algorithm>
#include <iterator>


void onemax() {
    std::fstream file("ga_setting3.csv", std::ios::out);
    if (!file.is_open()) {
        std::cout << "Cant open file";
    }
    objective::OneMax onemax(100, 1);
    auto f = std::bind(&objective::OneMax::function, &onemax, std::placeholders::_1);


    ///*Baco instance with parameter: iteration, population, vaporization, resetThreshhold, ostream*/
    //Baco instance(file, 1000, 100, 0.05, 0.99);
    /*GeneticAlgorithm instance with parameter: iteration, population, mutateProbability, swapProbability, tournamentsize*/
    GeneticAlgorithm instance(file, 101, 20, 0.005, 0.7, 2.0);
    Solution sol = instance.execute(10, 100, f, BinaryHeuristic::ObjectiveFunctionGoal::max);
    std::cout << "Value: " << sol.objectiveFunctionValue << std::endl;
    file.close();
}
void knapsack() {
    std::fstream file("ga_setting1.csv", std::ios::out);
    if (!file.is_open()) {
        std::cout << "Cant open file";
    }
    /*GeneticAlgorithm instance with parameter: iteration, population, mutateProbability, swapProbability, tournamentsize*/
    GeneticAlgorithm instance(file, 100, 20, 0.01, 0.7, 2.0);

    //Generate Problem
    objective::KnapsackProblem knapsack(275.0, 2000);
    //generate Items
    double value = 5;
    double weight = 0;
    for (int i = 0; i < 100; i++) {
        if (i % 10 == 0) {
            value++;
            weight++;
        }
        objective::Item item;
        item.value = value;
        item.weight = weight;
        knapsack.itemVec.push_back(item);
    }
    //Bind as callable object
    auto f1 = std::bind(&objective::KnapsackProblem::function, &knapsack, std::placeholders::_1);
    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
    Solution sol = instance.execute(10, 100, f1, BinaryHeuristic::ObjectiveFunctionGoal::max);
    std::cout << "Value: " << sol.objectiveFunctionValue << std::endl;
    std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
    std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
    std::cout << "Time: " << time.count() << "ms";
    file.close();
}

void knapsack2() {
    std::fstream file("onemaxtrigger.csv", std::ios::out);
    if (!file.is_open()) {
        std::cout << "Cant open file";
    }
    /*GeneticAlgorithm instance with parameter: iteration, population, mutateProbability, swapProbability, tournamentsize*/
    GeneticAlgorithm instance(file, 100, 20, 0.01, 0.6, 7);
    /*Baco instance with parameter : iteration, population, vaporization, resetThreshhold, ostream */
    //Baco instance(file, 1000, 20, 0.10, 0.999);
    //Generate Problem
    objective::KnapsackProblem knapsack(275.0, 2000);
    //generate Items
    double value = 5;
    double weight = 0;
    for (int i = 1; i < 99; i++) {
        objective::Item item;
        bool trigger = false;
        //item.value = normal_pdf(i/100.0, 0.5, 0.5) * 10.0 * (trigger? 0:1);

        //std::cout << item.value << " ";
        item.weight = weight;
        knapsack.itemVec.push_back(item);
    }
    //Bind as callable object
    auto f1 = std::bind(&objective::KnapsackProblem::function, &knapsack, std::placeholders::_1);
    Solution sol = instance.execute(10, 100, objective::onemaxTrigger, BinaryHeuristic::ObjectiveFunctionGoal::max);
    std::cout << "Value: " << sol.objectiveFunctionValue << std::endl;
    file.close();
}

int main()
{
    onemax();
    return 0;
}
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu

// Tips for Getting Started: 
//   1. Use the Solution Explorer window to add/manage files
//   2. Use the Team Explorer window to connect to source control
//   3. Use the Output window to see build output and other messages
//   4. Use the Error List window to view errors
//   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
//   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
