Ejemplo n.º 1
0
 public bool Equals(PairPos pair)
 {
     if (pair.FirstPos.Equals(this.FirstPos) && pair.SecondPos.Equals(this.SecondPos) ||
         pair.SecondPos.Equals(this.FirstPos) && pair.FirstPos.Equals(this.SecondPos))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Ejemplo n.º 2
0
        public static List <StepPlacementLog> Place(Matrix <int> R, out string errMsg)
        {
            // если в методе произошла какая-то критическая ошибка, записывайте её в эту переменную и делайте return null
            errMsg = "";

            var log = new List <StepPlacementLog>();

            // так как итерационный метод должен основываться на резульатах последовательного размещения
            // считываем результаты размещения
            var plc = ApplicationData.ReadPlacement(out errMsg);

            if (errMsg != "")
            {
                return(log);
            }

            var cmp = ApplicationData.ReadComposition(out errMsg);

            // если произошла ошибка при чтении результатов размещения - заканчиваем алгоритм
            if (errMsg != "")
            {
                return(null);
            }

            // считываем матрицы плат с уже размещёнными элементами
            List <Matrix <int> > boardsMatrices = plc.BoardsMatrices;

            var st = new StepPlacementLog(boardsMatrices, "Начинаем итерационное разщмещение...");

            log.Add(st);

            // запускаем цикл по всем платам
            for (int boardNum = 0; boardNum < boardsMatrices.Count; boardNum++)
            {
                // получаем матрицу, в котором хранятся номера элементов текущей платы
                var boardMatr = boardsMatrices[boardNum];

                // создаем список для пар позиций, элементы в которых нужно попробовать поменять местами
                List <PairPos> pairs = new List <PairPos>();

                // формируем список пар соседей
                // проходим по всем позициям платы
                for (int i = 0; i < boardMatr.RowsCount; i++)
                {
                    for (int j = 0; j < boardMatr.ColsCount; j++)
                    {
                        // если текущая позиция содержит элемент
                        if (boardMatr[i, j] != -1)
                        {
                            var currentPos = new Position(i, j);
                            // получаем позиции соседей для текущей позиции, которые содержат элемент
                            var neighbors = getNeighbors(boardMatr, currentPos);

                            // если найден хоть 1 сосед
                            if (neighbors.Count > 0)
                            {
                                // для каждого соседа создаём пару с текущим элементом
                                foreach (var neighbor in neighbors)
                                {
                                    var currentPair = new PairPos();
                                    currentPair.FirstPos  = currentPos.Clone();
                                    currentPair.SecondPos = neighbor.Clone();

                                    // если такой пары нет в уже сформированных, то добавляем её в общий список
                                    if (!pairs.Any(x => x.Equals(currentPair)))
                                    {
                                        pairs.Add(currentPair);
                                    }
                                }
                            }
                        }
                    }
                }
                // максимальное приращение
                int deltaLMax;
                // пара с этим максимальным приращением
                PairPos pairMaxDeltaL = new PairPos();

                string stepMsg = "";

                // запускаем цикл, пока будут положительные приращения
                do
                {
                    deltaLMax     = 0;
                    pairMaxDeltaL = null;
                    stepMsg       = "";

                    // запускаем цикл по всем парам
                    foreach (var pair in pairs)
                    {
                        int firstEl  = boardMatr[pair.FirstPos.Row, pair.FirstPos.Column];
                        int secondEl = boardMatr[pair.SecondPos.Row, pair.SecondPos.Column];
                        // формируем по кусочкам сообщение
                        stepMsg += $"\u0394L({firstEl}-{secondEl}) = ";

                        // формируем список остальных элементов на плате, кроме элоементов текущей пары
                        var otherElements = cmp.BoardsElements[boardNum].Select(x => x).ToList();
                        otherElements.Remove(firstEl);
                        otherElements.Remove(secondEl);
                        // добавляем элемент разъёма
                        otherElements.Add(0);
                        otherElements.Sort();

                        // текущее приращение
                        int L = 0;

                        // это просто 2 списка для формирования сообщения шага
                        List <string> operationsDef   = new List <string>(); // в этом хранится буквенное обозначение операции, например: (r1 - r2)*(d1 - d2)
                        List <string> operationsValue = new List <string>(); // а тут именно числовое (5 - 8)*(1 - 3)

                        // начинаем считать приращение для текущей пары
                        // для этого запускаем цикл по всем остальным элементам
                        foreach (var otherElement in otherElements)
                        {
                            // получаем позицию рассматриваемого элемента
                            Position currentElPos = getPosByElementNumber(boardMatr, otherElement);


                            operationsDef.Add($"(r{otherElement}-{firstEl} - r{otherElement}-{secondEl})*" +
                                              $"(d{otherElement}-{firstEl} - d{otherElement}-{secondEl})");

                            operationsValue.Add($"({R[otherElement, firstEl]}-{R[otherElement, secondEl]})*" +
                                                $"({getLength(currentElPos, pair.FirstPos)}-{getLength(currentElPos, pair.SecondPos)})");

                            // прибавляем к общему приращению
                            // (количество связей между текущим и первым из пары + количество связей между текущим и вторым из пары) *
                            // (длинна между позицией текущего и первого из пары - длинна между позицией текущего и второго из пары)
                            L += (R[otherElement, firstEl] - R[otherElement, secondEl]) *
                                 (getLength(currentElPos, pair.FirstPos) - getLength(currentElPos, pair.SecondPos));
                        }
                        // добавляем к сообщению шага сразу все описания операций
                        stepMsg += string.Join("+", operationsDef);
                        stepMsg += "=";
                        // потом все подставленные значения
                        stepMsg += string.Join("+", operationsValue);
                        stepMsg += "=";
                        stepMsg += L + "\n";
                        // если у текущей пары L больше чем у уже найденной ранее
                        if (L > deltaLMax)
                        {
                            deltaLMax     = L;    // запоминаем максимальное приращение
                            pairMaxDeltaL = pair; // и текущую пару
                        }
                    }

                    // нашли пару с максимальным приращением

                    // только если это приращение больше 0, нужно поменять элементы на позициях платы местами
                    if (deltaLMax > 0)
                    {
                        // т.к. у нас есть только позиции на плате, элементы в которых нужно поменять местами
                        // достаём номера элементов по этим позиция из матрицы платы
                        int firstElement  = boardMatr[pairMaxDeltaL.FirstPos.Row, pairMaxDeltaL.FirstPos.Column];
                        int secondElement = boardMatr[pairMaxDeltaL.SecondPos.Row, pairMaxDeltaL.SecondPos.Column];

                        // добавляем описание
                        stepMsg += $" -- Наибольшее \u0394L у пары ({firstElement}-{secondElement}) = {deltaLMax}. Меняем их местами";

                        // и наконец меняцм местами
                        boardMatr[pairMaxDeltaL.FirstPos.Row, pairMaxDeltaL.FirstPos.Column]   = secondElement;
                        boardMatr[pairMaxDeltaL.SecondPos.Row, pairMaxDeltaL.SecondPos.Column] = firstElement;
                    }
                    else
                    {
                        stepMsg += " -- Положительных приращений нет";
                    }

                    // логируем изменения
                    var step = new StepPlacementLog(boardsMatrices, stepMsg);
                    log.Add(step);

                    // цикл будет менять местами элементы с максимальным положительным приращением, пока не найдёт
                    // ни одного положительного приращения между парами
                } while (deltaLMax > 0);
            }

            return(log);
        }