#include "ObjectiveFunction.h"
#include <algorithm>
#include <iostream>

double objective::onemaxLinear(const std::vector<bool>& bitstring)
{
	return (double)std::count(bitstring.begin(), bitstring.end(), true);
}

double objective::onemaxWithTrap(const std::vector<bool>& bitstring)
{
	int x = std::count(bitstring.begin(), bitstring.end(), true);
	if (x < 70) {
		return x;
	}
	else if (70 <= x && x < 80) {
		return x;//70 + x*0.000000001;//return 140.0 - x;
	}
	else if (80 <= x && x < 90) {
		return x;//70 + x*0.000000001;//return x - 20.0;
	}
	else {
		return 3.0*x -200.0;
	}

	
}
float normal_pdf(float x, float m, float s)
{
	static const float inv_sqrt_2pi = 0.3989422804014327;
	float a = (x - m) / s;

	return inv_sqrt_2pi / s * std::exp(-0.5f * a * a);
}
double objective::onemaxTrigger(const std::vector<bool>& bitstring)
{
	if (bitstring.size() != 100) {
		return 0;
	}
	double sum = 0;
	if (bitstring[0]) sum += normal_pdf(0 / 100.0, 0.5, 0.5);
	if (bitstring[99]) sum += normal_pdf(99 / 100.0, 0.5, 0.5);
	for (int i = 1; i < 99; i++) {
		bool trigger = bitstring[i-1] && bitstring[i] && bitstring[i+1];
		if(bitstring[i]) sum += (1 - normal_pdf(i / 100.0, 0.5, 0.5)) * (trigger ? 0 : 1);
	}
	return sum;
}






Solution::Solution()
{
}

Solution::Solution(std::vector<bool> bitstring, double objectiveFunctionValue):
	bitstring(bitstring), objectiveFunctionValue(objectiveFunctionValue)
{
}

std::string Solution::bitstringToStdString()
{
	std::string str(bitstring.size(), 0);
	std::transform(bitstring.begin(), bitstring.end(), str.begin(),
		[](bool b) -> char { return b?'1':'0'; });
	return str;
}

objective::KnapsackProblem::KnapsackProblem(double weightLimit, double limitPenalty) : weightLimit(weightLimit), limitPenalty(limitPenalty)
{
}

double objective::KnapsackProblem::function(const std::vector<bool>& bitstring)
{
	double value = 0, weight = 0;
	int lastIndex = std::min(itemVec.size(), bitstring.size());
	for (int i = 0; i < lastIndex; i++) {
		if (bitstring[i]) {
			value += itemVec[i].value;
			weight += itemVec[i].weight;
		}
	}
	if (weight < weightLimit) {
		return value;
	}
	return value -limitPenalty;
}

objective::OneMax::OneMax(int n, int k): results(n+1)
{
	generateKStep(k);
}

void objective::OneMax::generateKStep(int step)
{
	std::cout << "Results:";
	int result = 0;
	for(int i = 0; i < results.size(); i++) {
		results[i] = result;
		std::cout << result << " ";
		if (i % step == 0) {
			result++;
		}
	}
	std::cout << std::endl;
}

double objective::OneMax::function(const std::vector<bool>& bitstring)
{
	int x = std::count(bitstring.begin(), bitstring.end(), true);
	if (x < results.size()) {
		return results[x];
	}
	else {
		return results[results.size() - 1];
	}
}
