private SA_Solution Run(double?initTemp, double?tempDecreasingCoefficient, long?maxRepetitionsWithoutImprovement)
        {
            Random random = new Random();

            SA_Solution initSolution = new SA_Solution(_distanceMatrix.GetLength(0), true, random);
            SA_Solution oldSolution  = initSolution;
            SA_Solution bestSolution = new SA_Solution(initSolution.Clone());

            double?temp      = initTemp;
            double oldResult = 0;
            double newResult = 0;

            int repetitionsWithoutImprovement = 0;

            while (repetitionsWithoutImprovement < maxRepetitionsWithoutImprovement)
            {
                SA_Solution newSolution = oldSolution.CreateNewSolutionWithSwappedTwoElements(random);
                oldResult = oldSolution.FunctionValue(_distanceMatrix);
                newResult = newSolution.FunctionValue(_distanceMatrix);

                if (newResult < bestSolution.FunctionValue(_distanceMatrix))
                {
                    bestSolution = newSolution;
                }

                if (newResult < oldResult)
                {
                    oldSolution = newSolution;
                    repetitionsWithoutImprovement = 0;
                }
                else if (random.NextDouble() < CalculateProbability(oldResult, newResult, temp))
                {
                    oldSolution = newSolution;
                    repetitionsWithoutImprovement++;
                }
                else
                {
                    repetitionsWithoutImprovement++;
                }
                temp *= tempDecreasingCoefficient;
            }

            PrepareLogger();
            _loggerFile.WriteLine("");
            LogPermutation(bestSolution.Permutation, bestSolution.FunctionValue(_distanceMatrix));
            LogDistancesForSolution(bestSolution);
            FinalizeLogger();

            return(bestSolution);
        }