/// <summary>
        /// Декодировать текущую секцию из генотипа.
        /// </summary>
        /// <param name="chromosome">Декодируемая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции в декодируемой хромосоме.</param>
        public void Decode(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                var sectionGenes = chromosome.GetGenes()       // Получаем значения генов только данной секции
                                   .Select((gene, index) => new { Value = (int)gene.Value, Index = index })
                                   .Where(q => GetSectionIndex(q.Index) == sectionIndex)
                                   .Select(q => q.Value)
                                   .ToArray();

                if (sectionGenes.Length < GeneValueGenerationFuncs.Length)
                {
                    throw new Exception("Incorrect section size!");
                }

                // 0-й ген - тип КУ, 1-й ген - узел КУ, 2-й ген - тип УСПД, 3-й ген - узел УСПД, 4-й ген - КПД
                MCDPart.Decode(chromosome.CurrentProject, sectionGenes[0], sectionGenes[1]);
                DADPart.Decode(chromosome.CurrentProject, sectionGenes[2], sectionGenes[3]);

                Channel = chromosome.CurrentProject.Equipments.DCs[sectionGenes[4]];
            }
            catch (Exception ex)
            {
                Console.WriteLine("TopologySection Decode failed! {0}", ex.Message);
            }
        }
Пример #2
0
        /// <summary>
        /// Сгенерировать новый ген, представляющий случайную вершину графа, для расположения в ней УСПД.
        /// </summary>
        /// <param name="chromosome">Текущая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции, для которой генерируется ген.</param>
        /// <returns>Целочисленное значение случайного гена, соответствующее индексу в массиве вершин графа.</returns>
        public static int GenerateVertexGene(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                // Выбираем случайный участок
                var randomRegionIndex = RandomizationProvider.Current.GetInt(0, chromosome.CurrentProject.Regions.Length);

                var randomRegion = chromosome.CurrentProject.Regions[randomRegionIndex];

                // Берём все вершины участка
                var regionVertices = chromosome.CurrentProject.Graph.Vertices.Where(q => q.Region == randomRegion);

                var minVertexWeight = regionVertices.Min(q => q.LaboriousnessWeight);    // Определяем самый малый вес у вершин участка

                // Находим все вершины с наименьшим весом
                var minWeightVertices = regionVertices.Where(q => q.LaboriousnessWeight == minVertexWeight);

                // Выбираем случайно одну вершину из тех, что с наименьшим весом
                return(RandomizationProvider.Current.GetInt(0, minWeightVertices.Count()));
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateDAVertexGene failed! {0}", ex.Message);
                return(0);
            }
        }
        /// <summary>
        /// Сгенерировать новый ген, представляющий случайный КПД для связьи устройства учёта и управления и УСПД,
        /// выбирается такой, чтобы подходил к устройству и к КПД.
        /// </summary>
        /// <param name="chromosome">Текущая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции, для которой генерируется ген.</param>
        /// <returns>Целочисленное значение случайного гена, соответствующее индексу в массиве доступных каналов передачи данных.</returns>
        protected static int GenerateDataChannelGene(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                // Декодируем КУ из гена, которое выбрано в данной секции (оно идёт первым в хромосоме)
                var mcd = chromosome.CurrentProject.Equipments.MCDs[(int)chromosome.GetGene(sectionIndex * TopologyChromosome.GENES_IN_SECTION).Value];

                // Декодируем УСПД из гена, которое выбрано в данной секции (оно идёт третьим в хромосоме)
                var dad = chromosome.CurrentProject.Equipments.DADs[(int)chromosome.GetGene(sectionIndex * TopologyChromosome.GENES_IN_SECTION + 2).Value];

                // Выбираем те КПД, которые совместимы и с выбранным КУ, и с выбранным УСПД
                var suitableDataChannels = chromosome.CurrentProject.Equipments.DCs
                                           .Select((dataChannel, index) => new { DataChannel = dataChannel, Index = index })
                                           .Where(indexedChannel => mcd.SendingCommunications.Contains(indexedChannel.DataChannel.Communication) &&
                                                  dad.ReceivingCommunications.Keys.Contains(indexedChannel.DataChannel.Communication))
                                           .ToArray();

                // Если не нашли подходящего УСПД, то выбираем случайный
                if (!suitableDataChannels.Any())
                {
                    return(RandomizationProvider.Current.GetInt(0, chromosome.CurrentProject.Equipments.DCs.Length));
                }

                // Иначе берём случайный КПД из подходящих
                var randomIndex = RandomizationProvider.Current.GetInt(0, suitableDataChannels.Count());

                return(suitableDataChannels[randomIndex].Index);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateDataChannelGene failed! {0}", ex.Message);
                return(0);
            }
        }
Пример #4
0
        /// <summary>
        /// Декодировать пути между элементами секций хромосомы.
        /// </summary>
        /// <param name="chromosome">Декодируемая хромосома.</param>
        protected void DecodePathes(TopologyChromosome chromosome)
        {
            try
            {
                // Группируем секции по частям с УСПД и перебираем группы
                foreach (var dadGroup in Sections.GroupBy(q => q.DADPart, new DataAcquisitionSectionPartComparer()))
                {
                    var pathes = new List <TopologyPath>();

                    foreach (var channelGroup in dadGroup.GroupBy(w => w.Channel))  // Группы секций группируем по каналам передачи данных, которые связывают КУ и УСПД
                    {
                        // Находим путь между УСПД и всеми КУ по каждому каналу передачи в группе секций
                        var path = TopologyPathfinder.GetShortestPath(chromosome.CurrentProject.Graph, dadGroup.Key.Vertex, channelGroup.Select(q => q.MCDPart.Vertex), channelGroup.Key);

                        if (path != null)
                        {
                            pathes.AddRange(path);
                        }
                    }

                    Pathes.Add(dadGroup.Key, pathes);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("DecodePathes failed! {0}", ex.Message);
            }
        }
Пример #5
0
        /// <summary>
        /// Сгенерировать новый ген, представляющий случайное устройство сбора и передачи данных.
        /// </summary>
        /// <param name="chromosome">Текущая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции, для которой генерируется ген.</param>
        /// <returns>Целочисленное значение случайного гена, соответствующее индексу в массиве УСПД.</returns>
        public static int GenerateDeviceGene(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                // Декодируем КУ из гена, которое выбрано в данной секции (оно идёт первым в хромосоме)
                var mcd = chromosome.CurrentProject.Equipments.MCDs[(int)chromosome.GetGene(sectionIndex * TopologyChromosome.GENES_IN_SECTION).Value];

                // Выбираем только те УСПД, которые подходят для КУ
                var suitableDADs = chromosome.CurrentProject.Equipments.DADs
                                   .Select((dad, index) => new { DAD = dad, Index = index })
                                   .Where(indexedDAD => indexedDAD.DAD.ReceivingCommunications.Keys.Any(communiction => mcd.SendingCommunications.Contains(communiction)))
                                   .ToArray();

                // Если не нашли подходящего УСПД, берём просто случайный
                if (!suitableDADs.Any())
                {
                    return(RandomizationProvider.Current.GetInt(0, chromosome.CurrentProject.Equipments.DADs.Length));
                }

                // Иначе берём случайный из подходящих
                var randomIndex = RandomizationProvider.Current.GetInt(0, suitableDADs.Count());

                return(suitableDADs[randomIndex].Index);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateDADeviceGene failed! {0}", ex.Message);
                return(0);
            }
        }
Пример #6
0
        /// <summary>
        /// Создать новую топологию - декодировать фенотип хромосомы на базе её текущего генотипа.
        /// </summary>
        /// <param name="chromosome">Декодируемая хромосома.</param>
        public Topology(TopologyChromosome chromosome)
        {
            try
            {
                Sections = new TopologySection[chromosome.CurrentProject.MCZs.Length];
                Pathes   = new Dictionary <DataAcquisitionSectionPart, IEnumerable <TopologyPath> >();

                DecodeSections(chromosome);
                GroupDADs(chromosome);
                DecodePathes(chromosome);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Topology failed! {0}", ex.Message);
            }
        }
Пример #7
0
        /// <summary>
        /// Генерировать новое случайное значение гена, представляющего устройство учёта и управления.
        /// Из всех доступных устройств, выбираются только те, которые подходят для данного места учёта и управления.
        /// Ген является индексом в массиве всех доступных устройств.
        /// </summary>
        /// <param name="chromosome">Текущая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции, для которой генерируется ген.</param>
        /// <returns>Целочисленное значение случайного гена, соответствующее индексу в массиве доступных устройств.</returns>
        public static int GenerateDeviceGene(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                var suitableMCDs = chromosome.CurrentProject.Equipments.MCDs
                                   .Select((mcd, index) => new { MCD = mcd, Index = index })                         // Запоминаем индекс устройства в массиве всех доступных устройств
                                   .Where(q => q.MCD.IsSuitableForMCZ(chromosome.CurrentProject.MCZs[sectionIndex])) // Выбираем только те устройства, которые подходят для места
                                   .ToArray();

                var randomIndex = RandomizationProvider.Current.GetInt(0, suitableMCDs.Count());        // Выбираем из массива выбранных устройств случайное

                return(suitableMCDs[randomIndex].Index);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateMCDevice failed! {0}", ex.Message);
                return(0);
            }
        }
Пример #8
0
        /// <summary>
        /// Поочерёдно декодировать каждую секцию хромосомы.
        /// </summary>
        /// <param name="chromosome">Декодируемая хромосома.</param>
        protected void DecodeSections(TopologyChromosome chromosome)
        {
            try
            {
                for (var sectionIndex = 0; sectionIndex < chromosome.Length / TopologyChromosome.GENES_IN_SECTION; sectionIndex++)
                {
                    if (Sections[sectionIndex] == null)
                    {
                        Sections[sectionIndex] = new TopologySection();
                    }

                    Sections[sectionIndex].Decode(chromosome, sectionIndex);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("DecodeSections failed! {0}", ex.Message);
            }
        }
        /// <summary>
        /// Сгенерировать новое значение гена секции в зависимости от индекса гена.
        /// </summary>
        /// <param name="chromosome">Хромосома, для гена которой предназначено данное значение.</param>
        /// <param name="geneIndex">Индекс гена в хромосоме.</param>
        /// <returns>Новое случайное значение гена для хромосомы.</returns>
        public static int GenerateGeneValue(TopologyChromosome chromosome, int geneIndex)
        {
            try
            {
                var geneInSectionIndex = GetGeneInSectionIndex(geneIndex);

                if (geneInSectionIndex >= GeneValueGenerationFuncs.Length)
                {
                    return(0);
                }

                // Вызываем соответствующую функцию для генерации гена
                return(GeneValueGenerationFuncs[geneInSectionIndex].Invoke(chromosome, GetSectionIndex(geneIndex)));
            }
            catch (Exception ex)
            {
                Console.WriteLine("EncodeGeneValue failed! {0}", ex.Message);
                return(0);
            }
        }
Пример #10
0
        /// <summary>
        /// Сгенерировать новый ген, представляющий случайную вершину графа, который находится на выбранном
        /// месте учёта и управления. Ген является индексом в массиве вершин графа, на которых
        /// находится данное место учёта и управления.
        /// </summary>
        /// <param name="chromosome">Текущая хромосома.</param>
        /// <param name="sectionIndex">Индекс секции, для которой генерируется ген.</param>
        /// <returns>Целочисленное значение случайного гена, соответствующее индексу в массиве вершин графа.</returns>
        public static int GenerateVertexGene(TopologyChromosome chromosome, int sectionIndex)
        {
            try
            {
                var currentMCZ = chromosome.CurrentProject.MCZs[sectionIndex];          // Текущее место учёта и управления

                var mczVertices = chromosome.CurrentProject.Graph.VerticesArray
                                  .Select((vertex, index) => new { Vertex = vertex, Index = index }) // Запоминаем индекс в массиве каждого места
                                  .Where(q => q.Vertex.MCZs.Contains(currentMCZ)).ToArray();         // Берём те вершины графа, где располагается данное место

                var randomIndex = RandomizationProvider.Current.GetInt(0, mczVertices.Count());

                return(mczVertices[randomIndex].Index);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GenerateMCDVertexGene failed! {0}", ex.Message);
                return(0);
            }
        }
Пример #11
0
        /// <summary>
        /// Сгруппировать УСПД одной модели, расположенные на одном участке.
        /// </summary>
        /// <param name="chromosome">Декодириуемая хромосома.</param>
        protected void GroupDADs(TopologyChromosome chromosome)
        {
            try
            {
                var dadSectionPartGroups = Sections
                                           .Select((section, Index) => new { Part = section.DADPart, Index }) // Запоминаем и индекс секции
                                           .GroupBy(q => q.Part.DAD)                                          // Группируем секции с одинаковым УСПД
                                           .Where(q => q.Count() > 1);                                        // Берём те группы, если хоть какие-то УСПД сгруппировали

                foreach (var dadSectionPartGroup in dadSectionPartGroups)
                {
                    // Далее группируем по участкам и берём те группы, где их больше 1 и где они ещё не на одной вершине
                    var regionSectionPartGroups = dadSectionPartGroup
                                                  .GroupBy(q => q.Part.Vertex.Region)
                                                  .Where(q => q.Count() > 1);

                    foreach (var regionSectionPartGroup in regionSectionPartGroups)
                    {
                        // Если все устройства и так уже в одной вершине, пропускаем эту группу
                        var firstVertex = dadSectionPartGroup.FirstOrDefault()?.Part.Vertex;

                        if (firstVertex == null || regionSectionPartGroup.All(q => q.Part.Vertex == firstVertex))
                        {
                            continue;
                        }

                        var dadsBus = TopologyPathfinder.GetShortestPath(   // Находим кратчайший путь
                            chromosome.CurrentProject.Graph,
                            firstVertex,                                    // Из первой вершины в группе
                            regionSectionPartGroup
                            .Select(q => q.Part.Vertex)                     // До остальных вершин в группе
                            .Distinct()                                     // Без повторяющихся вершин и без исходной вершины
                            .Where(q => q != firstVertex),                  // По топологии шина и учитывая только расстояние
                            new DataChannel {
                            ConnectionType = ConnectionType.None, Topology = DataChannelTopology.Bus
                        });

                        // Берём все грани пути и выбираем из них целевые вершины
                        var pathVertices = dadsBus.Where(q => q.Path != null).SelectMany(q => q.Path).Select(q => q.Target).ToList();

                        pathVertices.Add(firstVertex);                                      // И добавляем исходную вершину

                        var minVertexWeight = pathVertices.Min(q => q.LaboriousnessWeight); // Определяем самый малый вес у вершин пути

                        // Находим все вершины с наименьшим весом
                        var minWeightVertices = pathVertices.Where(q => q.LaboriousnessWeight == minVertexWeight);

                        // Выбираем случайно одну вершину из тех, что с наименьшим весом
                        var randomOptimalVertex = minWeightVertices.ElementAt(RandomizationProvider.Current.GetInt(0, minWeightVertices.Count()));

                        // Перемещаем все УСПД, которые ещё не в оптимальной вершине, в эту вершину, чтобы они стали одним УСПД
                        foreach (var sectionPart in regionSectionPartGroup.Where(q => q.Part.Vertex != randomOptimalVertex))
                        {
                            sectionPart.Part.Move(randomOptimalVertex);

                            // Определяем индекс вершины в упорядоченном массиве вершин
                            var index = Array.IndexOf(chromosome.CurrentProject.Graph.VerticesArray, randomOptimalVertex);

                            // Модифицируем хромосому тоже, находим ген позиции УСПД и обновляем индекс новой вершины
                            chromosome.ReplaceGene(sectionPart.Index * TopologyChromosome.GENES_IN_SECTION + 3, new GeneticSharp.Domain.Chromosomes.Gene(index));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("GroupDADs failed! {0}", ex.Message);
            }
        }