- •Содержание
- •Введение
- •1 Программное обеспечение реализации генетического алгоритма в составе системы выращивания топологии нейронной сети
- •1.1 Анализ требований
- •1.1.1 Постановка задачи
- •1.1.2 Анализ предметной области
- •1.1.2.1 Независимое применение генетических алгоритмов и нейронных сетей
- •1.1.2.2 Нейронные сети для поддержки генетических алгоритмов
- •1.1.2.3 Генетические алгоритмы для поддержки нейронных сетей
- •1.1.2.4 Применение генетических алгоритмов для обучения нейронных сетей
- •1.1.2.5 Генетические алгоритмы для выбора топологии нейронных сетей
- •1.1.2.6 Адаптивные взаимодействующие системы
- •1.1.2.7 Нейроэволюционные методы
- •1.1.3 Анализ существующих аналогов
- •1.1.4 Методы и средства решения поставленной задачи
- •1.1.4.1 Методы решения задачи и варианты использования разрабатываемого программного обеспечения
- •1.1.4.2 Технологические средства разработки
- •1.2 Математическая модель предметной области
- •1.3 Проектирование
- •1.2.1 Проектирование структур данных
- •1.3.2 Проектирование структуры программного обеспечения и алгоритмов
- •1.3.3 Проектирование пользовательского интерфейса
- •1.4 Описание программного обеспечения
- •1.5 Результаты тестирования
- •2 Технико-экономическое обоснование разработки по для реализации генетического алгоритма в составе системы выращивания топологии нейронной сети
- •2.1 Расчет затрат на разработку программы
- •2.2 Расчет цены разработанной программы
- •2.3 Расчет капитальных вложений
- •2.4 Расчет эксплуатационных расходов
- •2.5 Расчет денежного годового экономического эффекта
- •2.6 Определение показателей эффективности инвестиций
- •2.7 Вывод по разделу
- •3 Оптимизация зрительных условий труда пользователя пэвм
- •3.1 Условия работы пользователя пэвм
- •3.2 Требования к визуальным параметрам изображения
- •3.3 Требования к освещению помещений и рабочих мест с вдт и пэвм
- •Заключение
- •Список использованных источников
- •Листинг программы Приложение а
Листинг программы Приложение а
(обязательное).
GraphUnfolding.cs
namespace GraphUnfoldingMachine
{
//cостояние узла
// -1 - неизвестное состояние
// 0 - любое
public enum NodeState : byte
{
Max = 255, Min = 0, Ignored = 0, Unknown = 254,
A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = 7, H = 8, I = 9,
J = 10, K = 11, L = 12, M = 13, N = 14, O = 15, P = 16, Q = 17, R = 18, S = 19,
T = 20, U = 21, V = 22, W = 23, X = 24, Y = 25, Z = 26, s27 = 27, s28 = 28, s29 = 29,
s30 = 30, s31 = 31, s32 = 32, s33 = 33, s34 = 34, s35 = 35, s36 = 36, s37 = 37, s38 = 38, s39 = 39,
s40 = 40, s41 = 41, s42 = 42, s43 = 43, s44 = 44, s45 = 45, s46 = 46, s47 = 47, s48 = 48, s49 = 49,
s50 = 50, s51 = 51, s52 = 52, s53 = 53, s54 = 54, s55 = 55, s56 = 56, s57 = 57, s58 = 58, s59 = 59,
s60 = 60, s61 = 61, s62 = 62, s63 = 63, s64 = 64, s65 = 65, s66 = 66, s67 = 67, s68 = 68, s69 = 69,
s70 = 70, s71 = 71, s72 = 72, s73 = 73, s74 = 74, s75 = 75, s76 = 76, s77 = 77, s78 = 78, s79 = 79,
s80 = 80, s81 = 81, s82 = 82, s83 = 83, s84 = 84, s85 = 85, s86 = 86, s87 = 87, s88 = 88, s89 = 89,
s90 = 90, s91 = 91, s92 = 92, s93 = 93, s94 = 94, s95 = 95, s96 = 96, s97 = 97, s98 = 98, s99 = 99,
s100 = 100, s101 = 101, s102 = 102, s103 = 103, s104 = 104, s105 = 105, s106 = 106, s107 = 107, s108 = 108, s109 = 109,
s110 = 110, s111 = 111, s112 = 112, s113 = 113, s114 = 114, s115 = 115, s116 = 116, s117 = 117, s118 = 118, s119 = 119,
s120 = 120, s121 = 121, s122 = 122, s123 = 123, s124 = 124, s125 = 125, s126 = 126, s127 = 127, s128 = 128, s129 = 129,
s130 = 130, s131 = 131, s132 = 132, s133 = 133, s134 = 134, s135 = 135, s136 = 136, s137 = 137, s138 = 138, s139 = 139,
s140 = 140, s141 = 141, s142 = 142, s143 = 143, s144 = 144, s145 = 145, s146 = 146, s147 = 147, s148 = 148, s149 = 149,
s150 = 150, s151 = 151, s152 = 152, s153 = 153, s154 = 154, s155 = 155, s156 = 156, s157 = 157, s158 = 158, s159 = 159,
s160 = 160, s161 = 161, s162 = 162, s163 = 163, s164 = 164, s165 = 165, s166 = 166, s167 = 167, s168 = 168, s169 = 169,
s170 = 170, s171 = 171, s172 = 172, s173 = 173, s174 = 174, s175 = 175, s176 = 176, s177 = 177, s178 = 178, s179 = 179,
s180 = 180, s181 = 181, s182 = 182, s183 = 183, s184 = 184, s185 = 185, s186 = 186, s187 = 187, s188 = 188, s189 = 189,
s190 = 190, s191 = 191, s192 = 192, s193 = 193, s194 = 194, s195 = 195, s196 = 196, s197 = 197, s198 = 198, s199 = 199,
s200 = 200, s201 = 201, s202 = 202, s203 = 203, s204 = 204, s205 = 205, s206 = 206, s207 = 207, s208 = 208, s209 = 209,
s210 = 210, s211 = 211, s212 = 212, s213 = 213, s214 = 214, s215 = 215, s216 = 216, s217 = 217, s218 = 218, s219 = 219,
s220 = 220, s221 = 221, s222 = 222, s223 = 223, s224 = 224, s225 = 225, s226 = 226, s227 = 227, s228 = 228, s229 = 229,
s230 = 230, s231 = 231, s232 = 232, s233 = 233, s234 = 234, s235 = 235, s236 = 236, s237 = 237, s238 = 238, s239 = 239,
s240 = 240, s241 = 241, s242 = 242, s243 = 243, s244 = 244, s245 = 245, s246 = 246, s247 = 247, s248 = 248, s249 = 249,
s250 = 250, s251 = 251, s252 = 252, s253 = 253
};
//Вспомогательный класс для перечисления NodeState
public static class NodeStateHelper
{
public static string ToString(NodeState value)
{
switch ((long)value)
{
case 0: return "";
case -1: return "-";
default: return ((long)value).ToString();
}
}
//цвет вершин
public static Color GetVertexRenderColor(NodeState state)
{
Color col = Colors.Lime;
switch ((byte)state % 16)
{
case 1:
col = Colors.Pink;
break;
case 2:
col = Colors.Red;
break;
case 3:
col = Colors.OrangeRed;
break;
case 4:
col = Colors.Orange;
break;
case 5:
col = Colors.LightYellow;
break;
case 6:
col = Colors.Yellow;
break;
case 7:
col = Colors.LightGreen;
break;
case 8:
col = Colors.Green;
break;
case 9:
col = Colors.LightSeaGreen;
break;
case 10:
col = Colors.SeaGreen;
break;
case 11:
col = Colors.LightBlue;
break;
case 12:
col = Colors.Blue;
break;
case 13:
col = Colors.Violet;
break;
case 14:
col = Colors.LightCyan;
break;
case 15:
col = Colors.White;
break;
case 0:
col = Colors.LightGray;
break;
case -1:
col = Colors.LightYellow;
break;
default:
col = Colors.Gray;
break;
}
return col;
}
}
//условие выполнения операции - для таблицы переходов
public class OperationCondition
{
NodeState currentState;
//текущее состояние
public NodeState CurrentState { get { return currentState; } set { currentState = value; } }
NodeState _priorState;
//предыдущие состояние
public NodeState PriorState { get { return _priorState; } set { _priorState = value; } }
int allConnectionsCount_GE;
// количество связей больше чем (значение)
public int AllConnectionsCount_GE { get { return allConnectionsCount_GE; } set { allConnectionsCount_GE = value; } }
int allConnectionsCount_LE;
//количество связей меньше чем (значение)
public int AllConnectionsCount_LE { get { return allConnectionsCount_LE; } set { allConnectionsCount_LE = value; } }
int parentsCount_GE;
// количество предков больше чем (значение)
public int ParentsCount_GE { get { return parentsCount_GE; } set { parentsCount_GE = value; } }
int parentsCount_LE;
//количество предков меньше чем (значение)
public int ParentsCount_LE { get { return parentsCount_LE; } set { parentsCount_LE = value; } }
public OperationCondition()
{
currentState = 0;
_priorState = (NodeState)1;
allConnectionsCount_GE = -1;
allConnectionsCount_LE = -1;
parentsCount_GE = -1;
parentsCount_LE = -1;
}
}
//Тип операции
public enum OperationKindEnum
{
//перейти в состояние
TurnToState = 0x0,
//соедениться c ближайшим (не соединённым)
TryToConnectWithNearest = 0x1,
//родить новый узел, связынный
GiveBirthConnected = 0x2,
//разъедениться
DisconectFrom = 0x3,
//умереть (удалитьcя, самоустраниться )
Die = 0x4,
// попытаться соедениться (с)
TryToConnectWith = 0x5,
//родить новый узел
GiveBirth = 0x6,
}
//тип операции
public static class OperationKindHelper
{
static public string ToString(OperationKindEnum _value)
{
switch (_value)
{
case OperationKindEnum.TurnToState:
return "Turn To State";
case OperationKindEnum.TryToConnectWith:
return "Try To Connect With";
case OperationKindEnum.TryToConnectWithNearest:
return "Try To Connect With nearest";
case OperationKindEnum.GiveBirth:
return "Give Birth";
case OperationKindEnum.GiveBirthConnected:
return "Give Birth (Connected)";
case OperationKindEnum.Die:
return "Die";
case OperationKindEnum.DisconectFrom:
return "Disconect From";
default:
return _value.ToString();
}
}
//операции требуется операнд
static public bool IsNeedOperand(OperationKindEnum _value)
{
switch (_value)
{
case OperationKindEnum.TurnToState:
return true;
case OperationKindEnum.TryToConnectWith:
return true;
case OperationKindEnum.TryToConnectWithNearest:
return true;
case OperationKindEnum.GiveBirth:
return false;
case OperationKindEnum.GiveBirthConnected:
return false;
case OperationKindEnum.Die:
return false;
case OperationKindEnum.DisconectFrom:
return false;
default:
return false;
}
}
}
//операция
public class Operation
{
OperationKindEnum _kind;
//тип операции, обязательное значение
public OperationKindEnum Kind { get { return _kind; } set { _kind = value; } }
NodeState _operandNodeState;
//параметр операции (пока только один - состояние узла.)
public NodeState OperandNodeState { get { return _operandNodeState; } set { _operandNodeState = value; } }
public Operation()
{
_kind = OperationKindEnum.TurnToState;
_operandNodeState = NodeState.Ignored;
}
public Operation(OperationKindEnum kind, NodeState operandNodeState)
{
_kind = kind;
_operandNodeState = operandNodeState;
}
}
//элемент таблицы правил переходов из одного состояния узла в другое
public class ChangeTableItem
{
// устанавливается в true, если правило перехода сработало при очередной итерации развёртывания графа
public bool IsActive = false;
public bool WasActive = false;
public bool IsEnabled = true;
//Индекс последней активации
public int LastActivationInterationIndex = -1;
OperationCondition _condition;
// условие выполнения операции
public OperationCondition Condition { get { return _condition; } set { _condition = value; } }
Operation _operation;
//операция
public Operation Operation { get { return _operation; } set { _operation = value; } }
public ChangeTableItem()
{
_condition = null;
_operation = null;
}
public ChangeTableItem(OperationCondition condition, Operation operation)
{
_condition = condition;
_operation = operation;
}
public override string ToString()
{
string s;
s = String.Format("Current: {0}; Prior: {1}; → Operation: {2}; Operand: {3}",
Condition.CurrentState.ToString(),
Condition.PriorState.ToString(),
Operation.Kind.ToString(),
Operation.OperandNodeState.ToString());
return s;
}
}
//таблица переходов сетевого конечного автомата.
public class ChangeTable : System.Collections.Generic.List<ChangeTableItem>
{
//Добавление нового элемента (правила перехода) в таблицу переходов
public void Add(OperationCondition condition, Operation operation)
{
ChangeTableItem cti = new ChangeTableItem(condition, operation);
Add(cti);
}
//добавление нового элемента (правила перехода)
public void Add(NodeState currentState, NodeState priorState,
int allConnectionsCountGE, int allConncetionsCountLE,
int parentsCountGE, int parentsCountLE,
OperationKindEnum operationKind,
NodeState operand)
{
OperationCondition cond = new OperationCondition();
cond.CurrentState = currentState;
cond.PriorState = priorState;
cond.AllConnectionsCount_GE = allConnectionsCountGE;
cond.AllConnectionsCount_LE = allConncetionsCountLE;
cond.ParentsCount_GE = parentsCountGE;
cond.ParentsCount_LE = parentsCountLE;
Operation oper = new Operation(operationKind, operand);
Add(cond, oper);
isPrepared = false;
}
//Поиск элемента таблицы (условие -> операция)
public ChangeTableItem Find(GUMNode node, CountComparerType countComparerType, TranscriptionWay transcriptionWay)
{
int foundIndex;
ChangeTableItem result = Find(node, node.State, node.PriorState, node.ConnectionsCount, node.ParentsCount, node.changeTableReadingIndex, countComparerType, transcriptionWay, out foundIndex);
if (foundIndex == this.Count - 1)
{
node.changeTableReadingIndex = 0;
}
else
{
node.changeTableReadingIndex = foundIndex + 1;
}
return result;
}
//Поиск элемента таблицы правил (условие --> операция)
public ChangeTableItem Find(GUMNode node, NodeState nodeState, NodeState priorNodeState, int connectionsCount, int parentsCount, int changeTableReadingIndex, CountComparerType countComparerType, TranscriptionWay transcriptionWay, out int foundIndex)
{
if (transcriptionWay == TranscriptionWay.Resettable)
{
foundIndex = 0;
if ((isPrepared) && (nodeState != NodeState.Min))
{
#region
int chi_index;
chi_index = myHashTable.BinarySearch(new ConditionHashtableItem(nodeState));
if (chi_index < 0)
{
return null;
}
result = (result && tableItem.IsEnabled);
result = (result && (condition.CurrentState == nodeState));
result = (result && ((condition.PriorState == priorNodeState) || (condition.PriorState == NodeState.Ignored)));
result = (result && ((condition.AllConnectionsCount_GE <= connectionsCount) || (condition.AllConnectionsCount_GE == -1)));
result = (result && ((condition.AllConnectionsCount_LE >= connectionsCount) || (condition.AllConnectionsCount_LE == -1)));
result = (result && ((condition.ParentsCount_GE <= parentsCount) || (condition.ParentsCount_GE == -1)));
result = (result && ((condition.ParentsCount_LE >= parentsCount) || (condition.ParentsCount_LE == -1)));
if (result)
{
return tableItem;
}
}
return null;
}
}
else
{
foreach (ChangeTableItem tableItem in this)
{
bool result = true;
OperationCondition condition = tableItem.Condition;
result = (result && tableItem.IsEnabled);
result = (result && (condition.CurrentState == nodeState));
result = (result && ((condition.PriorState == priorNodeState) || (condition.PriorState == NodeState.Ignored)));
result = (result && ((condition.AllConnectionsCount_GE <= connectionsCount) || (condition.AllConnectionsCount_GE == -1)));
result = (result && ((condition.AllConnectionsCount_LE >= connectionsCount) || (condition.AllConnectionsCount_LE == -1)));
result = (result && ((condition.ParentsCount_GE <= parentsCount) || (condition.ParentsCount_GE == -1)));
result = (result && ((condition.ParentsCount_LE >= parentsCount) || (condition.ParentsCount_LE == -1)));
if (result)
{
return tableItem;
}
}
return null;
}
}
else
{
foundIndex = 0;
bool isFound = false;
for (int i = changeTableReadingIndex; i < this.Count; i++)
{
ChangeTableItem tableItem = this[i];
OperationCondition condition = tableItem.Condition;
bool result = true;
result = (result && tableItem.IsEnabled);
result = (result && (condition.CurrentState == nodeState));
result = (result && ((condition.PriorState == priorNodeState) || (condition.PriorState == NodeState.Ignored)));
result = (result && ((condition.AllConnectionsCount_GE <= connectionsCount) || (condition.AllConnectionsCount_GE == -1)));
result = (result && ((condition.AllConnectionsCount_LE >= connectionsCount) || (condition.AllConnectionsCount_LE == -1)));
result = (result && ((condition.ParentsCount_GE <= parentsCount) || (condition.ParentsCount_GE == -1)));
result = (result && ((condition.ParentsCount_LE >= parentsCount) || (condition.ParentsCount_LE == -1)));
if (result)
{
foundIndex = i;
isFound = true;
break;
}
}
if (isFound)
{
return this[foundIndex];
}
else
{
foundIndex = this.Count - 1;
return null;
}
}
}
internal void Reset()
{
foreach (var tableItem in this)
{
tableItem.IsActive = false;
}
}
}
Population.cs
public class GAParametres
{
public GAParametres()
{
}
public GAParametres(double crossOverRate, double mutationRate, double randomSelectionPortion, bool isGenomeLengthPenalty)
{
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
this.randomSelectionPortion = randomSelectionPortion;
}
// параметры популяции
private double crossOverRate = 0.95;
public double CrossOverRate { get { return crossOverRate; } set { crossOverRate = value; } }
private double mutationRate = 0.95;
public double MutationRate { get { return mutationRate; } set { mutationRate = value; } }
private double singleActiveGenMutaionFactor = 0.05;
public double SingleActiveGenMutaionFactor { get { return singleActiveGenMutaionFactor; } set { singleActiveGenMutaionFactor = value; } }
private MutationKind singleActiveGenMutaionKind = MutationKind.Byte;
public MutationKind SingleActiveGenMutaionKind { get { return singleActiveGenMutaionKind; } set { singleActiveGenMutaionKind = value; } }
private double singlePassiveGenMutaionFactor = 0.6;
public double SinglePassiveGenMutaionFactor { get { return singlePassiveGenMutaionFactor; } set { singlePassiveGenMutaionFactor = value; } }
private MutationKind singlePassiveGenMutaionKind = MutationKind.AllBytes;
public MutationKind SinglePassiveGenMutaionKind { get { return singlePassiveGenMutaionKind; } set { singlePassiveGenMutaionKind = value; } }
private double randomSelectionPortion = 0.0;
public double RandomSelectionPortion { get { return randomSelectionPortion; } set { randomSelectionPortion = value; } }
private bool isGenomeLengthPenalty = false;
public bool IsGenomeLengthPenalty { get { return isGenomeLengthPenalty; } set { isGenomeLengthPenalty = value; } }
}
//популяцих хромосом
public class Population
{
private IFitnessFunction fitnessFunction; //фитнесс-функция
private ISelectionMethod selectionMethod; //метод селекции
private List<IChromosome> population = new List<IChromosome>(); //список хромосом
public List<IChromosome> Chromosomes { get { return population; } }
private int size; //размер популяции
//параметры генетического алгоритма
private GAParametres parametres = new GAParametres();
private double fitnessMax = 0;
private double fitnessSum = 0;
private double fitnessAvg = 0;
private int ageMax = 0;
private int ageSum = 0;
private double ageAvg = 0;
private int chromosomeLenghMax = 0;
private int chromosomeLenghSum = 0;
private double chromosomeLenghAvg = 0;
private int activeGensCountMax = 0;
private int activeGensCountSum = 0;
private int activeGensCountAvg = 0;
private IChromosome bestChromosome = null;
private IChromosome ancestor;
//фитнесс-функция
public double FitnessMax
{
get { return fitnessMax; }
}
public double FitnessSum
{
get { return fitnessSum; }
}
//среднее значение фитнесс-функции
public double FitnessAvg
{
get { return fitnessAvg; }
}
//возраст
public int AgeMax
{
get { return ageMax; }
}
public double AgeAvg
{
get { return ageAvg; }
}
public int ChromosomeLengthMax
{
get { return chromosomeLenghMax; }
}
public double ChromosomeLenghAvg
{
get { return chromosomeLenghAvg; }
}
public int ActiveGensCountMax
{
get { return activeGensCountMax; }
}
public double ActiveGensCountAvg
{
get { return activeGensCountAvg; }
}
public IChromosome BestChromosome
{
get { return bestChromosome; }
}
public int Size
{
get { return size; }
}
public IChromosome this[int index]
{
get { return (IChromosome)population[index]; }
}
// создание популяции
public Population(int size,
List<IChromosome> initialPopulation,
IChromosome ancestor,
IFitnessFunction fitnessFunction,
ISelectionMethod selectionMethod
)
{
this.fitnessFunction = fitnessFunction;
this.selectionMethod = selectionMethod;
this.size = size;
this.ancestor = ancestor;
population = initialPopulation;
int currentLength = population.Count;
if (currentLength > size)
{
population.RemoveRange(size - 1, currentLength - size);
};
if (currentLength < size)
{
ancestor.Evaluate(fitnessFunction);
population.Add(ancestor);
// добавление еще хромосом
for (int i = currentLength + 1; i < size; i++)
{
IChromosome c = ancestor.CreateOffspring();
// вычисление фитнесс-функции
c.Evaluate(fitnessFunction);
// добавить популяцию
population.Add(c);
}
}
}
public Population(int size,
List<IChromosome> initialPopulation,
IChromosome ancestor,
IFitnessFunction fitnessFunction,
ISelectionMethod selectionMethod,
GAParametres parametres)
: this(size, initialPopulation, ancestor, fitnessFunction, selectionMethod)
{
this.parametres = parametres;
//устанавливаем параметры мутации для уже существующих
foreach (IChromosome c in population)
{
c.SetGAParametres(parametres);
}
}
public void Regenerate()
{
bestChromosome = null;
// очистить
population.Clear();
// добавить популяции
for (int i = 0; i < size; i++)
{
IChromosome c = ancestor.CreateOffspring();
c.Evaluate(fitnessFunction);
population.Add(c);
}
}
//кроссовер в популяции
public virtual void Crossover()
{
for (int i = 1; i < size; i += 2)
{
if (RandomGen3.NextDouble() <= parametres.CrossOverRate)
{
IChromosome c1 = ((IChromosome)population[i - 1]).Born();
IChromosome c2 = ((IChromosome)population[i]).Born();
c1.Crossover(c2);
population.Add(c1);
population.Add(c2);
}
}
}
//мутация
public virtual void Mutate()
{
for (int i = 0; i < size; i++)
{
if (RandomGen3.NextDouble() <= parametres.MutationRate)
{
// копирование хромосомы
IChromosome c = ((IChromosome)population[i]).Clone();
c.Mutate();
population.Add(c);
}
}
}
public virtual void InvalidateFitnessFunction()
{
for (int i = 0; i < size; i++)
{
IChromosome c = ((IChromosome)population[i]).Clone();
c.InvalidateFitnessValue();
}
}
//селекция
public virtual void Selection()
{
foreach (IChromosome c in population)
{
c.Evaluate(fitnessFunction);
}
//число хромосом в новой популяции
int randomAmount = (int)(parametres.RandomSelectionPortion * size);
// селекция
selectionMethod.ApplySelection(population, size - randomAmount);
// добавляем хромосомы
if (randomAmount > 0)
{
IChromosome ancestor = (IChromosome)population[0];
for (int i = 0; i < randomAmount; i++)
{
IChromosome c = ancestor.CreateOffspring();
c.Evaluate(fitnessFunction);
population.Add(c);
}
}
ageMax = 0;
ageSum = 0;
chromosomeLenghSum = 0;
chromosomeLenghMax = 0;
// найти лучшую хромосому
fitnessMax = double.MinValue;
fitnessSum = 0;
bestChromosome = null;
foreach (IChromosome c in population)
{
double fitness = c.Fitness;
fitnessSum += fitness;
if (fitness > fitnessMax)
{
fitnessMax = fitness;
bestChromosome = c;
}
int age = c.Age();
ageSum += age;
if (age > ageMax) { ageMax = age; }
}
fitnessAvg = fitnessSum / size;
ageAvg = (double)ageSum / size;
}
//запуск одной эпохи в популяции - мутация, кроссовер, селекция
public void RunEpoch()
{
InvalidateFitnessFunction();
try
{
Mutate();
}
catch (Exception e)
{
throw new Exception("Error in RunEpoch.Mutate " + e.Message, e);
};
try { Crossover(); }
catch (Exception e)
{
throw new Exception("Error in RunEpoch.Crossover " + e.Message, e);
};
try { Selection(); }
catch (Exception e)
{
throw new Exception("Error in RunEpoch.Selection " + e.Message, e);
};
}
public void Trace()
{
System.Diagnostics.Debug.WriteLine("Max = " + fitnessMax);
System.Diagnostics.Debug.WriteLine("Sum = " + fitnessSum);
System.Diagnostics.Debug.WriteLine("Avg = " + fitnessAvg);
System.Diagnostics.Debug.WriteLine("--------------------------");
foreach (IChromosome c in population)
{
System.Diagnostics.Debug.WriteLine("genotype = " + c.ToString() +
", phenotype = " + fitnessFunction.Translate(c) +
" , fitness = " + c.Fitness);
}
System.Diagnostics.Debug.WriteLine("==========================");
}
}
}
Genetic.cs
public class MyChromosome : IChromosome
{
// "Возраст" хромосомы
int age = 0;
double singleActiveGenMutaionFactor = 0.1;
MutationKind singleActiveGenMutaionKind = MutationKind.Byte;
double singlePassiveGenMutaionFactor = 0.5;
MutationKind singlePassiveGenMutaionKind = MutationKind.Byte;
protected double fitness = 0;
int maxLength;
MyGen[] genes; //хромосома - это массив генов, т.е. массив правил
protected bool isNeedToUpdateFitnessValue = true;
public string activeGensScheme;
public int activeGensCount;
public void InvalidateFitnessValue()
{
isNeedToUpdateFitnessValue = true;
}
//значение фитнес-функции
double IChromosome.Fitness
{
get { return fitness; }
}
//конструктор
public MyChromosome(
int length, //длина
int maxLength, //максимальная длина
double singleActiveGenMutaionFactor,
MutationKind singleActiveGenMutaionKind,
double singlePassiveGenMutaionFactor,
MutationKind singlePassiveGenMutaionKind
)
{
this.singleActiveGenMutaionFactor = singleActiveGenMutaionFactor;
this.singleActiveGenMutaionKind = singleActiveGenMutaionKind;
this.singlePassiveGenMutaionFactor = singlePassiveGenMutaionFactor;
this.singlePassiveGenMutaionKind = singlePassiveGenMutaionKind;
this.maxLength = maxLength;
//создаем массив генов
genes = new MyGen[length];
for (int i = 0; i < length; i++)
{
genes[i] = new MyGen();
}
//генерируем хромосому
Generate();
}
//копирование хромосомы
public MyChromosome(MyChromosome source)
{
genes = new MyGen[source.genes.Length];
fitness = source.fitness;
//копируем гены
for (int i = 0; i < genes.Length; i++)
{
genes[i] = new MyGen(source.genes[i].GetValue());
genes[i].WasActive = source.genes[i].WasActive;
}
// копируем поля
maxLength = source.maxLength;
age = source.age;
singleActiveGenMutaionFactor = source.singleActiveGenMutaionFactor;
singleActiveGenMutaionKind = source.singleActiveGenMutaionKind;
singlePassiveGenMutaionFactor = source.singlePassiveGenMutaionFactor;
singlePassiveGenMutaionKind = source.singlePassiveGenMutaionKind;
}
//установка параметров ГА
public void SetGAParametres(GAParametres parametres)
{
singleActiveGenMutaionFactor = parametres.SingleActiveGenMutaionFactor;
singleActiveGenMutaionKind = parametres.SingleActiveGenMutaionKind;
singlePassiveGenMutaionFactor = parametres.SinglePassiveGenMutaionFactor;
singlePassiveGenMutaionKind = parametres.SinglePassiveGenMutaionKind;
}
//конструктор хромосомы через таблицу
public MyChromosome(ChangeTable changeTable)
{
this.maxLength = changeTable.Count * 2;
SetChangeTable(changeTable);
}
public int Age()
{
return age;
}
IChromosome IChromosome.Clone()
{
return new MyChromosome(this);
}
IChromosome IChromosome.Born()
{
MyChromosome result = new MyChromosome(this);
this.age++;
result.age = 0;
return result;
}
IChromosome IChromosome.CreateOffspring()
{
MyChromosome result = new MyChromosome(this);
if (RandomGen3.NextDouble() < 0.9)
{
(result as IChromosome).Mutate();
}
return result;
}
//кроссинговер
void IChromosome.Crossover(IChromosome pair)
{
MyGen[] pairGens = ((MyChromosome)pair).genes;
int L1 = this.genes.Length;
int L2 = pairGens.Length;
int crossOverPoint1 = RandomGen3.Next(L1 - 1) + 1;
int crossOverPoint2;
bool Symmetric = false;
if (Symmetric)
{
crossOverPoint2 = crossOverPoint1;
}
else
{
crossOverPoint2 = RandomGen3.Next(L2 - 1) + 1;
}
int newL1 = Math.Min(maxLength, crossOverPoint1 + L2 - crossOverPoint2);
int newL2 = Math.Min(maxLength, crossOverPoint2 + L1 - crossOverPoint1);
MyGen[] genes1 = new MyGen[newL1];
MyGen[] genes2 = new MyGen[newL2];
Array.Copy(this.genes, 0, genes1, 0, crossOverPoint1);
Array.Copy(pairGens, crossOverPoint2, genes1, crossOverPoint1, newL1 - crossOverPoint1);
Array.Copy(pairGens, 0, genes2, 0, crossOverPoint2);
Array.Copy(this.genes, crossOverPoint1, genes2, crossOverPoint2, newL2 - crossOverPoint2);
this.genes = genes1;
((MyChromosome)pair).genes = genes2;
this.isNeedToUpdateFitnessValue = true;
((MyChromosome)pair).isNeedToUpdateFitnessValue = true;
}
//эволюция
void IChromosome.Evaluate(IFitnessFunction function)
{
fitness = function.Evaluate(this);
isNeedToUpdateFitnessValue = false;
}
//генерация хромосомы
public virtual void Generate()
{
foreach (MyGen gen in genes)
{
GenerateGen(gen);
}
isNeedToUpdateFitnessValue = true;
}
//генерация гена
private static void GenerateGen(MyGen gen)
{
byte[] bytes = new byte[8];
RandomGen3.NextBytes(bytes);
ulong lng = BitConverter.ToUInt64(bytes, 0);
gen.SetValue(lng);
}
//мутация гена
private static void MutateGen(MyGen gen, MutationKind mutationKind)
{
byte[] bytes = new byte[8];
RandomGen3.NextBytes(bytes);
ulong lng = BitConverter.ToUInt64(bytes, 0);
gen.SetValue(lng);
}
//мутация хромосомы
void IChromosome.Mutate()
{
if ((singleActiveGenMutaionFactor == singlePassiveGenMutaionFactor) && (singleActiveGenMutaionKind == singlePassiveGenMutaionKind))
{
// Если без разницы активность генов:
for (int i = 0; i < genes.Length; i++)
{
if (RandomGen3.NextDouble() < singleActiveGenMutaionFactor)
{
MyChromosome.MutateGen(genes[i], singleActiveGenMutaionKind);
}
}
}
else
{
// Если тип и вероятность мутации зависят от активности генов:
int activeGensCount = 0;
for (int i = 0; i < genes.Length; i++)
{
if (genes[i].WasActive)
{
activeGensCount++;
if (RandomGen3.NextDouble() < singleActiveGenMutaionFactor)
{
MyChromosome.MutateGen(genes[i], singleActiveGenMutaionKind);
}
if (RandomGen3.NextDouble() < singleActiveGenMutaionFactor*0.2)
{
MyChromosome.MutateGen(genes[i], MutationKind.Shift);
}
}
else
{
if (RandomGen3.NextDouble() < singlePassiveGenMutaionFactor)
{
MyChromosome.MutateGen(genes[i], singlePassiveGenMutaionKind);
}
if (RandomGen3.NextDouble() < singlePassiveGenMutaionFactor * 0.2)
{
MyChromosome.MutateGen(genes[i], MutationKind.Shift);
}
}
}
// cлучайная вставка активного гена
if (RandomGen3.NextDouble() < 0.4)
{
if ((genes.Length < maxLength) && (activeGensCount > 1))
{
MyGen[] genes1 = new MyGen[genes.Length + 1];
// находим случайный индекс активного гена:
int rndActiveNumberForInsertion = RandomGen3.Next(1, activeGensCount);
int activeGenIndex = -1;
int activeGenPassedCount = 0;
while (activeGenPassedCount < rndActiveNumberForInsertion)
{
activeGenIndex++;
if (genes[activeGenIndex].WasActive) { activeGenPassedCount++; };
}
Array.Copy(genes, 0, genes1, 0, activeGenIndex + 1);
Array.Copy(genes, activeGenIndex, genes1, activeGenIndex + 1, 1);
if (genes.Length - activeGenIndex - 1 > 0)
{
Array.Copy(genes, activeGenIndex + 1, genes1, activeGenIndex + 2, genes.Length - activeGenIndex - 1);
}
}
};
if (RandomGen3.NextDouble() < 0.6)
{
// удаляем первый попавшийся неактивный ген, если есть
if ((activeGensCount < genes.Length) && (genes.Length >= 100))
{
int rndInActiveNumberForInsertion = RandomGen3.Next(1, genes.Length - activeGensCount);
int inactiveGenIndex = -1;
int inactiveGenPassedCount = 0;
while (inactiveGenPassedCount < rndInActiveNumberForInsertion)
{
inactiveGenIndex++;
if (!genes[inactiveGenIndex].WasActive) { inactiveGenPassedCount++; };
}
if ((inactiveGenIndex < genes.Length) && (inactiveGenIndex > 0))
{
MyGen[] genes1 = new MyGen[genes.Length - 1];
Array.Copy(genes, 0, genes1, 0, inactiveGenIndex);
Array.Copy(genes, inactiveGenIndex + 1, genes1, inactiveGenIndex, genes.Length - 1 - inactiveGenIndex);
this.genes = genes1;
}
}
};
}
isNeedToUpdateFitnessValue = true;
}
public void SetActiveGensMask(System.Collections.BitArray activeGensBitArray)
{
for (int i = 0; i < genes.Count(); i++)
{
genes[i].WasActive = activeGensBitArray[i];
}
}
int IComparable.CompareTo(object obj)
{
double f = ((MyChromosome)obj).fitness;
int result;
if (fitness == f)
{
MyChromosome other = (MyChromosome)obj;
result = (this.age == other.age) ? 0 : (this.age > other.age) ? 1 : -1;
}
else
{
result = (fitness < f) ? 1 : -1; // в порядке убывания fitness
}
return result;
}
public ChangeTable GetChangeTable()
{
ChangeTable result = new ChangeTable();
foreach (MyGen gen in genes)
{
result.Add(gen.ToChangeTableItem());
}
return result;
}
public void SetChangeTable(ChangeTable changeTable)
{
ChangeTable result = new ChangeTable();
foreach (MyGen gen in genes)
{
result.Add(gen.ToChangeTableItem());
}
genes = new MyGen[changeTable.Count];
for (int i = 0; i < changeTable.Count; i++)
{
genes[i] = new MyGen();
genes[i].Status = (byte)changeTable[i].Condition.CurrentState;
genes[i].PriorStatus = (byte)changeTable[i].Condition.PriorState;
genes[i].Connections_GE = (byte)changeTable[i].Condition.AllConnectionsCount_GE;
genes[i].Connections_LE = (byte)changeTable[i].Condition.AllConnectionsCount_LE;
genes[i].Parents_GE = (byte)changeTable[i].Condition.ParentsCount_GE;
genes[i].Parents_LE = (byte)changeTable[i].Condition.ParentsCount_LE;
genes[i].OperationType = (byte)changeTable[i].Operation.Kind;
genes[i].OperandStatus = (byte)changeTable[i].Operation.OperandNodeState;
}
}
public int Length { get { return genes.Length; } }
}
//фитнесс-функция
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);
// Надвавка за краткость хромосомы:
if (isGenomeLengthPenalty)
{
result = result + 1.0 / (((chromosome as MyChromosome).Length));
}
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;
GraphUnfoldingMachine graphUnfoldingMachine = 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;
}
//Расчёт фитнесс функций фенотипа (выращеного графа)
//Должна возвращать результат в диапазоне от 1.0 до бесконечности
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();
}
}
}
public class BySamplePlanarGraphFitnessFunction : PlanarGraphFitnessFunction
{
Dictionary<int, int> fasetsDistributionByLength;
Dictionary<int, int> verticesDistributionByDegree;
public BySamplePlanarGraphFitnessFunction(Dictionary<int, int> fasetsDistributionByLength,
Dictionary<int, int> verticesDistributionByDegree,
int maxGUCAIterationCount,
int maxVertexCount,
bool isGenomeLengthPenalty,
bool isNotPlannedPenalty,
NumericalMethodParametres unfoldingParametres,
TranscriptionWay transcriptionWay)
: base(maxGUCAIterationCount, maxVertexCount, isGenomeLengthPenalty, isNotPlannedPenalty, unfoldingParametres, transcriptionWay)
{
this.fasetsDistributionByLength = fasetsDistributionByLength;
this.verticesDistributionByDegree = verticesDistributionByDegree;
}
//Возвращает распределение узлов по их степени
private Dictionary<int, int> GetVerticiesDistributionByDegree(Physical2DGraph.Physical2DGraph graph)
{
var vertParts = from x in graph.Vertices
group x by graph.AdjacentEdges(x).Count() into part
orderby part.Key
select new
{
Key = part.Key,
Count = part.Count()
};
Dictionary<int, int> result = new Dictionary<int, int>();
foreach (var part in vertParts)
{
result.Add(part.Key, part.Count);
}
return result;
}
// возвращает распределение граней по их степени
private Dictionary<int, int> GetFasetsDistributionByLength(List<Cycle<Physical2DGraphVertex>> fasets)
{
var fasetParts = from x in fasets
group x by x.Count
into part
orderby part.Key
select new
{
Key = part.Key,
Count = part.Count()
};
Dictionary<int, int> result = new Dictionary<int, int>();
foreach (var part in fasetParts)
{
result.Add(part.Key, part.Count);
}
return result;
}
public override double Evaluate(Physical2DGraph.Physical2DGraph graph)
{
if (isNotPlannedPenalty)
{
graph.ProcessUnfoldingModel(this.unfoldingParametres, new Point(0, 0)); // затратная операция!
if (!graph.IsPlanned()) { return 1.2; }
}
if (!graph.IsPlanarized)
{
graph.Planarize();
}
// 1. Находим распределение узлов по степеням и граней по длине получившегося графа
Dictionary<int, int> curFasetsDistributionByLength = graph.GetFasetsDistributionByLength();
Dictionary<int, int> curVerticesDistributionByDegree = graph.GetVerticiesDistributionByDegree();
// 2.Расчитываем дистанцию между целевым распределением узлов по степеням и распределением получившегося графа
var vertUnion = (from x in curVerticesDistributionByDegree
select new
{
Key = x.Key,
Value = -x.Value
}).Union
(from y in this.verticesDistributionByDegree
select new
{
Key = y.Key,
Value = y.Value
}
);
var vertGroupedSum =
from x in vertUnion
group x by x.Key into g
select new { g.Key, KeySum = g.Sum(x => x.Value) };
int vertDistance = vertGroupedSum.Sum(x => Math.Abs(x.KeySum));
// 3.Расчитываем дистанцию между целевым распределением граней по длине и распределением получившегося графа
var fasetsUnion = (from x in curFasetsDistributionByLength
select new
{
Key = x.Key,
Value = -x.Value
}).Union
(from y in fasetsDistributionByLength
select new
{
Key = y.Key,
Value = y.Value
}
);
int fasetDistance =
(from x in fasetsUnion
group x by x.Key into g
select new { g.Key, KeySum = g.Sum(x => x.Value) })
.Sum(x => Math.Abs(x.KeySum));
// 4. чем больше дистанция, тем менее пригоден к жизни получившийся граф:
// 1-ый приоритет: количество граней.
double result = Math.Abs(fasetsDistributionByLength.Sum(x => x.Value) - curFasetsDistributionByLength.Sum(x => x.Value));
return result;
}
}
public class TriangleMeshPlanarGraphFitnessFunction : PlanarGraphFitnessFunction
{
double shellVertexWeight;
public TriangleMeshPlanarGraphFitnessFunction(
int maxGUCAIterationCount,
int maxVertexCount,
bool isGenomeLengthPenalty,
bool isNotPlannedPenalty,
NumericalMethodParametres unfoldingParametres,
TranscriptionWay transcriptionWay,
double shellVertexWeight)
: base(maxGUCAIterationCount, maxVertexCount, isGenomeLengthPenalty, isNotPlannedPenalty, unfoldingParametres, transcriptionWay)
{
this.shellVertexWeight = shellVertexWeight;
}
public override double Evaluate(Physical2DGraph.Physical2DGraph graph)
{
double result;
if (!graph.IsPlanarized)
{
graph.Planarize();
}
List<Cycle<Physical2DGraphVertex>> fasets = graph.Fasets;
if (graph.VertexCount <= 2) { return 1.0; }
if (fasets.Count == 1) { return 1.01; }
// дополнительные ограничения: граф должен двусвязным
if (!graph.IsBeconnected()) { return 1.02; }
// дополнительные ограничения: граф должен быть уложен на плоскости в результате 2D развёртывания
// максимальное колво связей у вершины не должно превышать 5-ти
int MaxVertexDegree = graph.Vertices.Max(x => graph.AdjacentDegree(x));
if (MaxVertexDegree > 6) { return 1.03; }
if (isNotPlannedPenalty)
{
graph.ProcessUnfoldingModel(this.unfoldingParametres, new Point(0, 0)); // затратная операция!
if (!graph.IsPlanned()) { return 1.06; }
}
double wellConnectedVertexCount = graph.VertexCount;
Cycle<Physical2DGraphVertex> shellFaset = (from f in fasets orderby f.MinCycleLength descending select f).First();
int MaxCycleLength = shellFaset.MinCycleLength;
int perimetr = shellFaset.Count;
double innerVertexCount = graph.VertexCount - perimetr;
result = 1.01 * (double)fasets.Count + 1.1 * innerVertexCount - perimetr + 20;
return result;
}
}
public class QuadricMeshPlanarGraphFitnessFunction : PlanarGraphFitnessFunction
{
double shellVertexWeight;
private double faset3penaltyProbability;
public QuadricMeshPlanarGraphFitnessFunction(
int maxGUCAIterationCount,
int maxVertexCount,
bool isGenomeLengthPenalty,
bool isNotPlannedPenalty,
NumericalMethodParametres unfoldingParametres,
TranscriptionWay transcriptionWay,
double shellVertexWeight,
double faset3penaltyProbability)
: base(maxGUCAIterationCount, maxVertexCount, isGenomeLengthPenalty, isNotPlannedPenalty, unfoldingParametres, transcriptionWay)
{
this.shellVertexWeight = shellVertexWeight;
this.faset3penaltyProbability = faset3penaltyProbability;
}
public override double Evaluate(Physical2DGraph.Physical2DGraph graph)
{
double result;
if (!graph.IsPlanarized)
{
graph.Planarize();
}
List<Cycle<Physical2DGraphVertex>> fasets = graph.Fasets;
int AimVertexDegree = 4;
if (graph.VertexCount <= 2) { return 1.0; }
if (fasets.Count == 1) { return 1.01; }
if (!graph.IsBeconnected()) { return 1.02; }
int MaxVertexDegree = graph.Vertices.Max(x => graph.AdjacentDegree(x));
if (MaxVertexDegree > 6) { return 1.03; }
if (MaxVertexDegree > 5) { return 1.04; }
if (MaxVertexDegree > 4) { return 1.06; }
int MinCycleLength = fasets.Min(x => x.MinCycleLength);
if (faset3penaltyProbability > 0)
{
int Fasets3Count = (from f in fasets where f.MinCycleLength == 3 select f).Count();
if ((Fasets3Count > 0) && (RandomGen3.NextDouble() < faset3penaltyProbability)) { return 1.08; };
}
Cycle<Physical2DGraphVertex> shellFaset = (from f in fasets orderby f.MinCycleLength descending select f).First();
if (isNotPlannedPenalty)
{
graph.ProcessUnfoldingModel(this.unfoldingParametres, new Point(0, 0)); // затратная операция!
if (!graph.IsPlanned()) { return 1.1; }
}
double wellConnectedVertexCount = graph.VertexCount;
int MaxCycleLength = shellFaset.MinCycleLength;
double outerAimVertexCount = (double)shellFaset.Vertices.Take(shellFaset.Count).Where(x => x.ConnectionsCount == AimVertexDegree).Count();
double innerAimVertexCount = (double)graph.Vertices.Where(x => x.ConnectionsCount == AimVertexDegree).Count() - outerAimVertexCount;
if (fasets.Count > 2)
{
int innerNotAimVertexCount = graph.Vertices.Where(x => (x.ConnectionsCount != AimVertexDegree && !shellFaset.Vertices.Contains(x))).Count();
if (innerNotAimVertexCount > 0) return 1.11;
}
double Fasets4Count = (from f in fasets where f.MinCycleLength == 4 select f).Count();
if (MaxCycleLength == 4) { Fasets4Count = Fasets4Count - 1; };
double koef = Fasets4Count <= 4 ? 2.1 : 2;
result = Math.Max(3.98, 2.1 * Fasets4Count + 2 * innerAimVertexCount - wellConnectedVertexCount + 10.0);
return result;
}
}
public class HexMeshPlanarGraphFitnessFunction : PlanarGraphFitnessFunction
{
double shellVertexWeight;
public HexMeshPlanarGraphFitnessFunction(
int maxGUCAIterationCount,
int maxVertexCount,
bool isGenomeLengthPenalty,
bool isNotPlannedPenalty,
NumericalMethodParametres unfoldingParametres,
TranscriptionWay transcriptionWay,
double shellVertexWeight)
: base(maxGUCAIterationCount, maxVertexCount, isGenomeLengthPenalty, isNotPlannedPenalty, unfoldingParametres, transcriptionWay)
{
this.shellVertexWeight = shellVertexWeight;
}
public override double Evaluate(Physical2DGraph.Physical2DGraph graph)
{
double result;
if (!graph.IsPlanarized)
{
graph.Planarize();
}
List<Cycle<Physical2DGraphVertex>> fasets = graph.Fasets;
if (graph.VertexCount <= 2) { return 1.0; }
if (fasets.Count == 1) { return 1.01; }
if (!graph.IsBeconnected())
{
if (RandomGen3.NextDouble() < shellVertexWeight)
{
return 1.02;
}
}
int MaxVertexDegree = graph.Vertices.Max(x => graph.AdjacentDegree(x));
if (MaxVertexDegree > 6) { return 1.03; }
if ((MaxVertexDegree > 5) && (graph.VertexCount > 7)) { return 1.04; }
if ((MaxVertexDegree > 4) && (graph.VertexCount > 7)) { return 1.05; }
double V = graph.VertexCount;
Cycle<Physical2DGraphVertex> shell = (from f in fasets orderby f.MinCycleLength descending select f).First();
int MaxCycleLength = shell.MinCycleLength;
int VinnerNot3 = graph.Vertices.Where(x => (x.ConnectionsCount != 3) && !shell.Vertices.Contains(x)).Count();
if (VinnerNot3 > 0)
{
List<Physical2DGraphVertex> Vinnrt4List = graph.Vertices.Where(x => (x.ConnectionsCount == 4) && !shell.Vertices.Contains(x)).ToList();
if (!(VinnerNot3 == Vinnrt4List.Count))
{
return 1.08;
}
else
{
if (!((Vinnrt4List.Count < 4) && (!Vinnrt4List.Exists(x => x.Fasets.Where(f => f.MinCycleLength == 6).Count() > 2))))
{
return 1.09;
}
}
};
var VOuter4List = graph.Vertices.Where(x => (x.ConnectionsCount == 4) && shell.Vertices.Contains(x));
if (VOuter4List.Any(x => x.Fasets.Where(f => f.MinCycleLength == 6).Count() > 2))
{
return 1.1;
}
if (isNotPlannedPenalty)
{
if (RandomGen3.NextDouble() < shellVertexWeight)
{
graph.ProcessUnfoldingModel(this.unfoldingParametres, new Point(0, 0));
if (!graph.IsPlanned())
{
return 1.06;
}
}
}
double V3inner = graph.Vertices.Where(x => x.ConnectionsCount == 3 && x.Fasets.Where(f => f.MinCycleLength == 6).Count() == 3).Count();
double F6 = (from f in fasets where f.MinCycleLength == 6 select f).Count();
if (MaxCycleLength == 6) { F6 = F6 - 1; };
double F3 = (from f in fasets where f.MinCycleLength == 3 select f).Count();
if (MaxCycleLength == 3) { F3 = F3 - 1; }
if (F3 > 0)
{
if (RandomGen3.NextDouble() < shellVertexWeight)
{
return 1.05;
}
}
double F4 = (from f in fasets where f.MinCycleLength == 4 select f).Count();
if (MaxCycleLength == 4) { F4 = F4 - 1; };
result = 0;
if (F4 > 10)
if (RandomGen3.NextDouble() < shellVertexWeight)
{
result = result - 10;
}
result = result + 5.1 * F6 + 2.01 * F4 + 4.0 * V3inner - V + 10.0;
return Math.Max(result, 1.1);
}
}
//ген = одно правило
public class MyGen
{
public bool WasActive = false; //активность
public byte Status;
public byte PriorStatus;
public byte Connections_GE;
public byte Connections_LE;
public byte Parents_GE;
public byte Parents_LE;
public byte OperationType;
public byte OperandStatus;
public MyGen()
{
SetValue(0);
}
public MyGen(ulong value)
{
SetValue(value);
}
public ulong GetValue()
{
ulong result = 0;
result = result | this.Status;
result = result << 8;
result = result | this.PriorStatus;
result = result << 8;
result = result | this.Connections_GE;
result = result << 8;
result = result | this.Connections_LE;
result = result << 8;
result = result | this.Parents_GE;
result = result << 8;
result = result | this.Parents_LE;
result = result << 8;
result = result | this.OperationType;
result = result << 8;
result = result | this.OperandStatus;
return result;
}
public void SetValue(ulong value)
{
this.OperandStatus = Math.Max((byte)1, (byte)(value & 0x0F));
value = value >> 8;
this.OperationType = (byte)(value & 0x0F);
value = value >> 8;
this.Parents_LE = (byte)(value);
value = value >> 8;
this.Parents_GE = (byte)(value);
value = value >> 8;
this.Connections_LE = (byte)(value & 0x0F);
value = value >> 8;
this.Connections_GE = (byte)(value & 0x0F);
value = value >> 8;
this.PriorStatus = (byte)(value & 0x0F);
value = value >> 8;
this.Status = Math.Max((byte)1, (byte)(value & 0x0F));
}
//преобразуем ген(правило) в элемент таблицы
public ChangeTableItem ToChangeTableItem()
{
OperationCondition condition = new OperationCondition();
Operation operation = new Operation();
condition.CurrentState = (NodeState)Status;
condition.PriorState = (NodeState)PriorStatus;
condition.AllConnectionsCount_GE = Connections_GE > 8 ? -1 : Connections_GE;
condition.AllConnectionsCount_LE = Connections_LE > 8 ? -1 : Connections_LE;
condition.ParentsCount_GE = Parents_GE > 64 ? -1 : Parents_GE;
condition.ParentsCount_LE = Parents_LE > 64 ? -1 : Parents_LE;
operation.Kind = (OperationKindEnum)(OperationType % 4);
operation.OperandNodeState = (NodeState)OperandStatus;
return new ChangeTableItem(condition, operation);
}
}
}
namespace GeneticGraphUnfolding
{
public partial class GeneticGUMMainWindow : Window
{
GUMGraph gumGraph;
//отображаемая хромосома, либо лучший результат эволюции, либо выбранный пример
MyChromosome MyChromosome;
EvolutionResult evolutionResult;
// Текущая фитнесс-функция
PlanarGraphFitnessFunction UsingPlanarGraphFitnessFunction;
// используется для определения начальных положений узлов
Random rnd = new Random((Int32)DateTime.Now.Ticks);
// испольлзуется для замера одной итерации GA
DateTime priorDateTime;
Dictionary<int, DateTime> priorSeveralIterationDateTimes = new Dictionary<int, DateTime>(10);
int tagCounter;
int iterationCounterSaved = 0;
int experimentRepeatCounterSaved = 1;
private class Arguments
{
internal int populationSize = 100;
internal int maxIterationCount = 100;
internal int maxExperimentsRepeatsCount = 10;
internal int chromosomeStartLength = 1000;
internal int selectionMethod = 0;
public int chromosomeMaxLength = 1000;
// начальная популяция
internal List<MyChromosome> initialPopulation = new List<MyChromosome>();
public GAParametres geneticAlgorithmParametres = new GAParametres();
public PlanarGraphFitnessFunction planarGraphFitnessFunction;
}
private class Progress
{
internal MyChromosome bestSolution;
internal double fitness;
internal double fitnessAvg;
internal double AgeAvg;
internal double AgeMax;
internal int ChromosomeLenghMax;
internal double ChromosomeLenghAvg;
internal int ActiveGensCountMax;
internal double ActiveGensCountAvg;
internal int iteration;
internal int ExperimentRepeatCounter;
}
//Результат эволюции
private class EvolutionResult
{
MyChromosome bestChromosome;
List<MyChromosome> chromosomes = new List<MyChromosome>();
public MyChromosome BestChromosome { get { return bestChromosome; } }
public List<MyChromosome> Chromosomes { get { return chromosomes; } }
public EvolutionResult(MyChromosome bestChromosome, List<MyChromosome> chromosomes)
{
this.bestChromosome = bestChromosome;
this.chromosomes = chromosomes;
}
}
private Arguments arguments = new Arguments();
private BackgroundWorker backgroundWorker1;
bool IsStarted;
private double priorFitnessValue;
private int priorLoggedIteration;
public GeneticGUMMainWindow()
{
InitializeComponent();
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
ResetInitialSettings();
}
private void ResetInitialSettings()
{
GAParametres defaultParametres = new GAParametres();
tbMutationRatio.Text = defaultParametres.MutationRate.ToString();
tbCrossingRation.Text = defaultParametres.CrossOverRate.ToString();
tbRandomSelectionRatio.Text = defaultParametres.RandomSelectionPortion.ToString();
arguments.maxExperimentsRepeatsCount = 5;
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
if (IsStarted)
{
IsStarted = false;
// останавливаем процесс
EnableControls(!IsStarted);
this.backgroundWorker1.CancelAsync();
}
else
{
IsStarted = true;
arguments.planarGraphFitnessFunction = CreateGraphFitnessFunctionFromGUI();
UsingPlanarGraphFitnessFunction = arguments.planarGraphFitnessFunction;
FillArgumentsFromControls(arguments);
arguments.selectionMethod = 0;
UpdateControls();
if (evolutionResult != null)
{
arguments.initialPopulation = evolutionResult.Chromosomes;
}
EnableControls(!IsStarted);
backgroundWorker1.RunWorkerAsync(arguments);
}
}
//фитнес-функция из интерфейса
private PlanarGraphFitnessFunction CreateGraphFitnessFunctionFromGUI()
{
int maxGUCAIterationCount = 150;
int maxVertexCount = Int32.Parse(tbMaxVertexCount.Text); //максимальное количество вершин
NumericalMethodParametres unfoldingParametres = CreateNumericalMethodparametresFromGUI();
double shellVertexWeight = 1.0;
double faset3penaltyProbability = 1.0;
TranscriptionWay transcriptionWay = (TranscriptionWay)cb_TranscriptionWay.SelectedIndex;
switch (comboBox_FitnessFunctionType.SelectedIndex)
{
case 0:
{
// Определяем статистику выбранного графа
gumGraph.Planarize();
Dictionary<int, int> aimVerticesDistributionByDegree = gumGraph.GetVerticiesDistributionByDegree();
Dictionary<int, int> aimFasetsDistributionByLength = gumGraph.GetFasetsDistributionByLength();
return new BySamplePlanarGraphFitnessFunction(
aimFasetsDistributionByLength, aimVerticesDistributionByDegree, maxGUCAIterationCount, maxVertexCount,
false, true,
unfoldingParametres, transcriptionWay);
}
case 1:
{
return new TriangleMeshPlanarGraphFitnessFunction(maxGUCAIterationCount, maxVertexCount, false, true, unfoldingParametres, transcriptionWay, shellVertexWeight);
}
case 2:
{
return new QuadricMeshPlanarGraphFitnessFunction(maxGUCAIterationCount, maxVertexCount, false, true, unfoldingParametres, transcriptionWay, shellVertexWeight, faset3penaltyProbability);
}
case 3:
{
return new HexMeshPlanarGraphFitnessFunction(maxGUCAIterationCount, maxVertexCount, false, true , unfoldingParametres, transcriptionWay, shellVertexWeight);
}
default:
return null;
}
}
private NumericalMethodParametres CreateNumericalMethodparametresFromGUI()
{
NumericalMethodParametres unfoldingParametres = new NumericalMethodParametres();
unfoldingParametres.OneIterationTimeStep = 0.20;
unfoldingParametres.OneProcessIterationCount = 20;
unfoldingParametres.OuterIterationCount = 20;
return unfoldingParametres;
}
//заполнение параметров ГА введенными значениями
private void FillArgumentsFromControls(Arguments arguments)
{
try
{
arguments.populationSize = Math.Max(10, Math.Min(1000, int.Parse(tbPopulationSize.Text)));
tbPopulationSize.Text = arguments.populationSize.ToString();
}
catch
{
arguments.populationSize = 40;
}
try
{
arguments.maxIterationCount = Math.Max(0, int.Parse(tbIterationCount.Text));
}
catch
{
arguments.maxIterationCount = 100;
}
arguments.maxExperimentsRepeatsCount = 5;
try
{
arguments.chromosomeStartLength = Math.Max(0, int.Parse(tbChromosomeStartLength.Text));
arguments.chromosomeMaxLength = 2 * arguments.chromosomeStartLength;
}
catch
{
arguments.chromosomeStartLength = 100;
arguments.chromosomeMaxLength = 200;
}
try
{
arguments.geneticAlgorithmParametres.MutationRate = double.Parse(tbMutationRatio.Text);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Invalid Mutation Ration", MessageBoxButton.OK, MessageBoxImage.Error);
}
try
{
arguments.geneticAlgorithmParametres.CrossOverRate = double.Parse(tbCrossingRation.Text);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Invalid cross over rate", MessageBoxButton.OK, MessageBoxImage.Error);
}
try
{
arguments.geneticAlgorithmParametres.RandomSelectionPortion = double.Parse(tbRandomSelectionRatio.Text);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Invalid 'random selection portion'", MessageBoxButton.OK, MessageBoxImage.Error);
}
arguments.geneticAlgorithmParametres.SingleActiveGenMutaionFactor = Double.Parse("0,1");
arguments.geneticAlgorithmParametres.SingleActiveGenMutaionKind = (MutationKind)1;
arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionFactor = Double.Parse("0,5");
arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionKind = (MutationKind)2;
UpdateControls();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
if (MessageBox.Show("Удалить текущую популяцию?","Перезапуск",MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
this.backgroundWorker1.CancelAsync();
arguments.initialPopulation = new List<MyChromosome>();
iterationCounterSaved = 0;
experimentRepeatCounterSaved = 0;
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
e.Result = ProcessEvolution((Arguments)e.Argument, worker, e);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Progress progress = (Progress)e.UserState;
DateTime iterataionEndTime = DateTime.Now;
UnfoldAndDisplayGraphFromChromosome(progress.bestSolution);
lbCurentIterationCount.Content = progress.iteration.ToString();
iterationCounterSaved = progress.iteration;
if (experimentRepeatCounterSaved != progress.ExperimentRepeatCounter)
{
// начался новый эксперимент
priorSeveralIterationDateTimes.Clear();
experimentRepeatCounterSaved = progress.ExperimentRepeatCounter;
}
lbBestFitnessValue.Content = String.Format("{0:F4}", progress.fitness);
lbFitnessAvgValue.Content = String.Format(" (avg.={0:F4})", progress.fitnessAvg);
lbChromosomeMinMaxAvgLength.Content = String.Format("{0} (avg: {1:F1} , max:{2} )", progress.bestSolution.Length, progress.ChromosomeLenghAvg, progress.ChromosomeLenghMax);
lbActiveGensInfo.Content = String.Format("{0} (avg: {1:F1} , max:{2} )", progress.bestSolution.activeGensCount, progress.ActiveGensCountAvg, progress.ActiveGensCountMax);
priorSeveralIterationDateTimes.Add(progress.iteration, iterataionEndTime);
int minIterationNum = priorSeveralIterationDateTimes.Min(x => x.Key);
if (priorSeveralIterationDateTimes.Count() >= 10)
{
priorSeveralIterationDateTimes.Remove(minIterationNum);
};
minIterationNum = priorSeveralIterationDateTimes.Min(x => x.Key);
Double avgSeveralIterationTimeInSeconds = 0;
if (progress.iteration != minIterationNum)
{
avgSeveralIterationTimeInSeconds = iterataionEndTime.Subtract(priorSeveralIterationDateTimes[minIterationNum]).TotalSeconds / (progress.iteration - minIterationNum);
}
TimeSpan iterationInterval = iterataionEndTime.Subtract(priorDateTime);
lbIterationTime.Content = String.Format("{0:F4} (avg: {1:F4})", iterationInterval.TotalSeconds, avgSeveralIterationTimeInSeconds);
priorDateTime = DateTime.Now;
//Протоколируем изменение фитнессфункции
if ((progress.iteration % 10 == 0) || (progress.iteration - priorLoggedIteration > 10) || priorFitnessValue != progress.fitness)
{
try
{
int vertexCount = 0;
int edgeCount = 0;
int fasetsCount = 0;
if (gumGraph != null)
{
vertexCount = gumGraph.VertexCount;
edgeCount = gumGraph.EdgeCount;
gumGraph.Planarize();
fasetsCount = gumGraph.Fasets != null ? gumGraph.Fasets.Count : 0;
}
}
catch (Exception ex)
{
lbStatus.Content = String.Format("{0} log error: {1}", DateTime.Now.ToString(), ex.Message.ToString());
}
priorFitnessValue = progress.fitness;
priorLoggedIteration = progress.iteration;
}
}
private EvolutionResult ProcessEvolution(Arguments arguments, BackgroundWorker worker, DoWorkEventArgs e)
{
List<IChromosome> initialPopulation = new List<IChromosome>(arguments.initialPopulation);
//создаем популяцию
Population population =
new Population(arguments.populationSize,
initialPopulation,
(IChromosome)new MyChromosome(arguments.chromosomeStartLength, arguments.chromosomeMaxLength, arguments.geneticAlgorithmParametres.SingleActiveGenMutaionFactor, arguments.geneticAlgorithmParametres.SingleActiveGenMutaionKind, arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionFactor, arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionKind
),
arguments.planarGraphFitnessFunction,
(arguments.selectionMethod == 0) ? (ISelectionMethod)new EliteSelection(false) :
(arguments.selectionMethod == 1) ? (ISelectionMethod)new RankSelection() : (ISelectionMethod)new RouletteWheelSelection(),
arguments.geneticAlgorithmParametres
);
//итерации
int iterationCounter = iterationCounterSaved + 1;
int experimentRepeatCounter = experimentRepeatCounterSaved ;
while (!worker.CancellationPending)
{
// запуск одной эпохи генетического алгоритма
population.RunEpoch();
try
{
Progress progress = new Progress();
progress.bestSolution = new MyChromosome((MyChromosome)population.BestChromosome);
if (progress.bestSolution != null)
{
progress.fitness = population.BestChromosome.Fitness;
}
else
{
progress.fitness = -999;
}
progress.fitnessAvg = population.FitnessAvg;
progress.AgeAvg = population.AgeAvg;
progress.AgeMax = population.AgeMax;
progress.ChromosomeLenghMax = population.ChromosomeLengthMax;
progress.ChromosomeLenghAvg = population.ChromosomeLenghAvg;
progress.ActiveGensCountMax = population.ActiveGensCountMax;
progress.ActiveGensCountAvg = population.ActiveGensCountAvg;
progress.iteration = iterationCounter;
progress.ExperimentRepeatCounter = experimentRepeatCounter;
worker.ReportProgress(iterationCounter, progress);
}
catch (Exception)
{
gumGraph = null;
}
// прибавляем итерацию
iterationCounter++;
// выполняем условия останова:
if ((arguments.maxIterationCount != 0) && (iterationCounter > arguments.maxIterationCount))
{
experimentRepeatCounter++;
iterationCounter = 1;
population.Regenerate();
if (experimentRepeatCounter > arguments.maxExperimentsRepeatsCount)
{
break;
}
}
}
// клонируем список хромосом для передачи результата эволюции:
List<MyChromosome> chromosomes = new List<MyChromosome>();
foreach (IChromosome c in population.Chromosomes)
{
chromosomes.Add((MyChromosome)c);
}
// форируем результат эволюции
EvolutionResult evolutionResult = new EvolutionResult((MyChromosome)population.BestChromosome, chromosomes);
return evolutionResult;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
evolutionResult = (EvolutionResult)e.Result;
UnfoldAndDisplayGraphFromChromosome(evolutionResult.BestChromosome);
}
else
{
evolutionResult = (EvolutionResult)e.Result;
UnfoldAndDisplayGraphFromChromosome(evolutionResult.BestChromosome);
}
EnableControls(true);
}
private void EnableControls(bool isStopped)
{
comboBox_Sample.IsEnabled = isStopped;
btnStart.Content = !isStopped ? "||" : ">";
btnCancel.IsEnabled = !isStopped;
btnLoadChangeTable.IsEnabled = isStopped;
}
private void UnfoldAndDisplayGraphFromChromosome(MyChromosome MyChromosome)
{
MyChromosome = MyChromosome;
int stepsPassed;
gumGraph = (GUMGraph)UsingPlanarGraphFitnessFunction.GrowGraph(MyChromosome, out stepsPassed);
gumGraph.ProcessUnfoldingModel(CreateNumericalMethodparametresFromGUI(), new Point(600, 500));
if (gumGraph != null)
{
if (btnDisplayGraphProperties != null) { btnDisplayGraphProperties.IsEnabled = true; }
}
}
private void CreateMesh(Physical2DGraph.Physical2DGraph grpah, int rows, int cols)
{
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph, true);
int n = rows;
int m = cols;
// 1. делаем основу n
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < n; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
for (int j = 0; j < m; j++)
{
Physical2DGraphVertex[] priorRow = grpah.Vertices.Reverse().Take(n + 1).ToArray();
// создаём новый ряд:
for (int i = 0; i < n + 1; i++)
{
Physical2DGraphVertex v = priorRow[i];
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v, this.CreateNewPointInCenter(gumGraph)));
}
// соединаем узлы нового ряда
Physical2DGraphVertex[] newRow = grpah.Vertices.Reverse().Take(n + 1).ToArray();
for (int i = 0; i < n + 1; i++)
{
Physical2DGraphVertex v = newRow[i];
if (i > 0) { grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(newRow[i - 1], v)); };
}
}
}
private void CreateQuadricRingMesh(Physical2DGraph.Physical2DGraph grpah, int rows, int cols)
{
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph, true);
int n = rows - 1;
int m = cols;
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < n; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
for (int j = 0; j < m; j++)
{
Physical2DGraphVertex[] priorRow = grpah.Vertices.Reverse().Take(n + 1).ToArray();
// создаём новый ряд:
for (int i = 0; i < n + 1; i++)
{
Physical2DGraphVertex v = priorRow[i];
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v, this.CreateNewPointInCenter(gumGraph)));
}
// соединаем узлы нового ряда
Physical2DGraphVertex[] newRow = grpah.Vertices.Reverse().Take(n + 1).ToArray();
for (int i = 0; i < n + 1; i++)
{
Physical2DGraphVertex v = newRow[i];
if (i > 0) { grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(newRow[i - 1], v)); };
}
grpah.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(newRow[0], newRow[n]));
}
}
private Physical2DGraphVertex CreateNewPointInCenter(Physical2DGraph.Physical2DGraph grpah, bool clearTagCounter = false)
{
if (clearTagCounter)
{
tagCounter = 1;
}
Physical2DGraphVertex v = new Physical2DGraphVertex(new Point(600 * 0.5 + grpah.PhysicalModelParametres.FreeConnectionLength * rnd.NextDouble(),
500 * 0.5 + grpah.PhysicalModelParametres.FreeConnectionLength * rnd.NextDouble()
)
);
grpah.AddVertex(v);
tagCounter++;
return v;
}
//тестовые графы
private void comboBox_Sample_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
gumGraph = new GUMGraph();
// заполняем тестовый граф вершинами и рёбрами, в зависимости от примера
switch (comboBox_Sample.SelectedIndex)
{
case 0: // дерево
{
#region пример 1 - дерево
Physical2DGraphVertex vA = new Physical2DGraphVertex(new Point(100, 100));
vA.Tag = "A";
gumGraph.AddVertex(vA);
Physical2DGraphVertex vB = new Physical2DGraphVertex(new Point(100, 50));
vB.Tag = "B";
gumGraph.AddVertex(vB);
Physical2DGraphVertex vC = new Physical2DGraphVertex(new Point(150, 75));
vC.Tag = "C";
gumGraph.AddVertex(vC);
Physical2DGraphVertex vD = new Physical2DGraphVertex(new Point(80, 200));
vD.Tag = "D";
gumGraph.AddVertex(vD);
Physical2DGraphVertex vE = new Physical2DGraphVertex(new Point(175, 200));
vE.Tag = "E";
gumGraph.AddVertex(vE);
Physical2DGraphVertex vF = new Physical2DGraphVertex(new Point(200, 100));
vF.Tag = "F";
gumGraph.AddVertex(vF);
Physical2DGraphVertex vG = new Physical2DGraphVertex(new Point(300, 100));
vG.Tag = "G";
gumGraph.AddVertex(vG);
Physical2DGraphVertex vH = new Physical2DGraphVertex(new Point(50, 75));
vH.Tag = "H";
gumGraph.AddVertex(vH);
Physical2DGraphVertex vK = new Physical2DGraphVertex(new Point(250, 50));
vK.Tag = "K";
gumGraph.AddVertex(vK);
Physical2DGraphVertex vL = new Physical2DGraphVertex(new Point(330, 175));
vL.Tag = "L";
gumGraph.AddVertex(vL);
Physical2DGraphVertex vM = new Physical2DGraphVertex(new Point(260, 150));
vM.Tag = "M";
gumGraph.AddVertex(vM);
Physical2DGraphVertex vN = new Physical2DGraphVertex(new Point(270, 200));
vN.Tag = "N";
gumGraph.AddVertex(vN);
Physical2DGraphVertex vU = new Physical2DGraphVertex(new Point(45, 150));
vU.Tag = "U";
gumGraph.AddVertex(vU);
Physical2DGraphEdge<Physical2DGraphVertex> edgeAH = new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vH);
gumGraph.AddEdge(edgeAH);
Physical2DGraphEdge<Physical2DGraphVertex> edgeBA = new Physical2DGraphEdge<Physical2DGraphVertex>(vB, vA);
gumGraph.AddEdge(edgeBA);
Physical2DGraphEdge<Physical2DGraphVertex> edgeUA = new Physical2DGraphEdge<Physical2DGraphVertex>(vU, vA);
gumGraph.AddEdge(edgeUA);
Physical2DGraphEdge<Physical2DGraphVertex> edgeDA = new Physical2DGraphEdge<Physical2DGraphVertex>(vD, vA);
gumGraph.AddEdge(edgeDA);
Physical2DGraphEdge<Physical2DGraphVertex> edgeAC = new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vC);
gumGraph.AddEdge(edgeAC);
Physical2DGraphEdge<Physical2DGraphVertex> edgeCE = new Physical2DGraphEdge<Physical2DGraphVertex>(vC, vE);
gumGraph.AddEdge(edgeCE);
Physical2DGraphEdge<Physical2DGraphVertex> edgeCF = new Physical2DGraphEdge<Physical2DGraphVertex>(vC, vF);
gumGraph.AddEdge(edgeCF);
Physical2DGraphEdge<Physical2DGraphVertex> edgeFK = new Physical2DGraphEdge<Physical2DGraphVertex>(vF, vK);
gumGraph.AddEdge(edgeFK);
Physical2DGraphEdge<Physical2DGraphVertex> edgeFM = new Physical2DGraphEdge<Physical2DGraphVertex>(vF, vM);
gumGraph.AddEdge(edgeFM);
Physical2DGraphEdge<Physical2DGraphVertex> edgeMG = new Physical2DGraphEdge<Physical2DGraphVertex>(vM, vG);
gumGraph.AddEdge(edgeMG);
Physical2DGraphEdge<Physical2DGraphVertex> edgeGN = new Physical2DGraphEdge<Physical2DGraphVertex>(vG, vN);
gumGraph.AddEdge(edgeGN);
Physical2DGraphEdge<Physical2DGraphVertex> edgeGL = new Physical2DGraphEdge<Physical2DGraphVertex>(vG, vL);
gumGraph.AddEdge(edgeGL);
#endregion
break;
};
case 1: // обобщённый пример 1
{
#region пример 2 - обобщённый
Physical2DGraphVertex vA = new Physical2DGraphVertex(new Point(100, 100));
vA.Tag = "A";
gumGraph.AddVertex(vA);
Physical2DGraphVertex vB = new Physical2DGraphVertex(new Point(100, 50));
vB.Tag = "B";
gumGraph.AddVertex(vB);
Physical2DGraphVertex vC = new Physical2DGraphVertex(new Point(150, 75));
vC.Tag = "C";
gumGraph.AddVertex(vC);
Physical2DGraphVertex vD = new Physical2DGraphVertex(new Point(80, 200));
vD.Tag = "D";
gumGraph.AddVertex(vD);
Physical2DGraphVertex vE = new Physical2DGraphVertex(new Point(175, 200));
vE.Tag = "E";
gumGraph.AddVertex(vE);
Physical2DGraphVertex vF = new Physical2DGraphVertex(new Point(200, 100));
vF.Tag = "F";
gumGraph.AddVertex(vF);
Physical2DGraphVertex vG = new Physical2DGraphVertex(new Point(300, 100));
vG.Tag = "G";
gumGraph.AddVertex(vG);
Physical2DGraphVertex vH = new Physical2DGraphVertex(new Point(50, 75));
vH.Tag = "H";
gumGraph.AddVertex(vH);
Physical2DGraphVertex vK = new Physical2DGraphVertex(new Point(250, 50));
vK.Tag = "K";
gumGraph.AddVertex(vK);
Physical2DGraphVertex vL = new Physical2DGraphVertex(new Point(330, 175));
vL.Tag = "L";
gumGraph.AddVertex(vL);
Physical2DGraphVertex vM = new Physical2DGraphVertex(new Point(260, 150));
vM.Tag = "M";
gumGraph.AddVertex(vM);
Physical2DGraphVertex vN = new Physical2DGraphVertex(new Point(270, 200));
vN.Tag = "N";
gumGraph.AddVertex(vN);
Physical2DGraphVertex vU = new Physical2DGraphVertex(new Point(45, 150));
vU.Tag = "U";
gumGraph.AddVertex(vU);
Physical2DGraphVertex v1 = new Physical2DGraphVertex(new Point(55, 170));
v1.Tag = "1";
gumGraph.AddVertex(v1);
Physical2DGraphVertex v2 = new Physical2DGraphVertex(new Point(45, 190));
v2.Tag = "2";
gumGraph.AddVertex(v2);
Physical2DGraphVertex vV = new Physical2DGraphVertex(new Point(380, 175));
vV.Tag = "V";
gumGraph.AddVertex(vV);
Physical2DGraphVertex vW = new Physical2DGraphVertex(new Point(380, 225));
vW.Tag = "W";
gumGraph.AddVertex(vW);
Physical2DGraphVertex vO = new Physical2DGraphVertex(new Point(100, 125));
vO.Tag = "O";
gumGraph.AddVertex(vO);
Physical2DGraphVertex vP = new Physical2DGraphVertex(new Point(80, 150));
vP.Tag = "P";
gumGraph.AddVertex(vP);
Physical2DGraphVertex vQ = new Physical2DGraphVertex(new Point(120, 160));
vQ.Tag = "Q";
gumGraph.AddVertex(vQ);
Physical2DGraphVertex vR = new Physical2DGraphVertex(new Point(100, 180));
vR.Tag = "R";
gumGraph.AddVertex(vR);
Physical2DGraphVertex vS = new Physical2DGraphVertex(new Point(110, 75));
vS.Tag = "S";
gumGraph.AddVertex(vS);
Physical2DGraphVertex vT = new Physical2DGraphVertex(new Point(40, 20));
vT.Tag = "T";
gumGraph.AddVertex(vT);
Physical2DGraphVertex vX = new Physical2DGraphVertex(new Point(210, 210));
vX.Tag = "X";
gumGraph.AddVertex(vX);
Physical2DGraphVertex vY = new Physical2DGraphVertex(new Point(190, 250));
vY.Tag = "Y";
gumGraph.AddVertex(vY);
Physical2DGraphVertex vZ = new Physical2DGraphVertex(new Point(5, 300));
vZ.Tag = "Z";
gumGraph.AddVertex(vZ);
Physical2DGraphEdge<Physical2DGraphVertex> edgeAH = new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vH);
gumGraph.AddEdge(edgeAH);
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vC));
Physical2DGraphEdge<Physical2DGraphVertex> edgeDH = new Physical2DGraphEdge<Physical2DGraphVertex>(vD, vH);
gumGraph.AddEdge(edgeDH);
Physical2DGraphEdge<Physical2DGraphVertex> edgeED = new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vD);
gumGraph.AddEdge(edgeED);
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vC));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vC, vB));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vH, vB));
Physical2DGraphEdge<Physical2DGraphVertex> edgeEA = new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vA);
gumGraph.AddEdge(edgeEA);
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vF, vC));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vF, vK));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vM, vF));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vK, vG));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vM, vG));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vL, vG));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vL, vV));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vW, vL));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vM, vN));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vS, vA));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vO));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vP, vO));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vO, vQ));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vP, vQ));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vQ, vR));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vR, vP));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vH, vT));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vT, vB));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vX));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vY));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vX, vY));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vZ, vH));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vZ, vE));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vH, vU));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v1, vU));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v1, v2));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v2, vD));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vF));
gumGraph.AddEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vE, vM));
#endregion
break;
};
case 2: // обобщённый пример 2
{
#region пример 3 - обобщённый
Physical2DGraphVertex vA = new Physical2DGraphVertex(new Point(100, 100));
vA.Tag = "A";
gumGraph.AddVertex(vA);
Physical2DGraphVertex vB = new Physical2DGraphVertex(new Point(100, 50));
vB.Tag = "B";
gumGraph.AddVertex(vB);
Physical2DGraphVertex vC = new Physical2DGraphVertex(new Point(150, 75));
vC.Tag = "C";
gumGraph.AddVertex(vC);
Physical2DGraphVertex vD = new Physical2DGraphVertex(new Point(80, 200));
vD.Tag = "D";
gumGraph.AddVertex(vD);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vA, vB));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vB, vC));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vB, vD));
MessageBox.Show(String.Format("vertices count {0}", gumGraph.VertexCount));
#endregion
break;
}
case 3: // Кольцо-6
{
#region Кольцо 6
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 5; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
this.Unfold(gumGraph);
#endregion
break;
}
case 4: // Волосатое кольцо-6
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vLeaf = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vStart, vLeaf));
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 5; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vLeaf = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vLeaf));
vPrior = vNext;
}
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
this.Unfold(gumGraph);
#endregion
break;
}
case 5: // Треугольник с деревьями-6
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vTree = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vStart, vTree));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vTree, this.CreateNewPointInCenter(gumGraph)));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vTree, this.CreateNewPointInCenter(gumGraph)));
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 2; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vTree = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vTree));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vTree, this.CreateNewPointInCenter(gumGraph)));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vTree, this.CreateNewPointInCenter(gumGraph)));
vPrior = vNext;
}
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
this.Unfold(gumGraph);
#endregion
break;
}
case 6: // Кольцо c нитью 6
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 5; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
for (int i = 0; i < 3; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
this.Unfold(gumGraph);
#endregion
break;
}
case 7: // Кольцо-8
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 7; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vStart));
this.Unfold(gumGraph);
#endregion
break;
}
case 8: // Нитка-7
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vPrior = vStart;
Physical2DGraphVertex vNext = null;
for (int i = 0; i < 6; i++)
{
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vPrior, vNext));
vPrior = vNext;
}
this.Unfold(gumGraph);
#endregion
break;
}
case 9: // Звёздочка-6
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
for (int i = 0; i < 5; i++)
{
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vStart, this.CreateNewPointInCenter(gumGraph)));
}
this.Unfold(gumGraph);
#endregion
break;
}
case 10: // Mesh-1 (квадратная сетка 3x3)
{
#region
this.CreateMesh(gumGraph, 3, 3);
this.Unfold(gumGraph);
#endregion
break;
}
case 11: // Mesh-2 (квадратная сетка 9x1)
{
#region
this.CreateMesh(gumGraph, 9, 1);
this.Unfold(gumGraph);
#endregion
break;
}
case 12: // Mesh-3 (квадратная сетка-кольцо)
{
#region
this.CreateQuadricRingMesh(gumGraph, 9, 1);
this.Unfold(gumGraph);
#endregion
break;
}
case 13: // Mesh-4 (квадратная сетка 4x2)
{
#region
this.CreateMesh(gumGraph, 4, 2);
this.Unfold(gumGraph);
#endregion
break;
}
case 14: // Mesh-5 (квадратная сетка 4x4)
{
#region
this.CreateMesh(gumGraph, 4, 4);
this.Unfold(gumGraph);
#endregion
break;
}
case 15: // Mesh-6 (квадратная сетка 6x6)
{
#region
this.CreateMesh(gumGraph, 6, 6);
this.Unfold(gumGraph);
#endregion
break;
}
case 16: // Mesh-7 (квадратная сетка 2x2 + листья)
{
#region
this.CreateMesh(gumGraph, 2, 2);
foreach (Physical2DGraphVertex v in gumGraph.Vertices.Reverse().Take(3).ToArray())
{
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v, this.CreateNewPointInCenter(gumGraph)));
}
foreach (Physical2DGraphVertex v in gumGraph.Vertices.Take(3).ToArray())
{
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(v, this.CreateNewPointInCenter(gumGraph)));
}
this.Unfold(gumGraph);
#endregion
break;
}
case 17: // Mesh-8 (квадратная цепочка)
{
#region
Physical2DGraphVertex vStart = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vNext1 = null;
Physical2DGraphVertex vNext2 = null;
Physical2DGraphVertex vNext = vStart;
for (int i = 0; i < 9; i++)
{
vNext1 = this.CreateNewPointInCenter(gumGraph);
vNext2 = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vNext1));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vNext2));
vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext1, vNext));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext2, vNext));
}
this.Unfold(gumGraph);
#endregion
break;
}
case 18: // Mesh-9 (квадратная крест и листья)
{
#region
this.CreateMesh(gumGraph, 1, 1);
Physical2DGraphVertex[] centerVertexArray = gumGraph.Vertices.ToArray();
for (int i = 0; i < 4; i++)
{
Physical2DGraphVertex vNext1 = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vNext2 = this.CreateNewPointInCenter(gumGraph);
int nextInd = i < 3 ? i + 1 : 0;
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(centerVertexArray[i], vNext1));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(centerVertexArray[nextInd], vNext2));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext1, vNext2));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext1, this.CreateNewPointInCenter(gumGraph)));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext2, this.CreateNewPointInCenter(gumGraph)));
}
this.Unfold(gumGraph);
#endregion
break;
}
case 19: // Mesh-10 (треугольная сетка)
{
#region
Physical2DGraphVertex vCenter = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vFirst = null;
Physical2DGraphVertex vPrior = null;
for (int i = 0; i < 6; i++)
{
Physical2DGraphVertex vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vCenter, vNext));
if (i > 0)
{
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vPrior));
if (i == 5)
{
// соединяем с первым
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vFirst));
}
}
else
{
vFirst = vNext;
}
vPrior = vNext;
}
this.Unfold(gumGraph);
#endregion
break;
}
case 20: // Mesh-11 (дефектная треугольная сетка)
{
#region
Physical2DGraphVertex vCenter = this.CreateNewPointInCenter(gumGraph);
Physical2DGraphVertex vFirst = null;
Physical2DGraphVertex vPrior = null;
for (int i = 0; i < 5; i++)
{
Physical2DGraphVertex vNext = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vCenter, vNext));
if (i > 0)
{
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vPrior));
if (i == 4)
{
Physical2DGraphVertex vDefect = this.CreateNewPointInCenter(gumGraph);
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vNext, vDefect));
// соединяем с первым
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vDefect, vFirst));
}
}
else
{
vFirst = vNext;
}
vPrior = vNext;
}
this.Unfold(gumGraph);
#endregion
break;
}
case 21: // Mesh-12 (дефектная квадратная сетка)
{
#region
for (int i = 0; i < 16; i++)
{
this.CreateNewPointInCenter(gumGraph);
}
Physical2DGraphVertex[] vArr = gumGraph.Vertices.ToArray();
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[0], vArr[1]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[1], vArr[2]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[3], vArr[2]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[0], vArr[3]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[0], vArr[1]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[1], vArr[5]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[5], vArr[2]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[3], vArr[4]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[4], vArr[0]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[4], vArr[9]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[0], vArr[8]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[7], vArr[1]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[7], vArr[6]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[5], vArr[6]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[6], vArr[15]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[15], vArr[14]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[14], vArr[7]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[7], vArr[8]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[10], vArr[8]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[10], vArr[11]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[11], vArr[9]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[11], vArr[12]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[12], vArr[13]));
gumGraph.AddVerticesAndEdge(new Physical2DGraphEdge<Physical2DGraphVertex>(vArr[13], vArr[10]));
this.Unfold(gumGraph);
#endregion
break;
}
default:
break;
}
UpdateControls();
}
private void Unfold(GUMGraph gumGraph)
{
NumericalMethodParametres parametres = new NumericalMethodParametres();
parametres.OneIterationTimeStep = 0.2;
parametres.OneProcessIterationCount = 20;
parametres.OuterIterationCount = 20;
gumGraph.ProcessUnfoldingModel(parametres);
}
private void btnDisplayFenotype_Click(object sender, RoutedEventArgs e)
{
UnfoldAndDisplayGraphFromChromosome(MyChromosome);
}
//отображение информации о графе
private void btnDisplayGraphProperties_Click(object sender, RoutedEventArgs e)
{
// 0. Для отладки: нумеруем вершины графа
if (gumGraph != null)
{
// 1. вызываем метод планаразации гарфа.
gumGraph.Planarize();
bool isPlanned = gumGraph.IsPlanned();
foreach (Physical2DGraphEdge<Physical2DGraphVertex> edge in gumGraph.Edges)
{
edge.IsBelongToFacet = false;
}
foreach (Cycle<Physical2DGraphVertex> faset in gumGraph.Fasets)
{
foreach (Physical2DGraphEdge<Physical2DGraphVertex> edge in faset)
{
edge.IsBelongToFacet = true;
}
}
// отображаем статистику графа
StringBuilder sb = new StringBuilder();
UsingPlanarGraphFitnessFunction = CreateGraphFitnessFunctionFromGUI();
sb.AppendLine(String.Format("Количество вершин = {0}", gumGraph.VertexCount));
Dictionary<int, int> vertParts = gumGraph.GetVerticiesDistributionByDegree();
foreach (var part in vertParts)
{
sb.AppendLine(String.Format("Вершин степени {0} = {1}", part.Key, part.Value));
}
sb.AppendLine();
sb.AppendLine(String.Format("Количество граней = {0}", gumGraph.Fasets.Count));
Dictionary<int, int> fasetParts = gumGraph.GetFasetsDistributionByLength();
foreach (var part in fasetParts)
{
sb.AppendLine(String.Format("Граней степени {0} = {1}", part.Key, part.Value));
}
textPlanarStatistics.Text = sb.ToString();
}
}
private void DoUpdateVertexRenderShape(Physical2DGraph.Physical2DGraphVertex vertex, Transform transform)
{
DrawingVisual dw = (DrawingVisual)vertex.visualForCanvasViewer;
DrawingContext dc = dw.RenderOpen();
Point position = transform.Transform(vertex.Position);
if (vertex.Tag != null)
{
Color txtCol = GetVertexRenderTextColor(vertex);
FormattedText formattedText = new FormattedText(
vertex.Tag.ToString(),
System.Globalization.CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface("Verdana"),
12,
new SolidColorBrush(Colors.White));
}
dc.Close();
}
private void DoUpdateEdgeRenderShape(Physical2DGraphEdge<Physical2DGraph.Physical2DGraphVertex> edge, Transform transform)
{
Point DisplayPosition1 = transform.Transform(edge.Source.Position);
Point DisplayPosition2 = transform.Transform(edge.Target.Position);
DrawingVisual dw = (DrawingVisual)edge.visualForCanvasViewer;
DrawingContext dc = dw.RenderOpen();
Color colSource = Colors.Lime;
Color colTarget = Colors.Lime;
if ((edge.Source is GUMNode) && (edge.Target is GUMNode))
{
GUMNode gumnSource = edge.Source as GUMNode;
colSource = GetVertexRenderColor(gumnSource);
GUMNode gumnTarget = edge.Target as GUMNode;
colTarget = GetVertexRenderColor(gumnTarget);
}
Brush b;
b = new SolidColorBrush(colSource);
}
#endregion
private void UpdateControls()
{
if (gumGraph != null)
{
if (btnDisplayGraphProperties != null) { btnDisplayGraphProperties.IsEnabled = true; }
}
if (((comboBox_FitnessFunctionType.SelectedIndex == 0) && (comboBox_Sample.SelectedIndex != -1))
|| (comboBox_FitnessFunctionType.SelectedIndex >= 0)
)
{
btnStart.IsEnabled = true;
}
else
{
btnStart.IsEnabled = false;
}
if ((MyChromosome != null) && (UsingPlanarGraphFitnessFunction != null))
{
btnSaveChangeTable.IsEnabled = true;
}
}
private void btnSaveChangeTable_Click(object sender, RoutedEventArgs e)
{
ChangeTable changeTable = MyChromosome.GetChangeTable();
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.Filter = "XAML (*.xaml)|*.xaml| All files (*.*)|*.*";
dlg.FilterIndex = 0;
dlg.FileName = "ChangeTable.xaml";
if (dlg.ShowDialog() == true)
{
try
{
System.IO.FileStream stream = new FileStream(dlg.FileName, FileMode.Create);
System.Windows.Markup.XamlWriter.Save(changeTable, stream);
stream.Close();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "xamlWhriter.Save Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None);
}
}
}
//Загрузка гена и заполнение им популяции
private void btnLoadChangeTable_Click(object sender, RoutedEventArgs e)
{
int chromosomeStartLength;
int chromosomeMaxLength;
try
{
chromosomeStartLength = Math.Max(0, int.Parse(tbChromosomeStartLength.Text));
chromosomeMaxLength = 2 * chromosomeStartLength;
}
catch
{
chromosomeStartLength = 100;
chromosomeMaxLength = 200;
}
if (MessageBox.Show("Fill the population by genom from file?", "Genom loading from file..", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "XAML (*.xaml)|*.xaml| All files (*.*)|*.*";
if (dlg.ShowDialog() == true)
{
ChangeTable changeTable;
try
{
// загружаем из файла:
System.IO.FileStream stream = new FileStream(dlg.FileName, FileMode.Open);
changeTable = (ChangeTable)System.Windows.Markup.XamlReader.Load(stream);
stream.Close();
// заполняем начальную популяцию загруженным "геном".
FillArgumentsFromControls(arguments);
MyChromosome crhomosome = new MyChromosome(changeTable.Count, chromosomeMaxLength, arguments.geneticAlgorithmParametres.SingleActiveGenMutaionFactor, arguments.geneticAlgorithmParametres.SingleActiveGenMutaionKind, arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionFactor, arguments.geneticAlgorithmParametres.SinglePassiveGenMutaionKind );
crhomosome.SetChangeTable(changeTable);
if (evolutionResult == null)
{
// расчёт ещё ни разу не запускался:
evolutionResult = new EvolutionResult(crhomosome, new List<MyChromosome>());
}
evolutionResult.Chromosomes.Clear();
UsingPlanarGraphFitnessFunction = CreateGraphFitnessFunctionFromGUI();
int stepsCount;
UsingPlanarGraphFitnessFunction.GrowGraph(crhomosome, out stepsCount);
MyChromosome newChromosome;
for (int i = 0; i < arguments.populationSize; i++)
{
newChromosome = new MyChromosome(crhomosome);
evolutionResult.Chromosomes.Add(new MyChromosome(crhomosome));
}
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "xamlReader.Save Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None);
}
}
} }
private void comboBox_FitnessFunctionType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
UpdateControls();
}
}
}