Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПЗ_17.05..docx
Скачиваний:
9
Добавлен:
04.05.2019
Размер:
3.08 Mб
Скачать

1.3.3 Проектирование пользовательского интерфейса

Интерфейс пользователя приложения реализуем в виде графического оконного интерфейса. Он должен соответствовать потребностям пользователя, обеспечивать удобство работы и представление всей информации в наглядном и удобном виде. Необходимо предусмотреть: поля ввода для задания пользователем параметров генетического алгоритма, элементы интерфейса для вывода информации о текущей итерации и графе. Для удобства пользователя необходимо разместить кнопки управления процессом роботы генетического алгоритма. Главное окно приложение представлено на рисунке 1.18.

Элементы интерфейса перечислены в таблице 1.4.

Таблица 1.4 – Элементы интерфейса

Компонент

Класс

Функция

1

2

3

Панель

группирования

(сноска 1 рисунок 1.18)

GroupBox

Визуальное обрамление и соединение в группу элементов

Текстовое поле

(сноска 2 рисунка 1.18)

TextBox

Поля для ввода параметров ГА

Текстовое поле

(сноска 3 рисунка 1.18)

TextBox

Поле для вывода информации о графе, представляющем топологию сети.

Продолжение таблицы 1.4

1

2

3

Метки

(сноска 4 рисунок 1.18)

Label

Информация о том, что вводить в соответствующее текстовое поле

Метки

(сноска 5 рисунок 1.18)

Label

Вывод информации о текущей итерации ГА.

Комбинированный список

(сноска 6 рисунка 1.18)

ComboBox

Выбор фитнесс-функции и образца для нее, а также выбор порядка применения правил.

Кнопки

(сноска 7 рисунка 1.18)

Button

Кнопки для управления процессом эволюции, запуск или остановка ГА, сохранение или загрузка топологии из файла, просмотр информации о графе.

1

2

4

5

3

7

6

Рисунок 1.18 – Главное окно приложения

1.4 Описание программного обеспечения

Разработка ПО велась в среде Visual Studio 2010 на языке С#.

Для реализации генетического алгоритма была использована библиотека AForge.Genetic.

Наиболее интересным моментом в реализации генетического алгоритма в нашем случае является вычисление фитнесс-функции. Поэтому рассмотрим подробнее реализацию процесса ее вычисления.

Реализуем соответствующий абстрактный класс, описывающий фитнесс-функцию:

//фитнесс-функция

public abstract class PlanarGraphFitnessFunction : IFitnessFunction

{

// параметры фитнесс функции

protected int maxVertexCount;

protected int maxGUCAIterationCount;

protected bool isGenomeLengthPenalty;

protected bool isNotPlannedPenalty;

protected NumericalMethodParametres unfoldingParametres;

private TranscriptionWay transcriptionWay;

public PlanarGraphFitnessFunction(

int maxGUCAIterationCount,

int maxVertexCount,

bool isGenomeLengthPenalty,

bool isNotPlannedPenalty,

NumericalMethodParametres

unfoldingParametres,

TranscriptionWay transcriptionWay)

{

this.maxGUCAIterationCount = maxGUCAIterationCount;

this.maxVertexCount = maxVertexCount;

this.isGenomeLengthPenalty = isGenomeLengthPenalty;

this.isNotPlannedPenalty = isNotPlannedPenalty;

this.unfoldingParametres = unfoldingParametres;

this.transcriptionWay = transcriptionWay;

}

Так как целью нашей системы является выращивание заданной топологии, то в первую очередь нас интересуют геометрические свойства графа. Поэтому значение фитнесс-функции хромосомы должно быть тем больше, чем граф, построенный по правилам этой хромосомы, ближе к заданной топологии нейронной сети.

Для инициализации процесса расчета фитнесс-функции реализуем соответствующую процедуру:

//Расчёт фитнесс функции хромосомы

double IFitnessFunction.Evaluate(IChromosome chromosome)

{

double result;

int stepsPassed;

//выращивание графа по хромосоме

Physical2DGraph.Physical2DGraph graph = GrowGraph(chromosome, out stepsPassed);

// Фильтр на планарность, минимальный размер графа и т.п.:

result = this.EvaluateCommonFilter(graph, stepsPassed);

result = this.Evaluate(graph);

return result;

}

Для того чтобы уменьшить время расчета фитнесс-функции, необходимо отсеивать сразу неподходящие графы. Поэтому для фильтрации минимально жизнеспособных экземпляров (графов) реализуем соответствующую процедуру. Она будет проверять, чтобы граф содержал более одного узла, был планарным и т.п.

private double EvaluateCommonFilter(Physical2DGraph.Physical2DGraph graph, int stepsPassed)

{

// граф не должен состоять из одного узла ("мёртворождённый")

if (graph.VertexCount == 1)

{

return 0;

};

// граф не должен быть слишком велик

if ((graph.VertexCount >= maxVertexCount))

{

return 0.1;

}

// Процесс развёртывания графа его рост не должен быть бесконечным:

if (stepsPassed >= maxGUCAIterationCount - 2)

{

return 0.9;

}

bool isPlanar = graph.Planarize();

if (!isPlanar)

{

return 0.3;

}

return 1.0;

}

Отдельно реализуем процедуру, которая разворачивает граф по хромосоме:

public Physical2DGraph.Physical2DGraph GrowGraph(IChromosome chromosome, out int stepsPassed)

{

GUMGraph gumGraph = new GUMGraph();

gumGraph.AddVertex(new GUMNode(NodeState.A));

gumGraph.MaxVerticesCount = maxVertexCount;

gumGraph.MaxConnectionCount = 6;

GraphUnfoldingMachinegraphUnfoldingMachine=new GraphUnfoldingMachine(gumGraph);

graphUnfoldingMachine.MaxStepsCount = maxGUCAIterationCount;

graphUnfoldingMachine.Support1Connected = true;

graphUnfoldingMachine.TranscriptionWay = this.transcriptionWay;

graphUnfoldingMachine.ChangeTable=TranslateNative(chromosome);

graphUnfoldingMachine.Reset();

graphUnfoldingMachine.Run();

//Заполняем схему активности генов

int activeGensCount = 0;

bool priorGenIsActive = false;

int counter = 0;

if (graphUnfoldingMachine.ChangeTable.Count > 0)

{

priorGenIsActive=graphUnfoldingMachine.ChangeTable[0].WasActive;

}

StringBuilder sb = new StringBuilder();

foreach (var chi in graphUnfoldingMachine.ChangeTable)

{

if (chi.WasActive)

{ activeGensCount++;

}

if (chi.WasActive)

{ if (!priorGenIsActive)

{ sb.Append(counter);

} sb.Append("x");

counter = 1;

} else

{ counter++;

} priorGenIsActive = chi.WasActive;

} if (!priorGenIsActive)

{ sb.Append(counter);

} stepsPassed = graphUnfoldingMachine.PassedStepsCount;

(chromosome as MyChromosome).activeGensScheme = sb.ToString();

(chromosome as MyChromosome).activeGensCount = activeGensCount;

//Заполняем и передаём хромосоме карту активности битовой строки

System.Collections.BitArray activeGensBitArray = new System.Collections.BitArray(graphUnfoldingMachine.ChangeTable.Count,false);

for (int i = 0; i < graphUnfoldingMachine.ChangeTable.Count; i++)

{ if (graphUnfoldingMachine.ChangeTable[i].WasActive)

{ activeGensBitArray[i] = true;

}

} chromosome.SetActiveGensMask(activeGensBitArray);

return graphUnfoldingMachine.Graph; }

Для расчёта фитнесс-функций фенотипа (выращеного графа) объявим соответствующую процедуру:

public abstract double Evaluate(Physical2DGraph.Physical2DGraph graph);

Расшифровку хромосомы в набор правил производят следующие процедуры:

object IFitnessFunction.Translate(IChromosome chromosome)

{ return TranslateNative(chromosome);

}

public ChangeTable TranslateNative(IChromosome chromosome)

{ if (chromosome == null)

{return new ChangeTable();}

else {

return ((MyChromosome)chromosome).GetChangeTable();}}

}

Этот абстрактный класс описывает фитнесс-функцию в общем виде, от него будем наследовать классы, описывающие конкретные фитнесс-функции.

Полный листинг приведен в приложении А.

Для того чтобы описать особенности физического представления подсистемы построим диаграмму компонентов. Диаграмма компонентов позволяет определить архитектуру разрабатываемой системы, установив зависимости между соответствующими программными компонентами. Диаграмма компонентов представлена на рисунке 1.19.