/// <summary> /// Obtiene el porcentaje de soluciones aceptadas que se generaron /// a partir de una solución inicial con una temperatura /// </summary> /// <param name="solution">solución inicial para recorrer el espacio de soluciones</param> /// <param name="T">temperatura inicial permite conocer el porcentaje de soluciones promedio para dicha temperatura</param> /// <returns>porcentaje de soluciones aceptadas para una temperatura inicial</returns> private double percentage_accepted(ISolution solution, double T) { ISolution s = (ISolution)solution.Clone(); //Cantidad de soluciones aceptadas double c = 0; //Se generan N vecinos a partir de una solución for (int i = 0; i < N_PERCENTAGE_ACCEPTED; i++) { ISolution s1 = s.getNeighbour(random); //Si el vecino es aceptado se incrementa la cantidad //de soluciones aceptadas if (isAccepted(s1, solution, T)) { c++; } //Siempre se intercambia la solución por el vecino para //para explorar más en el conjunto de soluciones s = s1; } //Retorna cantidad de soluciones aceptadas sobre el numero //de soluciones que se generon en total return((double)c / (double)N_PERCENTAGE_ACCEPTED); }
private void FindSolutionsRecursive(ArrayList result, int level, ISolutionEnumerator enumerator) { ISolution solution = GetSolution(level); Debug.Assert(solution != enumerator.StartingPartialSolution); while (enumerator.FillDescendantSolution(solution)) { //Console.Write(solution.ToString()); //Console.ReadLine(); if (solution.IsComplete) { //Console.Write(solution.ToString()); //Console.ReadLine(); result.Add(solution.Clone()); } else { ISolutionEnumerator descendantEnumerator = GetSolutionEnumerator(level + 1); solution.FillDescendantSolutionEnumerator(descendantEnumerator); descendantEnumerator.StartingPartialSolution = solution; FindSolutionsRecursive(result, level + 1, descendantEnumerator); } } }
public IEnumerable<ISolution> GetNeighbors(ISolution solution) { for (int i = 1; i < solution.Count; i++) for (int j = i + 1; j <= solution.Count; j++) { ISolution item = solution.Clone(); var t = item.Items[i]; item.Items[i] = item.Items[j]; item.Items[j] = t; yield return item; } }
/// <summary> /// Calcula un lote a partir de una solucion inicial y una temperatura dada /// </summary> /// <param name="T">Temperatura en la que se encuentra la simulación</param> /// <param name="solution">solucion inicial</param> /// <param name="random">objeto permite aleatoriedad</param> /// <returns></returns> public double calculate_batch(double T, ISolution solution, Random random) { this.temperature = T; ISolution s = (ISolution)solution.Clone(); best = s; //Cantidad de soluciones aceptadas int c = 0; double r = 0; int iterations = 0; finished = false; while (c < L && iterations < MAX_ITERATIONS) { ISolution s1 = s.getNeighbour(random); if (s1.calculateCostFunction() < best.calculateCostFunction()) { best = s1; } double s1_cost_function = s1.calculateCostFunction(); double s_cost_function = s.calculateCostFunction(); if (s1_cost_function <= (s_cost_function + T)) { s = s1; c = c + 1; r = r + s1_cost_function; //Guarda todas las soluciones generadas por el lote solutions.Add(s1); //Console.WriteLine(s1_cost_function); costs_functions.Add(s1_cost_function); } iterations = iterations + 1; } finished = c == L; lastSolution = s; return(r / (double)L); }
public ISolution Combine(ISolution solutionFirst, ISolution solutionSecond) { Random rnd = new Random(); ISolution result = solutionFirst.Clone(); int k = rnd.Next(solutionFirst.Count) + 1; for (int i = 1; i <= k; i++) result.Items[i] = solutionFirst.Items[i]; for (int i = 1; i <= solutionSecond.Count; i++) if (!result.Items.Contains(solutionSecond.Items[i])) { result.Items[k] = solutionSecond.Items[i]; k++; } return result; }
public ISolution GetBestNeighbor(ISolution solution) { ISolution result = null; for (int i = 1; i < solution.Count; i++) for (int j = i + 1; j <= solution.Count; j++) { ISolution item = solution.Clone(); var t = item.Items[i]; item.Items[i] = item.Items[j]; item.Items[j] = t; if (result == null || result.Cost > item.Cost) result = item; } if (result == null) result = solution; return result; }
/// <summary> /// Obtiene una temperatura que aumenta la probabilidad /// de desplazarse más rapida y efectivamente por el /// conjunto de soluciones, evitando de igual forma /// que sea un enfriamiento demasiado lentp /// </summary> /// <param name="solution">Solución inicial (aleatoria)</param> /// <param name="T">temperatura inicial arbitraria </param> /// <param name="P"> /// Porcentaje de soluciones que se desea sean aceptadas /// por la temperatura inicial que se quiere encontrar. Aprox /// .85<= p <= .95 /// </param> /// <returns></returns> private double initial_temperature(ISolution solution, double T, double P) { ISolution s = (ISolution)solution.Clone(); /** * Se calcula el porcentaje de soluciones aceptadas * a partir de la temperatura arbitraria que se tomo */ double p = percentage_accepted(s, T); double T1, T2; /** * Si la diferencia entre el porcentaje de soluciones * aceptadas a partir de los datos iniciales se acerca * bastante al porcentaje de soluciones que se quiere * acepte la temperatura inicial es decir p sea casi p * se dice que la temperatura dada es un temperatura * adecuada para iniciar el algoritmo **/ if (Math.Abs(P - p) <= EP_INITIAL_TEMPERATURE) { return(T); } /** * Si el porcentaje de soluciones aceptadas (p) es menor * al porcentaje P que se desea tener, se incrementa la * temperatura al doble **/ if (p < P) { /** * Mientras el porcentaje de soluciones aceptas p siga * siendo menor que el porcentaje que se desea se aumenta * la temperatura y se evalua hasta que el porcentaje de * aceptados se mayor que el que se desea **/ while (p < P) { T = 2 * T; p = percentage_accepted(s, T); } /** * --------|------------|----------- * temp/2 temp **/ T1 = T / 2; T2 = T; } else { /** * Por el contrario si el numero de aceptados excede * el porcentaje de aceptados que se desea, la temperatura * se disminuye y se evalua hasta que el porcentaje de aceptados * sea el apropiado **/ while (p > P) { T = T / 2; p = percentage_accepted(s, T); } /** * --------|------------|----------- * temp 2 * temp **/ T1 = T; T2 = 2 * T; } /** * Realiza una busqueda binaria entre T1 y T2 * --------|----------|----------|----------- * T1 ? T2 * con el objetivo de encontrar un valor intermedio * entre estos que se acerque más al porcentaje de * aceptados que se quiere. * temp ha sido cambiado entre 2 incrementandolo y * decrementandolo por eso se hacen las operaciones * respectivas para obtener T1 o T2 **/ return(binary_search(s, T1, T2, P)); }