Esempio n. 1
0
        private void Calculate()
        {
            BnBNodeData nData = new BnBNodeData(Cities); // заносим начальные данные из коллекции городов

            tmrTimer.Start();                            //запуск таймера
            _liInfo = new List <string>();

            nData.ReductedMatrix();                         // приводим матрице по столбцам и строкам
            nData.PowCalc();                                // подсчет степеней у нулевых элементов
            nData.LogMatrix();                              // вывод в логи для отладки
            _greatParentNode = new BnBNode(null, nData);    // создаем первый родительский узел с данными

            // Обход
            GoDown(_greatParentNode, null);

            liPath = FindBest(_greatParentNode, new List <string>());    // получаем лучшие пути
            // Записываем лучшие пути в отладочные данные
            _liInfo.Add("------результат------");
            foreach (string lp in liPath)
            {
                _liInfo.Add(lp);
            }

            tmrTimer.Stop();           //остановка таймера

            // Вычисление завершено
            OnFinally(new EventArgs());
            //CitiesCollection pathCities = BestPath;
            //List<CitiesCollection> pathCitiesList = BestPathList;
        }
Esempio n. 2
0
        /// <summary>
        /// Находит лучшие пути
        /// </summary>
        /// <param name="currentNode">Текущий узед</param>
        /// <param name="liPath">Накопленный путь ввиде списка</param>
        /// <returns></returns>
        private List <string> FindBest(BnBNode currentNode, List <string> liPath)
        {
            if (currentNode.Data.Length == 2)
            {
                if (currentNode.Data.SummWeight <= _dCriterialWeight)
                {
                    liPath.Add(currentNode.Index + " | " + currentNode.Data.Path.PiePath[0] + " | " + currentNode.Data.SummWeight);
                }
                return(liPath);
            }

            for (int i = 0; i < currentNode.Nodes.Count; i++)
            {
                if (currentNode.Nodes[i].Forbidden == false)
                {
                    FindBest(currentNode.Nodes[i], liPath);
                }
            }
            return(liPath);
        }
Esempio n. 3
0
 /// <summary>
 /// Обход вверх
 /// </summary>
 private void GoUp(BnBNode currentNode, BnBNode calledNode)
 {
     while (currentNode != calledNode)
     {
         //получили родителя
         BnBNode parentNode = currentNode.ParentNode;
         if (parentNode == null)
         {
             return;
         }
         BnBNode childNode = currentNode;
         for (int i = 0; i < parentNode.Nodes.Count; i++)
         {
             if (parentNode.Nodes[i] != childNode)
             {
                 if (parentNode.Nodes[i].Data.SummWeight <= _dCriterialWeight)
                 {
                     if (parentNode.Nodes[i].Viewed == false)
                     {
                         // Обход вниз для i-го ребенка
                         _stCountDown++;
                         currentNode.Viewed = true;
                         GoDown(parentNode.Nodes[i], currentNode);
                         return;
                     }
                 }
                 else
                 {
                     parentNode.Nodes[i].Forbidden = true;
                 }
             }
         }
         currentNode.Viewed = true;
         // Продолжаем функцию ОбходВверх для родителя родителя.  (поднимаемся на уровень выше)
         currentNode = currentNode.ParentNode;
     }
     return;
 }
Esempio n. 4
0
        /// <summary>
        /// Обход вниз
        /// </summary>
        /// <param name="parent">Текущий родительский узел</param>
        /// <param name="calledNode">Вызвавший узел</param>
        private void GoDown(BnBNode currentNode, BnBNode calledNode)
        {
            bool _continue = true;

            while (_continue)
            {
                // Если текущий суммарный вес больше, чем Критериальный суммарный вес
                if (currentNode.Data.SummWeight > _dCriterialWeight)
                {
                    currentNode.Forbidden = true;
                    currentNode.Viewed    = true;

                    // Запускаем функцию ОбходВверх(текущий_узел);
                    GoUp(currentNode, calledNode);
                    _continue = false;
                    break;
                }

                // Если матрица 2х2
                if (currentNode.Data.Length == 2)
                {
                    for (int i = 0; i < currentNode.Data.Length; i++)
                    {
                        for (int j = 0; j < currentNode.Data.Length; j++)
                        {
                            if (currentNode.Data.Distance[i, j].Value == 0)
                            {
                                int childI = currentNode.Data.VerIndexes[i];
                                int childJ = currentNode.Data.HorIndexes[j];

                                currentNode.Data.RecalcPath(childI, childJ);
                            }
                        }
                    }
                    _dCriterialWeight = currentNode.Data.SummWeight;
                    //currentNode.Data.LogMatrix();

                    currentNode.Viewed = true;
                    _strCountUp++;
                    // Запускаем функцию ОбходВверх(текущий_узел);
                    GoUp(currentNode, calledNode);
                    _continue = false;
                    break;
                }

                //currentNode.Data.LogMatrix();
                if (currentNode.Viewed == false)
                {
                    double dMaxPowValue = currentNode.Data.GetMaxPowValue();
                    for (int i = 0; i < currentNode.Data.Length; i++)
                    {
                        for (int j = 0; j < currentNode.Data.Length; j++)
                        {
                            if (currentNode.Data.Distance[i, j].Pow == dMaxPowValue)
                            {
                                // Пересечение с максимальным значением степени

                                int childI = currentNode.Data.VerIndexes[i];
                                int childJ = currentNode.Data.HorIndexes[j];

                                // Берется дуга i,j
                                BnBNodeData childDataFirst = new BnBNodeData(currentNode.Data, i, j);
                                BnBNode     childNodeFirst = new BnBNode(currentNode, childDataFirst);
                                childDataFirst.RecalcPath(childI, childJ);               // добавляем дугу в маршрут и исключаем закольцованность
                                childDataFirst.ReductedMatrix();                         // приведение матрицы
                                childDataFirst.PowCalc();                                // подсчет степеней матрицы
                                //childDataFirst.LogMatrix();

                                // Не берется дуга i,j
                                BnBNodeData childDataSecond = new BnBNodeData(currentNode.Data);
                                BnBNode     childNodeSecond = new BnBNode(currentNode, childDataSecond);
                                childDataSecond.RemoveLoopback(childI, childJ);
                                childDataSecond.RemoveLoopback(childJ, childI);
                                childDataSecond.ReductedMatrix();
                                childDataSecond.PowCalc();
                                //childDataSecond.LogMatrix();

                                currentNode.Nodes.Add(childNodeFirst);
                                currentNode.Nodes.Add(childNodeSecond);

                                // служебные данные
                                _lNodeCount += 2;       // количество узлов в дереве
                                _liInfo.Add(" ");
                                _liInfo.Add(String.Format("№: {0:00000}\tParent:{1:00000}", childNodeFirst.Index, childNodeFirst.ParentNode.Index));
                                _liInfo.Add(String.Format("Размерность: {0:#}x{1:#}", childNodeFirst.Data.Length, childNodeFirst.Data.Length));
                                _liInfo.Add(String.Format("Длина пути: {0:000.00}", childNodeFirst.Data.SummWeight));
                                //_liInfo.AddRange( childNodeFirst.Data.ListInfo() );
                                _liInfo.Add(" ");
                                _liInfo.Add(String.Format("№: {0:00000}\tParent:{1:00000}", childNodeSecond.Index, childNodeSecond.ParentNode.Index));
                                _liInfo.Add(String.Format("Размерность: {0:#}x{1:#}", childNodeSecond.Data.Length, childNodeSecond.Data.Length));
                                _liInfo.Add(String.Format("Длина пути: {0:000.00}", childNodeSecond.Data.SummWeight));
                                //_liInfo.AddRange( childNodeSecond.Data.ListInfo() );

                                break;
                            }
                        }
                    }

                    // Находим минимальный суммарный вес у потомков
                    double minSummWeight = double.MaxValue;
                    for (int i = 0; i < currentNode.Nodes.Count; i++)
                    {
                        if (currentNode.Nodes[i].Data.SummWeight < minSummWeight)
                        {
                            minSummWeight = currentNode.Nodes[i].Data.SummWeight;
                        }
                    }
                    // Запускаем функцию ОбходВниз для первого дочернего элемента с минимальным суммарным весом
                    for (int i = 0; i < currentNode.Nodes.Count; i++)
                    {
                        if (currentNode.Nodes[i].Data.SummWeight == minSummWeight)
                        {
                            _stCountDown++;
                            //GoDown(currentNode.Nodes[i]);
                            currentNode = currentNode.Nodes[i];
                            continue;
                        }
                    }
                }
            }
            return;
        }