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

Листинг программы Приложение а

(обязательное).

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();

}

}

}