- •Содержание
- •Введение
- •1 Постановка задачи
- •2 Модель решения задачи
- •3 Алгоритм решения задачи
- •4 Реализация методов решения задачи
- •5 Архитектура программы
- •6 Графический интерфейс пользователя
- •7 Тестирование программы
- •8 Демонстрация работы программы
- •Заключение
- •Список использованных источников
- •Приложение а
3 Алгоритм решения задачи
Принцип действия генетического алгоритма (блок-схема) приведен на рисунке 1.
Рисунок 1- Блок-схема генетического алгоритма
Случайным образом формируется начальная хромосома, состоящая из номеров технологических операций, после чего производится сортировка операций в зависимости от времени перенастройки оборудования между операциями. Хромосомы представляют собой набор целочисленных значений номеров технологических операций.
На основании начальной хромосомы путем перестановок операций производится создание первого поколения хромосом – популяции. Таким образом, популяция представляет собой двухмерный массив целых чисел.
В ходе выполнения алгоритма при помощи фитнесс-функции выбираются хромосомы для скрещивания. Наиболее «приспособленными» хромосомами считаются те, у которых суммарное время перенастройки оборудования меньшее.
На этапе скрещивания производится обмен участками хромосом двух родителей. Обмен хромосом реализован при помощи двухточечного кроссовера, при котором выбираются локусы (позиции в массивах), которыми меняются хромосомы. Поскольку в данном примере необходимо наиболее эффективно расположить технологические операции, которые в том числе не должны дублироваться, производится корректировка и замена номеров повторяющихся операций на номера отсутствующих операций. Механизм двухточечного кроссовера представлен на рисунке 1.
Рисунок 2- Скрещивание хромосом
Над новым поколением хромосом с заданной вероятностью производится мутация. Процесс мутации представляет собой случайный обмен двух генов внутри одной хромосомы – перестановка двух технологических операций. Механизм операции мутации приведен на рисунке 2.
Рисунок 3 - Мутация хромосом
После выполнения генетических операций производится оценка «приспособленности» новой популяции. Если в течение заданного времени стагнации не происходит появление «лучшей» особи, механизм прекращает работу.
При увеличении времени стагнации возрастает эффекивность алгоритма, так как будет выполнено большее количество генетических операций. Однако при этом увеличивается время выполнения алгоритма.
.
4 Реализация методов решения задачи
В ходе реализации проекта было написано веб-приложение, состоящее из нескольких классов и интерфейсов для решения поставленной задачи.
Реализация генетического алгоритма приведена в классе GeneticEngine.
package engine; import matrix.BestResult; import matrix.FirstGeneration; import matrix.Result; import matrix.Time; import java.util.Random; public class GeneticEngine { public GeneticEngine(Time time, FirstGeneration firstGeneration, FitnessFunction fitnessFunction, int stagnationTime){ this.setTime(time); this.setFirstGeneration(firstGeneration); this.setStagnationTime(stagnationTime); this.setPopulationSize(firstGeneration.getPopulationSize()); this.setGeneticSize(firstGeneration.getSize()); this.setFitnessFunction(fitnessFunction); this.random = new Random(); this.reversalOperationNumbers = new int[getPopulationSize()][getGeneticSize()]; this.setGeneticOperationsCurrent(new int[getPopulationSize()][getGeneticSize()]); this.reversalOperationNumbers = firstGeneration.getReversalOperationNumbers().clone(); this.setBestResults(new BestResult()); } private Time time; private FirstGeneration firstGeneration; //number of gens private int geneticSize; private int populationSize; private int stagnationTime; //reversal operationNumbers (population) private int[][] reversalOperationNumbers; //array to store reversal operations private int[][] geneticOperationsCurrent; //fitness function local private FitnessFunction fitnessFunction; //random generator private Random random; private BestResult bestResults; public void run(){ Result result = new Result(); //get parameters this.getFitnessFunction().getGenerationBestResult(this.getreversalOperationNumbers(), result); this.getBestResults().setFirstGenerationBestResultValue(result.getResultValue()); this.getBestResults().setFirstGenerationBestResult(result.getResult()); this.getBestResults().setTime(time); int[][]reversalOperationNumbers = this.getreversalOperationNumbers().clone(); int[][] geneticOperationsCurrent = new int[getPopulationSize()][getGeneticSize()]; int fitnessFunctionCurrentResult; int bestResulCurrentGeneration = result.getResultValue(); long start = System.currentTimeMillis(); //long run = start; long cur = System.currentTimeMillis(); while (cur - start < getStagnationTime() * 1000) { this.selection(reversalOperationNumbers, geneticOperationsCurrent, populationSize); this.crossing(geneticOperationsCurrent, populationSize); this.mutation(geneticOperationsCurrent); fitnessFunctionCurrentResult = this.getFitnessFunction().getFitnessFunctionResult(geneticOperationsCurrent[0]); int fitnessFunctionGenerationResult; for (int index = 1; index < populationSize; index++) { fitnessFunctionGenerationResult = this.getFitnessFunction().getFitnessFunctionResult(geneticOperationsCurrent[index]); fitnessFunctionCurrentResult = fitnessFunctionCurrentResult > fitnessFunctionGenerationResult ? fitnessFunctionGenerationResult : fitnessFunctionCurrentResult; } if (bestResulCurrentGeneration > fitnessFunctionCurrentResult){ bestResulCurrentGeneration = fitnessFunctionCurrentResult; int[][] tmp = reversalOperationNumbers; this.setreversalOperationNumbers(geneticOperationsCurrent); this.setgeneticOperationsCurrent(tmp); reversalOperationNumbers = geneticOperationsCurrent; geneticOperationsCurrent = tmp; start = System.currentTimeMillis(); } cur = System.currentTimeMillis(); } int bestFitnessFunctionResult = fitnessFunction.getFitnessFunctionResult(getreversalOperationNumbers()[0]); for (int[] genom : this.getreversalOperationNumbers()) { int fitnessFunctionResult = this.fitnessFunction.getFitnessFunctionResult(genom); if (bestFitnessFunctionResult >= fitnessFunctionResult) { bestFitnessFunctionResult = fitnessFunctionResult; this.getBestResults().setBestResult(genom); this.getBestResults().setBestResuktValue(bestFitnessFunctionResult); } } } private void selection(int[][] reversalOperationNumbers, int[][] geneticOperationsCurrent, int populationSize) { for (int i = 0; i < populationSize; i++) { int index1 = getRandom().nextInt(populationSize); int index2 = getRandom().nextInt(populationSize); int fr1 = this.fitnessFunction.getFitnessFunctionResult(reversalOperationNumbers[index1]); int fr2 = this.fitnessFunction.getFitnessFunctionResult(reversalOperationNumbers[index2]); geneticOperationsCurrent[i] = fr1 >= fr2 ? reversalOperationNumbers[index2].clone() : reversalOperationNumbers[index1].clone(); } } private void crossing(int[][] geneticOperationsCurrent, int populationSize) { for (int i = 0; i < populationSize / 2; i++) { int index1 = i << 1; int index2 = index1 | 1; cross(geneticOperationsCurrent[index1], geneticOperationsCurrent[index2]); } } private void cross(int[] genom1, int[] genom2) { int index1 = this.getRandom().nextInt(this.geneticSize); int index2 = this.getRandom().nextInt(this.geneticSize); int startIndex = Math.min(index1, index2); int endIndex = Math.max(index1, index2); for (int i= startIndex; i <= endIndex; i++){ int rep = genom2[i]; int tmp = genom1[i]; genom1[i] = rep; genom2[i] = tmp; for (int index = 0; index < genom1.length; index ++ ){ if (genom1[index] == rep && index != i){ genom1[index] = tmp; } } for (int index = 0; index < genom2.length; index ++ ){ if (genom2[index] == tmp && index != i){ genom2[index] = rep; } } } } // Mutation - Mutate all genom in generation private void mutation(int[][] geneticOperationsCurrent) { for (int[] genom : geneticOperationsCurrent) { if (getRandom().nextDouble() <= 0.1) { mutate(genom); } } } private void mutate(int[] genom) { int randomValue = (int) (Math.random() * (genom.length)); int randomValue2 = (int) (Math.random() * (genom.length)); int value = genom[randomValue]; genom[randomValue] = genom[randomValue2]; genom[randomValue2] = value; } private int getGeneticSize() { return geneticSize; } private void setGeneticSize(int geneticSize) { this.geneticSize = geneticSize; } private int getPopulationSize() { return populationSize; } private void setPopulationSize(int populationSize) { this.populationSize = populationSize; } private int[][] getreversalOperationNumbers() { return reversalOperationNumbers; } private FitnessFunction getFitnessFunction() { return fitnessFunction; } private void setFitnessFunction(FitnessFunction fitnessFunction) { this.fitnessFunction = fitnessFunction; } private void setgeneticOperationsCurrent(int[][] geneticOperationsCurrent) { this.setGeneticOperationsCurrent(geneticOperationsCurrent); } private void setreversalOperationNumbers(int[][] reversalOperationNumbers) { this.reversalOperationNumbers = reversalOperationNumbers; } private Random getRandom() { return random; } public Time getTime() { return time; } public void setTime(Time time) { this.time = time; } public FirstGeneration getFirstGeneration() { return firstGeneration; } public void setFirstGeneration(FirstGeneration firstGeneration) { this.firstGeneration = firstGeneration; } public int[][] getGeneticOperationsCurrent() { return geneticOperationsCurrent; } public void setGeneticOperationsCurrent(int[][] geneticOperationsCurrent) { this.geneticOperationsCurrent = geneticOperationsCurrent; } public BestResult getBestResults() { return bestResults; } public void setBestResults(BestResult bestResults) { this.bestResults = bestResults; } public int getStagnationTime() { return stagnationTime; } public void setStagnationTime(int stagnationTime) { this.stagnationTime = stagnationTime; } }
В конструкторе класса производится инициализация полей.
Метод run реализует бизнес-логику генетического алгоритма.
Метод selection реализует механизм селекции хромосом, методы crossing и mutation – скрещивание и мутацию хромосом соответственно.
Класс FitnessFunctionMax содержит реализацию фитнесс-функции.
import matrix.FirstGeneration; import matrix.Result; import matrix.Time; import java.util.Random; public class FitnessFunctionMax implements FitnessFunction { public FitnessFunctionMax(Time time, FirstGeneration firstGeneration){ this.setRandom(new Random()); this.setTime(time); this.setFirstGeneration(firstGeneration); this.setGeneticSize(firstGeneration.getSize()); } private FirstGeneration firstGeneration; private Time time; private Random random; private int geneticSize; public int getFitnessFunctionResult(int []displacedOperations){ int fullTime = 0; int firstOperation; int lastOperation; for(int operationIndex = 0; operationIndex < geneticSize - 1; operationIndex++){ firstOperation = displacedOperations[operationIndex] - 1; lastOperation = displacedOperations[operationIndex + 1] - 1; fullTime += getTime().getMatrixTime()[firstOperation][lastOperation]; } return fullTime; } public void getGenerationBestResult(int[][] geneticoperationNumbers, Result result){ int bestResult = this.getFitnessFunctionResult(geneticoperationNumbers[0]); int[] tmp; for (int[] gen : geneticoperationNumbers) { int resultFitnessFunction = this.getFitnessFunctionResult(gen); if (bestResult >= resultFitnessFunction) { tmp = new int[gen.length]; System.arraycopy(gen, 0, tmp, 0, gen.length); result.setResult(tmp); bestResult = resultFitnessFunction; } } result.setResultValue(bestResult); } private Random getRandom() { return random; } private void setRandom(Random random) { this.random = random; } public FirstGeneration getFirstGeneration() { return firstGeneration; } public void setFirstGeneration(FirstGeneration firstGeneration) { this.firstGeneration = firstGeneration; } public Time getTime() { return time; } public void setTime(Time time) { this.time = time; } public int getGeneticSize() { return geneticSize; } public void setGeneticSize(int geneticSize) { this.geneticSize = geneticSize; } }
Метод getGenerationBestResult предназначен для определения лучшего результата фитнесс-функции для популяции. Метод getFitnessFunctionResult – для определения значения фитнесс-функции для текущей хромосомы.
