#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <math.h>
 
using namespace std;
 
class sa_tsp{
public:
        void init(int);
        void wczytaj(string);
        int symulacja();
        int* copy(int*);
        bool accept(int , int, double);
        void run(string, int);
        void piszTrase(int*);
 
 
        int n; //liczba miast
        int** koord; //wspolrzedne miast
        int** odl; // odleglosci miedzy miastami
        int* trasa; //aktualna trasa
        int* sasiad; // trasa zmutowana(sąsiad)
        int* trasaBest;// najlepsza trasa
        int dlg; // dlugosc aktualnej trasy
        int dlgBest; //dlugosc najlepszej trasy
        static const int maxRows = 5000;
        double** stat; 
};
 
void sa_tsp::init(int n){
        odl = new int*[n];
        koord = new int*[n];
        trasa = new int[n];
        sasiad = new int[n];
        trasaBest = new int[n];
        for (int i = 0; i < n; i++){
                odl[i] = new int[n];
                koord[i] = new int[2];
        }
}
// funkcja wczytujaca wspolrzedne z pliku. Nazwa pliku przekazywana jest
// jako parametr wejściowy
void sa_tsp::wczytaj(string plik){
        ifstream ifs;
        string tekst;
 
        ifs.open(plik);
        if (ifs.good()){
                while (tekst.find("DIMENSION:") == string::npos){
                        getline(ifs, tekst);
                }      
 
        }
        else
                cout << "Nie udalo sie otworzyc pliku." << endl;
}
 
int sa_tsp::symulacja()
{
        int i, j;
        int jj = 0;
       
        // Liczba tras do wyznaczenia temperatury
        int ile = 10;
       
        // Długość mutanta
        int dlgTemp;
       
        double T = 0;
        double Tlen = 0;
        double alpha = 0.95;
 
        dlgBest = pow(2,31-1);
       
        // Wyznaczanie startowej trasy
        for(i=0; i<ile; i++)
        {
                makeTour();
                Tlen += dlg;
                if(dlg<dlgBest)
                {
                        trasaBest = copy(trasa);
                        dlgBest = dlg;
                }
        }
 
        T = 600;
        cout << "T: " << T << " " << dlgBest << " " << Tlen;
       
        // Początkowa trasa
        trasa = copy(trasaBest);
       
        // Długość początkowej trasy
        dlg = dlgBest;
 
        bool success = false;
        bool found = false;
        bool done = false;
        // Liczy iteracje
        int iter = 0;
 
        // Liczy porażki
        int fail = 0;
 
        //Liczy sukcesy
        int succ;
 
        while(!done)
        {
 
                i = 0;
                succ = 0;
                success = false;
                while(!success)
                {
 
                        dlgTemp = mutacja1(dlg);
                        if(accept(dlgTemp, dlg, T))
                        {
                                trasa = copy(sasiad);
                                dlg = dlgTemp;
                                if(dlgTemp < dlgBest)
                                {
                                        trasaBest = copy(sasiad);
                                        dlgBest = dlgTemp;
                                        found = true;
                                        succ++;
                                }
                        }
                        i++;
                        iter++;
                        if(iter%100 == 0)
                        {
                                if(jj < maxRows)
                                {
                                        stat[jj][0]++;
                                        stat[jj][1] += dlgBest;
                                        jj++;
                                }
                        }
                        success = (i>100*n || succ>10*n);
 
                }
 
                T = T*alpha;
                if(found)
                {
                        fail = 0;
                }
                else
                        fail++;
                done = (fail == 5);
 
        }
 
        cout << "Tend: " << T;
        return dlgBest;
}
 
int* sa_tsp::copy(int* tour)
{
        int* tmp = new int[n];
       
        for(int i=0; i<n; i++)
                tmp[i] = tour[i];
 
        return tmp;
}
 
bool sa_tsp::accept(int dlgTemp, int dlg, double T)
{
        double yes = false;
        float r = 1.0;
       
        do
        {
                r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        }
        while(r<0.0 || r>=1.0);
 
        if(dlgTemp<dlg)
        {
                yes = true;
        }
        else
        {
                yes = (r<exp(-(dlgTemp-dlg)/T));
        }
        return yes;
}
 
void sa_tsp::run(string fname, int maxEpoch)
{
        readData(fname);
        computeDist();
        //maxEpoch = 1;
        for(int epoch = 0; epoch<maxEpoch; epoch++)
        {
                symulacja();
        }
        for(int i=0; i<maxRows; i++)
        {
                if(stat[i][0]>0)
                {
                        stat[i][1] /= stat[i][0];
                        cout << (100*i) << " " << stat[i][1];
                }
        }
}
 
void sa_tsp::piszTrase(int* trasa)
{
        for(int i=0; i<n; i++)
                cout << trasa[i] << " ";
}
 
int _tmain(int argc, _TCHAR* argv[])
{
        sa_tsp problem = sa_tsp();
 
        problem.wczytaj("kroA100.tsp");
 
        cin.clear();
        cin.sync();
        cin.get();
        return 0;
}