Beispiel #1
0
        public static List <StepPlacementLog> Place(CompositionResult cmp, Matrix <int> R, out string errMsg)
        {
            // если в методе произошла какая-то критическая ошибка, записывайте её в эту переменную и делайте return null
            errMsg = "";

            // считываем результат компоновки, в нём хранится список элементов для каждого узла
            var boardsElements = cmp.BoardsElements;

            // создаём класс для логирования (обязательно)
            var log = new List <StepPlacementLog>();

            // создаём список с матрицами для каждого узла
            var boards = new List <Matrix <int> >();

            // тестовый алгоритм просто последовательно размещает все элементы на плату

            // запускаем цикл по платам, в каждой плате резмещаем элементы, а потом переходим к следующей
            foreach (var boardElements in boardsElements)
            {
                // определяем размер платы (3х3, 4х4, 5х5) основываясь на количестве элементов, которые необходимо на ней расположить
                var size = Convert.ToInt32(Math.Ceiling(Math.Sqrt(boardElements.Count)));

                // создаём матрицу просчитанного размера
                var boardMatr = new Matrix <int>(size, size);

                // заполняем "-1" матрицу
                boardMatr.Fill(-1);

                // добавляем в общий список плат новую матрицу платы, в которую будем на этом шаге заносить элементы
                boards.Add(boardMatr);

                // определяет в какую позицию будет поставлен элемент
                int pos = 0;

                // запускаем цикл по элементам, которые должны быть размещены на плате
                foreach (var element in boardElements)
                {
                    // добавляем в последнюю плату элемент на определённую позицию. позиция тут задаётся от 1 до 9. нумерация немного не такая как в идз:
                    // 1 4 7
                    // 2 5 8
                    // 3 6 9 (для платы 3х3)
                    boards.Last().setValueByPlatePos(pos, element);
                    pos++;


                    // записываем результат
                    string msg  = "Поместили элемент D" + element + " на " + boards.Count + " плату"; // пишем сообщение чё произошло на этом шаге
                    var    step = new StepPlacementLog(boards, msg);
                    log.Add(step);
                }
            }

            // возвращаем список шагов
            return(log);
        }
Beispiel #2
0
        public static List <StepPlacementLog> Place(CompositionResult cmp, Matrix <int> R, out string errMsg)
        {
            matrR = R;
            // если в методе произошла какая-то критическая ошибка, записывайте её в эту переменную и делайте return null
            errMsg = "";

            // считываем результат компоновки, в нём хранится список элементов для каждого узла
            var boardsElements = cmp.BoardsElements;

            // создаём класс для логирования (обязательно)
            var log = new List <StepPlacementLog>();

            // создаём список с матрицами для каждого узла
            var boards = new List <Matrix <int> >();

            // запускаем цикл по платам, в каждой плате резмещаем элементы, а потом переходим к следующей
            foreach (var boardElements in boardsElements)
            {
                // определяем размер платы (3х3, 4х4, 5х5) основываясь на количестве элементов, которые необходимо на ней расположить
                var size = Convert.ToInt32(Math.Ceiling(Math.Sqrt(boardElements.Count)));

                // создаём матрицу просчитанного размера
                var boardMatr = new Matrix <int>(size, size);

                // заполняем "-1" матрицу
                boardMatr.Fill(-1);

                // добавляем в общий список плат новую матрицу платы, в которую будем на этом шаге заносить элементы
                boards.Add(boardMatr);

                // начальная позиция - условные координаты разъема
                var pos = new Position(-1, -1);

                // таким способом копируем список всех элементов в список неразмещённых
                List <int> unplacedElements = boardElements.Select(x => x).ToList();

                // в списке размещённых по умолчанию только разъём
                List <int> placedElements = new List <int>();
                placedElements.Add(0);

                // запускаем цикл, пока не разместим все элементы
                while (unplacedElements.Count > 0)
                {
                    // список с количеством связей с ранее размещёнными элементами ещё неразмещённых
                    // позиция в списке совпадает с позицией в списке неразмещённых номеров элементов
                    var countRelationWithPlaced = new List <int>();

                    // с помощью метода получаем список количества связей для каждого неразмещённого элемента
                    countRelationWithPlaced = countRelations(unplacedElements, placedElements);

                    // определяем максимальное число связей
                    var maxRelations = countRelationWithPlaced.Max();

                    // определяем позицию, в которой находится элемент с максимальным количеством связей
                    var elementPosMaxRelations = countRelationWithPlaced.IndexOf(maxRelations);

                    // получаем номер элемента по позиции в списке
                    var elementNumberMaxRelations = unplacedElements[elementPosMaxRelations];

                    string msg = "Количество связей с размещёнными элементами неразмещённых: ";
                    for (int i = 0; i < unplacedElements.Count; i++)
                    {
                        msg += $"D{unplacedElements[i]}={countRelationWithPlaced[i]}; ";
                    }
                    msg += "\n";
                    msg += $"Максимальное количество c размещёнными элементами у элемента D{elementNumberMaxRelations}\n";
                    msg += $"Найдём оптимальную позицию:\n";

                    // получаем список незанятых соседних ячеек на основе позиции элемента размещённого на предыдущем шаге
                    var neighbors = getNeigbors(boardMatr, pos);

                    // начинаем определение оптимальной позиции для размещения элемента
                    Position minLpos = null;
                    int      minL    = int.MaxValue;
                    // запускаем цикл по всем соседям
                    foreach (var neighbor in neighbors)
                    {
                        msg += $"D{elementNumberMaxRelations} -> {boardMatr.getRelativePosByAbsolute(neighbor)}; L=";
                        List <string> operations = new List <string>();
                        int           L          = 0;
                        // запускаем цикл по всем элементам
                        for (int j = 0; j < matrR.ColsCount; j++)
                        {
                            // если этот элемент был размещён
                            if (placedElements.Contains(j))
                            {
                                // если у размещаемого элемента есть связи с текущим рассматриваемым
                                if (matrR[elementNumberMaxRelations, j] != 0)
                                {
                                    // количество связей определяем по матрице R
                                    int countRelationsWithElement = matrR[elementNumberMaxRelations, j];
                                    // получаем расстояние между элементами
                                    int length = getLength(neighbor, getPosByElementNumber(boardMatr, j));
                                    operations.Add($"{countRelationsWithElement}*{length}");
                                    // суммируем длину умноженную на количество связей в L
                                    L += countRelationsWithElement * length;
                                }
                            }
                        }
                        msg += String.Join("+", operations);
                        msg += $"={L}\n";
                        // если подсчитанное L меньше просчитанного на предыдущих шагах
                        if (L < minL)
                        {
                            minL = L;
                            // принимаем эту позицию как оптимальную
                            minLpos = neighbor.Clone();
                        }
                    }
                    int minLposRelative = boardMatr.getRelativePosByAbsolute(minLpos);
                    msg += $"Минимальное значение L в {minLposRelative} позиции\n";
                    pos  = minLpos.Clone();

                    // устанавливаем элемент в оптимальную позицию
                    boards.Last().setValueByPlatePos(minLposRelative, elementNumberMaxRelations);

                    // начинаем логирование действия

                    msg += $"Помещаем его в {minLposRelative} позицию на {boards.Count} плату";
                    var step = new StepPlacementLog(boards, msg);
                    log.Add(step);
                    // закончили логирование

                    // убираем из списка неразмещённых элемент, который только что разместили
                    unplacedElements.Remove(elementNumberMaxRelations);
                    // и добавляем в список размещённых
                    placedElements.Add(elementNumberMaxRelations);
                }
            }
            return(log);
        }
Beispiel #3
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);
        }
Beispiel #4
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(null);
            }

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

            // переменные для операций с матрицами, списками и прочим
            int    coloumn, row, coloumn_next, row_next, coef, index, i, j, maxL, exchange_coloumn, exchange_row, buf, boardNum;
            string stepMsg;
            bool   flag;

            // номер текущей платы
            boardNum = 0;
            log.Add(new StepPlacementLog(boardsMatrices, "Начинаем итерационное размещение методом Шаффера..."));
            // цикл по платам с уже размещёнными элементами
            foreach (var boardMatrix in boardsMatrices)
            {
                boardNum++;
                // если у платы меньше 3 строк или столбцов, то нет смысла переставлять столбцы и строки
                if (boardMatrix.ColsCount < 3 || boardMatrix.RowsCount < 3)
                {
                    stepMsg = $" -- Плата №{boardNum} имеет размер менее 3х3. Нет смысла её рассматривать .\n";
                    var step = new StepPlacementLog(boardsMatrices, stepMsg);
                    log.Add(step);
                    continue;
                }
                // цикл по столбцам платы
                flag = true;
                // цикл продолжается, пока есть положительные приращения deltaL
                while (flag == true)
                {
                    stepMsg = $" -- Рассматриваем столбцы платы №{boardNum}.\n";
                    // создание матрицы со связями для текущей платы
                    Matrix <int> n = new Matrix <int>(boardMatrix.RowsCount, boardMatrix.ColsCount);
                    n.Fill(0);
                    // цикл по столбцами (слева направо); последний столбец не рассматриваем
                    for (coloumn = 0; coloumn < boardMatrix.ColsCount - 1; coloumn++)
                    {
                        // цикл по элементам столбца (сверху вниз)
                        for (row = 0; row < boardMatrix.RowsCount; row++)
                        {
                            // проверка, размещен ли элемент в этом месте платы
                            if (boardMatrix[row, coloumn] == -1)
                            {
                                continue;
                            }
                            // цикл по оставшимся столбцам матрицы для подсчета связей текущего столбца с каждым
                            for (coloumn_next = coloumn + 1; coloumn_next < boardMatrix.ColsCount; coloumn_next++)
                            {
                                // цикл по элементам следующих столбцов для подсчета связей
                                // текущего элемента текущего столбца с каждым из элементов следующих столбцов
                                for (row_next = 0; row_next < boardMatrix.RowsCount; row_next++)
                                {
                                    // проверка, размещен ли элемент в этом месте платы
                                    if (boardMatrix[row_next, coloumn_next] == -1)
                                    {
                                        continue;
                                    }
                                    // добавление к ячейке n очередной связи (из матрицы R) текущего
                                    // элемента текущего столбца с очередным элементом одного из следующих столбцов
                                    n[coloumn, coloumn_next] += R[boardMatrix[row, coloumn], boardMatrix[row_next, coloumn_next]];
                                    // заполняем матрицу зеркально ниже нулевой диагонали
                                    n[coloumn_next, coloumn] += R[boardMatrix[row, coloumn], boardMatrix[row_next, coloumn_next]];
                                }
                            }
                        }
                    }
                    // вычисление deltaL для определения пар столбцов, которые надо поменять местами
                    List <int> deltaL = new List <int>(n.ColsCount - 1);
                    // цикл для вычисления каждого deltaL
                    for (index = 0; index < deltaL.Capacity; index++)
                    {
                        stepMsg += $"\u0394L{index + 1}-{index + 2} = ";
                        // это просто 2 списка для формирования сообщения шага
                        List <string> operationsDef   = new List <string>(); // в этом хранится буквенное обозначение операции, например: (r1 - r2)*(d1 - d2)
                        List <string> operationsValue = new List <string>(); // а тут именно числовое (5 - 8)*(1 - 3)

                        // список номеров столбцов, кроме двух текущих
                        List <int> other = new List <int>();
                        for (i = 0; i < deltaL.Capacity + 1; i++)
                        {
                            if (i != index && i != index + 1)
                            {
                                other.Add(i);
                            }
                        }
                        // обнуление текущего L для его наращивания в цикле
                        deltaL.Add(0);
                        // цикл по списку не текущих столбцов. в каждом проходе реализация формулы k*(l13 - l23) (числа для примера)
                        for (j = 0; j < other.Count; j++)
                        {
                            // расстояние между столбцами
                            coef = Math.Abs(index - other[j]) - Math.Abs(index + 1 - other[j]);
                            // формула k*(l13 - l23)
                            deltaL[index] += coef * (n[index, other[j]] - n[index + 1, other[j]]);

                            operationsDef.Add($"(r{index + 1}-{other[j] + 1} - r{index + 2}-{other[j] + 1})*" +
                                              $"(d{index + 1}-{other[j] + 1} - d{index + 2}-{other[j] + 1})");

                            operationsValue.Add($"({n[index, other[j]]}-{n[index + 1, other[j]]})*" +
                                                $"({Math.Abs(index - other[j])}-{Math.Abs(index + 1 - other[j])})");
                        }
                        // добавляем к сообщению шага сразу все описания операций
                        stepMsg += string.Join(" + ", operationsDef);
                        stepMsg += " = ";
                        // потом все подставленные значения
                        stepMsg += string.Join(" + ", operationsValue);
                        stepMsg += " = ";
                        stepMsg += deltaL[index] + ".\n";
                    }

                    // наибольшее значения из списка deltaL
                    maxL = 0;
                    // номер столбца, который нужно поменять местами с его соседом справа
                    exchange_coloumn = -1;
                    // цикл для поиска положительных значений в списке deltaL для определения пар столбцов, которые надо поменять местами
                    for (i = 0; i < deltaL.Count; i++)
                    {
                        if (deltaL[i] > maxL)
                        {
                            maxL             = deltaL[i];
                            exchange_coloumn = i;
                        }
                    }
                    // проверка необходимости перестановки столбцов
                    if (maxL > 0)
                    {
                        stepMsg += $" -- Наибольшее \u0394L у столбцов {exchange_coloumn + 1} и {exchange_coloumn + 2} = {maxL}. Меняем их местами.";
                        // перестановка пары столбцов
                        for (row = 0; row < boardMatrix.RowsCount; row++)
                        {
                            buf = boardMatrix[row, exchange_coloumn];
                            boardMatrix[row, exchange_coloumn]     = boardMatrix[row, exchange_coloumn + 1];
                            boardMatrix[row, exchange_coloumn + 1] = buf;
                        }
                        flag = true;
                    }
                    else
                    {
                        stepMsg += " -- Положительных приращений нет";
                        flag     = false;
                    }

                    var step = new StepPlacementLog(boardsMatrices, stepMsg);
                    log.Add(step);
                }

                // цикл по строкам платы
                flag = true;
                // цикл продолжается, пока есть положительные приращения deltaL
                while (flag == true)
                {
                    stepMsg = $" -- Рассматриваем строки платы №{boardNum}.\n";
                    // создание матрицы со связями для текущей платы
                    Matrix <int> n = new Matrix <int>(boardMatrix.ColsCount, boardMatrix.RowsCount);
                    n.Fill(0);
                    // цикл по строкам (сверху вниз); последнюю строку не рассматриваем
                    for (row = 0; row < boardMatrix.RowsCount - 1; row++)
                    {
                        // цикл по элементам строки (слева направо)
                        for (coloumn = 0; coloumn < boardMatrix.ColsCount; coloumn++)
                        {
                            // проверка, размещен ли элемент в этом месте платы
                            if (boardMatrix[row, coloumn] == -1)
                            {
                                continue;
                            }
                            // цикл по оставшимся строкам матрицы для подсчета связей текущей строки с каждой
                            for (row_next = row + 1; row_next < boardMatrix.RowsCount; row_next++)
                            {
                                // цикл по элементам следующих строк для подсчета связей
                                // текущего элемента текущей строки с каждым из элементов следующих строк
                                for (coloumn_next = 0; coloumn_next < boardMatrix.ColsCount; coloumn_next++)
                                {
                                    // проверка, размещен ли элемент в этом месте платы
                                    if (boardMatrix[row_next, coloumn_next] == -1)
                                    {
                                        continue;
                                    }
                                    // добавление к ячейке n очередной связи (из матрицы R) текущего
                                    // элемента текущей строки с очередным элементом одной из следующих строк
                                    n[coloumn, coloumn_next] += R[boardMatrix[row, coloumn], boardMatrix[row_next, coloumn_next]];
                                    // заполняем матрицу зеркально ниже нулевой диагонали
                                    n[coloumn_next, coloumn] += R[boardMatrix[row, coloumn], boardMatrix[row_next, coloumn_next]];
                                }
                            }
                        }
                    }
                    // вычисление deltaL для определения пар строк, которые надо поменять местами
                    List <int> deltaL = new List <int>(n.RowsCount - 1);
                    // цикл для вычисления каждого deltaL
                    for (index = 0; index < deltaL.Capacity; index++)
                    {
                        stepMsg += $"\u0394L{index + 1}-{index + 2} = ";
                        // это просто 2 списка для формирования сообщения шага
                        List <string> operationsDef   = new List <string>(); // в этом хранится буквенное обозначение операции, например: (r1 - r2)*(d1 - d2)
                        List <string> operationsValue = new List <string>(); // а тут именно числовое (5 - 8)*(1 - 3)

                        // список номеров строк, кроме двух текущих
                        List <int> other = new List <int>();
                        for (i = 0; i < deltaL.Capacity + 1; i++)
                        {
                            if (i != index && i != index + 1)
                            {
                                other.Add(i);
                            }
                        }
                        // обнуление текущего L для его наращивания в цикле
                        deltaL.Add(0);
                        // цикл по списку не текущих столбцов. в каждом проходе реализация формулы k*(l13 - l23) (числа для примера)
                        for (j = 0; j < other.Count; j++)
                        {
                            // расстояние между строками
                            coef = Math.Abs(index - other[j]) - Math.Abs(index + 1 - other[j]);
                            // формула k*(l13 - l23)
                            deltaL[index] += coef * (n[index, other[j]] - n[index + 1, other[j]]);

                            operationsDef.Add($"(r{index + 1}-{other[j] + 1} - r{index + 2}-{other[j] + 1})*" +
                                              $"(d{index + 1}-{other[j] + 1} - d{index + 2}-{other[j] + 1})");

                            operationsValue.Add($"({n[index, other[j]]}-{n[index + 1, other[j]]})*" +
                                                $"({Math.Abs(index - other[j])}-{Math.Abs(index + 1 - other[j])})");
                        }
                        // добавляем к сообщению шага сразу все описания операций
                        stepMsg += string.Join(" + ", operationsDef);
                        stepMsg += " = ";
                        // потом все подставленные значения
                        stepMsg += string.Join(" + ", operationsValue);
                        stepMsg += " = ";
                        stepMsg += deltaL[index] + ".\n";
                    }

                    // наибольшее значения из списка deltaL
                    maxL = 0;
                    // номер строки, которую нужно поменять местами с её соседом снизу
                    exchange_row = -1;
                    // цикл для поиска положительных значений в списке deltaL для определения пар строк, которые надо поменять местами
                    for (i = 0; i < deltaL.Count; i++)
                    {
                        if (deltaL[i] > maxL)
                        {
                            maxL         = deltaL[i];
                            exchange_row = i;
                        }
                    }
                    // проверка необходимости перестановки строк
                    if (maxL > 0)
                    {
                        stepMsg += $" -- Наибольшее \u0394L у строк {exchange_row + 1} и {exchange_row + 2} = {maxL}. Меняем их местами.";
                        // перестановка пары столбцов
                        for (row = 0; row < boardMatrix.RowsCount; row++)
                        {
                            buf = boardMatrix[row, exchange_row];
                            boardMatrix[row, exchange_row]     = boardMatrix[row, exchange_row + 1];
                            boardMatrix[row, exchange_row + 1] = buf;
                        }
                        flag = true;
                    }
                    else
                    {
                        stepMsg += " -- Положительных приращений нет";
                        flag     = false;
                    }

                    var step = new StepPlacementLog(boardsMatrices, stepMsg);
                    log.Add(step);
                }
            }

            return(log);
        }
Beispiel #5
0
        public static List <StepPlacementLog> Place()
        {
            // создаём класс для логирования (обязательно)
            var log = new List <StepPlacementLog>();

            // создаём список с матрицами для каждого узла
            var boards = new List <Matrix <int> >();

            var boardMatr = new Matrix <int>(2, 2);

            boardMatr.Fill(-1);

            // добавляем в общий список плат новую матрицу платы, в которую будем на этом шаге заносить элементы
            boards.Add(boardMatr);


            //boardMatr

            // начинаем логирование действия

            string msg = "r = {4 3 2 1 1 0}\n" +
                         "d = {1 1 1 1 2 2} \n" +
                         "r х d = 4 + 3 + 2 + 1 + 2 + 0 = 12. \n" +
                         "Значение целевой функции F(P) не может быть меньше 12.\n";
            var step = new StepPlacementLog(boards, msg);

            log.Add(step);


            boardMatr[0, 0] = 1;
            msg             = "Помещаем элемент e1 в позицию р1 \n" +
                              "Размещен 1 элемент: F(q) = 0. \n" +
                              "Неразмещенные элементы {e2, e3, e4}, свободные позиции {р2, р3, р4}\n" +
                              "r1 = {4 3 1} и d1 = {1 1 2}; r1 х d1 =  4 + 3 + 2 = 9 \n" +
                              "w(P) =  9; \n" +
                              "r = {2 1 0} и d = {1 1 2}; v(P) = r х d = 2 + 1 + 0 = 3;\n" +
                              "v(P) = r х d = 2 + 1 + 0 = 3;\n" +
                              "F(P) = 0 + 9 + 3 = 12.\n\n" +
                              "Помещаем элемент e1 в позицию р2\n" +
                              "Размещен 1 элемент: F(q) = 0.\n" +
                              "Неразмещенные элементы {e2, e3, e4}, свободные позиции {р1, р3, р4}.\n" +
                              "r1 = {4 3 1} и d2 = {1 1 2}; r1 x d2 =  4 + 3 + 2 = 9; \n" +
                              "w(P) =  9;\n" +
                              "r = {2 1 0} и d= {1 1 2}; v(P) = r x d = 2 + 1 + 0 = 3;\n" +
                              "F(P) = 0 + 9 + 3 = 12.\n\n" +
                              "Помещаем элемент e1 в позицию р3 \n" +
                              "Размещен 1 элемент: F(q) = 0.\n" +
                              "Неразмещенные элементы {e2, e3, e4}, свободные позиции {р1, р2, р4}.\n" +
                              "r1 = {4 3 1} и d3 = {1 1 2}; r1 х d3 =  4 + 3 + 2 = 9;\n" +
                              "w(P) =  9; \n" +
                              "r = {2 1 0} и d = {1 1 2}; v(P) = r х d = 2 + 1 + 0 = 3;\n" +
                              "v(P) = r х d = 2 + 1 + 0 = 3;\n" +
                              "F(P) = 0 + 9 + 3 = 12.\n\n" +
                              "Помещаем элемент e1 в позицию р4\n" +
                              "Размещен 1 элемент: F(q) = 0.\n" +
                              "Неразмещенные элементы {e2, e3, e4}, свободные позиции {р1, р2, р3}.\n" +
                              "r1 = {4 3 1} и d4 = {1 1 2}; r1 x d4 =  4 + 3 + 2 = 9; \n" +
                              "w(P) =  9;\n" +
                              "r = {2 1 0} и d= {1 1 2}; v(P) = r x d = 2 + 1 + 0 = 3;\n" +
                              "F(P) = 0 + 9 + 3 = 12.\n\n" +
                              "Минимальное значение F(P) в 1 позиции\n" +
                              "Помещаем его в 1 позицию на 1 плату";
            step = new StepPlacementLog(boards, msg);
            log.Add(step);


            boardMatr[1, 1] = 2;
            msg             = "Помещаем элемент e2 в позицию р2. \n" +
                              "Размещены 2 элемента: e1 в р1, e2 в р2, F(q) = r12 d12 = 1.\n" +
                              "Неразмещенные элементы {e3, e4}, свободные позиции {р3, р4};\n" +
                              "r1 ={4 3}  и  d1 ={1 2}; r1 x d1 = 4 + 6 = 10;\n" +
                              "r2 ={2 0}  и  d2 ={1 2}; r2 x d2 = 2 + 0 = 2;\n" +
                              "w(P) = 10 + 2 = 12.\n" +
                              "r = {1} и d = {1}; v(P) = r х d = 1;\n" +
                              "F(P) = 1 + 12 + 1 = 14.\n" +
                              "Помещаем элемент e2 в позицию р3. \n" +
                              "Размещены 2 элемента: e1 в р1, e2 в р3, F(q) = r12 d13 = 1.\n" +
                              "Неразмещенные элементы {e3, e4}, свободные позиции {р2, р4};\n" +
                              "r1 ={4 3}  и  d1 ={1 2}; r1 x d1 = 4 + 6 = 10;\n" +
                              "r2 ={2 0}  и  d3 ={1 2}; r2 x d3 = 2 + 0 = 2;\n" +
                              "w(P) = 10 + 2 = 12.\n" +
                              "r = {1} и d = {1}; v(P) = r х d = 1;\n" +
                              "F(P) = 1 + 12 + 1 = 14.\n" +
                              "Помещаем элемент e2 в позицию р4. \n" +
                              "Размещены 2 элемента: e1 в р1, e2 в р4, F(q) = r12 d14 = 2.\n" +
                              "Неразмещенные элементы {e3, e4}, свободные позиции {р2, р3};\n" +
                              "r1 ={4 3}  и  d1 ={1 1}; r1 x d1 = 4 + 3 = 7;\n" +
                              "r2 ={2 0}  и  d4 ={1 1}; r2 x d4 = 2 + 0 = 2;\n" +
                              "w(P) = 7 + 2 = 9.\n" +
                              "r = {1} и d = {2}; v(P) = r х d = 2;\n" +
                              "F(P) = 1 + 12 + 1 = 13.\n" +
                              "Минимальное значение F(P) в 4 позиции\n" +
                              "Помещаем его в 4 позицию на 1 плату";
            step = new StepPlacementLog(boards, msg);
            log.Add(step);


            boardMatr[0, 1] = 3;
            msg             = "Помещаем элемент e3 в позицию р2. \n" +
                              "Размещены 3 элемента: e1 в р1, e2 в р4, e3 в р2, F(q) = r12d14 + r13d12 + r23d42 = 2 + 3 + 2 = 7.\n" +
                              "Неразмещенный элемент {e4}, свободная позиция {р3};\n" +
                              "r1 = {4} и d1 = {1}; r1 x d1 = 4;\n" +
                              "r2 = {0} и d4 = {1}; r2 x d4 = 0;\n" +
                              "r3 = {1} и d2 = {2}; r3 x d2 = 2;\n" +
                              "w(P) = 4 + 0 + 2 = 6. \n" +
                              "Неразмещенный элемент один, v(P) = 0;\n" +
                              "F(P) = 7 + 6 + 0 = 13.\n" +
                              "Помещаем элемент e3 в позицию р3. \n" +
                              "Размещены 3 элемента: e1 в р1, e2 в р4, e3 в р3, F(q) = r12d14 + r13d13 + r23d43 = 2 + 3 + 2 = 7.\n" +
                              "Неразмещенный элемент {e4}, свободная позиция {р2}; \n" +
                              "r1 = {4} и d1 = {1}; r1 x d1 = 4;\n" +
                              "r2 = {0} и d4 = {1}; r2 x d4 = 0;\n" +
                              "r3 = {1} и d3 = {2}; r3 x d3 = 2;\n" +
                              "w(P) = 4 + 0 + 2 = 6. \n" +
                              "Неразмещенный элемент один, v(P) = 0;\n" +
                              "F(P) = 7 + 6 + 0 = 13.\n" +
                              "Минимальное значение F(P) в 2 позиции\n" +
                              "Помещаем его в 2 позицию на 1 плату";
            step = new StepPlacementLog(boards, msg);
            log.Add(step);


            boardMatr[1, 0] = 4;
            msg             = "Помещаем элемент e4 в позицию р3.\n" +
                              "Размещены 4 элемента: e1 в р1, e2 в р4, e3 в р2, e4 в 3, F(q) = r12d14 + r13d12 + r23d42 + r14d13 + r24d43 + r34d23 = 2 + 3 + 2 + 4 + 0 + 2 = 13.\n" +
                              "Неразмещенного элемента нет, свободных позиций нет;\n" +
                              "w(P) = 0;\n" +
                              "Неразмещенного элемента нет, v(P) = 0;\n" +
                              "F(P) = 13 + 0 + 0 = 13.\n" +
                              "Минимальное значение F(P) в 3 позиции\n" +
                              "Помещаем его в 3 позицию на 1 плату";
            step = new StepPlacementLog(boards, msg);
            log.Add(step);

            return(log);
        }