Example #1
0
        /// <summary>
        /// Создание пошагового метода ветвей и границ
        /// </summary>
        /// <param name="graph">орг. граф</param>
        public BranchAndBound(Digraph graph)
        {
            // метод ветвей и границ для указанного графа
            Graph = graph;

            // переход в следующее состояние
            next = IterationState.Start;

            // создание пустого маршрута коммивояжера
            TsPath = new Digraph.Path(Graph);

            if (Graph.CountVertex() == 0)
            {
                // пустой маршрут
                // окончание метода
                next = IterationState.Stop;
            }
            else if (Graph.CountVertex() == 1)
            {
                // маршрут из одной вершины
                TsPath.Append(new Digraph.Edge(0, 0, 0));
                // окончание метода
                next = IterationState.Stop;
            }
            else if (Graph.CountVertex() == 2)
            {
                // маршрут из двух вершин
                TsPath.Append(new Digraph.Edge(0, 1, Graph[0, 1]));
                TsPath.Append(new Digraph.Edge(1, 0, Graph[1, 0]));
                // окончание метода
                next = IterationState.Stop;
            }
        }
Example #2
0
            /// <summary>
            /// Создание маршрута на основе ветвления 
            /// </summary>
            /// <param name="branch">ветвление</param>
            /// <returns>маршрут</returns>
            public Digraph.Path CreatePathFromBranch(Branch branch)
            {
                var edges = GetEdgesBranching(branch);

                var path = new Digraph.Path(Graph);

                foreach (var e in edges)
                    if (e.Begin >= 0 && e.End >= 0)
                        path.Append(e);

                return path;
            }
Example #3
0
        /// <summary>
        /// Нахождение маршрута коммивояжера
        /// </summary>
        /// <param name="graph">ограф. граф</param>
        /// <returns>маршрут коммивояжера</returns>
        public static Digraph.Path Tsp(Digraph graph)
        {
            // маршрут коммивояжера
            var TsPath = new Digraph.Path(graph);

            // если граф пуст
            if (graph.CountVertex() == 0)
            {
                // пустой маршрут
                return TsPath;
            }
            // если граф имеет одну вершину
            else if (graph.CountVertex() == 1)
            {
                TsPath.Append(new Digraph.Edge(0, 0, 0));
                // маршрут для одной вершины
                return TsPath;
            }
            // если граф имеет две вершины
            else if (graph.CountVertex() == 2)
            {
                TsPath.Append(new Digraph.Edge(0, 1, graph[0, 1]));
                TsPath.Append(new Digraph.Edge(1, 0, graph[1, 0]));
                // маршрут для двух вершин
                return TsPath;
            }

            /// Создания неперекающихся множеств вершин в графе,
            /// для определения и исключения подмаршрутов графа
            var dsu = new Dsu(graph.CountVertex());

            // минимальное ветвление
            var minBranch = new Branch(float.PositiveInfinity, null);

            /// Получение исходной матрицы смежности данного графа
            var matrix = new ReductionMatrix(graph.Adjacency);

            /// Создание корня и дерева ветвления
            var parentBranch = new Branch(matrix.Reduce(), null);
            var tree = new TreeBranch(graph, parentBranch);

            for (; ; )
            {
                // ребра с нулевой стоимостью
                var zeroEdges = new List<Digraph.Edge>();
                // Получение всех ребер и соответсвующих штрафов
                for (int i = 0; i < matrix.Size; i++)
                    for (int j = 0; j < matrix.Size; j++)
                        if (matrix[i, j] == 0)
                            zeroEdges.Add(new Digraph.Edge(i, j, matrix.MinInRow(i, j) + matrix.MinInColumn(j, i)));

                // если нет ребер ветвления - нет маршрута коммивояжера
                if (zeroEdges.Count == 0)
                    return new Digraph.Path(graph);

                /// Определение ребра ветвления - ребра с максимальным штрафом
                var branchingEdge = zeroEdges.OrderByDescending(e => e.Cost).ToList().First();

                /// Процесс ветления - не включая данное ребро
                var leftBranch = new Branch(parentBranch.LowerBound + branchingEdge.Cost,
                    new Digraph.Edge(-branchingEdge.Begin, -branchingEdge.End, float.PositiveInfinity));
                // добавление ветвления в дерево
                tree.Add(parentBranch, Branch.Direction.Left, leftBranch);

                /// Процесс ветления - включая данное ребро
                ExcludeSubRoute(matrix, dsu, branchingEdge);

                var rightBranch = new Branch(parentBranch.LowerBound + matrix.Reduce(),
                    new Digraph.Edge(branchingEdge.Begin, branchingEdge.End, graph[branchingEdge.Begin, branchingEdge.End]));
                // добавление ветвления в дерево
                tree.Add(parentBranch, Branch.Direction.Right, rightBranch);

                /// Проверка на достаточность размера матрцицы
                if (matrix.RealSize == 2)
                {
                    // новый родитель
                    parentBranch = rightBranch;
                    /// Добавление оставщихся ребер в дерево ветвлений
                    for (int i = 0; i < matrix.Size; i++)
                        for (int j = 0; j < matrix.Size; j++)
                            if (matrix[i, j] == 0)
                            {
                                // новый потомок
                                rightBranch = new Branch(parentBranch.LowerBound, new Digraph.Edge(i, j, graph[i, j]));
                                tree.Add(parentBranch, Branch.Direction.Right, rightBranch);
                                // потомок теперь родитель
                                parentBranch = rightBranch;
                            }

                    /// Определение нового минимального ветвления
                    if (parentBranch.LowerBound < minBranch.LowerBound)
                        minBranch = parentBranch;
                }

                /// Выбор новой родительской вершины из еще не подвергшихся ветвлению
                parentBranch = tree.GetNotGoBranches().OrderBy(b => b.LowerBound).ToList().First();

                /// Проверка на нахождения минимального ветвления и остановки
                if (minBranch.LowerBound <= parentBranch.LowerBound)
                    break;

                /// Корректировка матрицы для данного ветвления и редуцирование
                if (parentBranch != rightBranch)
                {
                    // новые непересекающиеся множества вершин
                    dsu = new Dsu(graph.CountVertex());
                    // исходная редуцированная матрица
                    matrix = new ReductionMatrix(graph.Adjacency);
                    // получение текущих вершин для данного ветвления
                    var currentPath = tree.GetEdgesBranching(parentBranch);

                    // исключение всех подмаршрутов
                    foreach (var e in currentPath)
                        ExcludeSubRoute(matrix, dsu, e);

                    // редуцирование матрицы
                    matrix.Reduce();
                }
            }

            // формирование маршрута коммивояжера
            TsPath = tree.CreatePathFromBranch(minBranch);

            return TsPath;
        }