2017-02-08 23 views
6

Рассмотрим ориентированный граф, который проходит от первого узла 1 до некоторых конечных узлов (у которых больше нет исходящих ребер). Каждое ребро в графе имеет связанную с ним вероятность. Суммируя вероятности, чтобы каждый возможный путь ко всем возможным конечным узлам возвращался 1. (Это означает, что в конечном итоге мы сможем получить один из конечных узлов.)Направленный граф вероятности - алгоритм сокращения циклов?

Проблема была бы простой, если бы циклы на графике не существовали. К сожалению, на графике могут возникать довольно запутанные петли, которые могут проходить бесконечно много раз (вероятность, разумеется, мультипликативно с каждым обходом цикла).

Есть ли общий алгоритм для нахождения вероятностей для каждого конечного узла?

Особенно неприятный пример:

можно представить края в виде матрицы (вероятность для перехода из строки (узла) x к строке (узел) y находится в записи (x,y))

{{0, 1/2, 0, 1/14, 1/14, 0, 5/14}, 
{0, 0, 1/9, 1/2, 0, 7/18, 0}, 
{1/8, 7/16, 0, 3/16, 1/8, 0, 1/8}, 
{0, 1, 0, 0, 0, 0, 0}, 
{0, 0, 0, 0, 0, 0, 0}, 
{0, 0, 0, 0, 0, 0, 0}, 
{0, 0, 0, 0, 0, 0, 0}} 

Или как ориентированный граф:

enter image description here

в качестве исходного узла 1 синий, конечные узлы 5,6,7 - зеленые. Все ребра помечены вероятностью пересечения их, когда они начинаются с узла, на котором они происходят.

Это имеет восемь различных путей от исходного узла 1 до конечных узлов:

{{1/14, {1, 5}}, {5/14, {1, 7}}, {7/36, {1, 2, 6}}, 
{1/144, {1, 2, 3, 5}}, {1/144, {1, 2, 3, 7}}, 
{1/36, {1, 4, 2, 6}}, {1/1008, {1, 4, 2, 3, 5}}, {1/1008, {1, 4, 2, 3, 7}}} 

(Обозначения для каждого пути есть {вероятность того, последовательность узлов посетили})

И есть пять различных петли:

{{1/144, {2, 3, 1}}, {7/144, {3, 2}}, {1/2, {4, 2}}, 
{1/48, {3, 4, 2}}, {1/1008, {4, 2, 3, 1}}} 

(Обозначение петель {вероятности для прохождения цикла один раз, последовательность узлов посетили}).

Если только эти циклы могут быть разрешены для получения эффективного дерева, подобного графу, проблема будет решена.

Любой намек на то, как справиться с этим?

Я знаком с Java, C++ и C, поэтому предложения на этих языках предпочтительны.

+0

Вы избегаете бесконечных циклов, блокируя уже посещенный узел. Ничего неприятного в этом нет, используете ли вы рекурсивное решение или что-то вроде алгоритма Дейкстры. –

+0

@WeatherVane Вы говорите, что восемь разных путей, перечисленных мной, уже являются окончательным результатом? Я считаю, что на самом деле допускается бесконечное число циклов, так как оно становится своего рода геометрическим рядом в вероятности прохождения цикла (в простейшем случае из 1 цикла), который сходится к конечному числу. Моя проблема в том, что есть много циклов и несколько пересекающихся. Тогда я не вижу, как обобщить геометрический ряд. – Kagaratsch

+0

Вы спросили, как удалить циклы. –

ответ

1

Я не эксперт в области цепей Маркова, и, хотя я думаю, что это, вероятно, что алгоритмы известны для вида проблема, которую вы представляете, мне трудно найти их.

Если никакая помощь не поступает из этого направления, вы можете рассмотреть вопрос о переводе своих собственных. Я вижу по крайней мере два разных подхода:

  1. Моделирование.

Проверьте, как состояние системы изменяется с течением времени, начиная с системой в состоянии 1 с вероятностью 100%, и выполняя множество итераций, в котором вы применить ваши вероятности перехода для вычисления вероятности состояния, полученной после приема шаг. Если по крайней мере один конечный («поглощающий») узел может быть достигнут (при ненулевой вероятности) от каждого узла, то на достаточно больших шагах вероятность того, что система находится в чем-либо, кроме конечного состояния, будет асимптотически уменьшаться до нуля. Вы можете оценить вероятность того, что система закончится в конечном состоянии S как вероятность того, что она находится в состоянии S после n шагов с верхней границей ошибки в этой оценке, заданной вероятностью того, что система находится в не- окончательное состояние после n шагов.

С практической точки зрения, это то же самое вычисление Трап, где Тр является вашей вероятность перехода матрицы, дополненной с самими-ребрами с вероятностью 100% для всех конечных состояний.

  1. Точные вычисления.

Рассмотрите график G, который вы описываете. Даны две вершины я и е, таким образом, что есть по крайней мере один путь от я к ф и е не имеет других самостоятельных краев исходящих ребер, можно разбить на пути от я до f в классы, характеризующиеся количеством повторных посещений i до достижения f.Там может быть бесконечное число таких классов, которые я назначит С если (п), где п представляет собой число раз путей в C если (n) revisit node i. В частности, С II (0) содержит все простые петли в G, которые содержат я (разъяснения: а также другие пути).

Полная вероятность заканчивающийся в узле е при условии, что система пересекает граф, начиная с узла я задается

Pr (ф | я, G) = Pr (С если (0) | G) + Рг (С если (1) | G) + Pr (C если (2) | G) ...

Теперь заметим, что если п> 0, то каждый путь в C если (п) имеет форму объединения двух путей гр и т, где с принадлежит с II (п -1) и т принадлежит С если (0). То есть, с это путь, который начинается в узле я и заканчивается в узле я, проходя через яп -1 раз между ними, и т путь из я к f, который не проходит через i.Мы можем использовать это, чтобы переписать нашу вероятностную формулу:

Pr (е | я, G) = Pr (C если (0) | G) + Pr (C II (0) | G) * Пр (С если (0) | G) + Pr (C II (1) | G) * Pr (C если (0) | G) + ...

Но обратите внимание, что каждый путь в C II (п) представляет собой композицию из п + 1 путей, принадлежащих к C II (0). Отсюда следует, что Pr (C II (п) | G) = Pr (C II (0) | G) п +1, так что мы получаем

Pr (е | я) = Pr (C, если (0) | G) + Рг (С II (0) | G) * Пр (С если (0) | G) + Рг (С б (0) | G) * Pr (C если (0) | G) + ...

А теперь, немного алгебра дает нам

Pr (е | я, G) - Pr (C если (0) | G) = Pr (С II (0) | G) * Пр (е | я, G)

, которые мы можем решить для Pr (f | я, G), чтобы получить

Pr (е | я, G) = Pr (C если (0) | G)/(1 - Pr (C II (0) | G))

Мы, таким образом, сводит задачу к одному с точки зрения путей, которые не возвращают к исходному узлу, за исключением, возможно, в качестве конечного узла. Они не исключают путей, которые имеют петли, которые не включают начальный узел, но мы можем, тем не менее, переписать эту проблему в терминах нескольких экземпляров исходной задачи, вычисленных на подграфе исходного графа.

В частности, пусть S (я, G), множество наследников вершины я в графе G - то есть, множество вершин с таким образом, что существует ребро из я к с в G, и пусть Х (о, я) подграф графа G, образованный удалением всех ребер, которые начинаются на я. Кроме того, пусть p is - вероятность, связанная с ребром (i, s) в G.

Pr (С если (0) | G) = сумма по с в S (я, G) от р является * Пр (е | s, X (G, я))

другими словами, вероятность того, достижения п из I через G без пересмотра я между ними есть сумма по всем наследникам я продукта вероятности достижения с от я в одну стадии с вероятностью достигнув f от s через G без пересечения любых границ исходящих от i. Это относится ко всем f в G, включая i.

Теперь заметим, что S (я, G) и все р является являются knowns, и что задача вычисления Pr (ф | s, X (G, i)) - это новый, строго меньший экземпляр исходной проблемы. Таким образом, это вычисление может быть выполнено рекурсивно, и такая рекурсия будет завершена. Тем не менее, может потребоваться много времени, если ваш график будет сложным, и похоже, что наивная реализация этого рекурсивного подхода будет экспоненциально масштабироваться по количеству узлов. Есть способы ускорить вычисление в обмен на более высокое использование памяти (т. Е. Memoization).


Возможны и другие возможности. Например, я подозреваю, что подход к динамическому программированию снизу вверх, но мне не удалось убедить себя, что циклы на графике не представляют непреодолимой проблемы.

+0

Я считаю, что запоминание сделает его почти линейным (полиномиально точно). Ты обалденный! Спасибо. – Kagaratsch

+1

@FauChristian, вопрос, который задает вопрос, - это «общий алгоритм **, чтобы найти вероятности для достижения каждого из конечных узлов» (выделено мной), и этот ответ дает два. Если вы не считаете, что это намеки на реализацию, тогда подсказки для реализации действительно * не *, о чем спрашивает вопрос. Конечно, ОП, похоже, полностью удовлетворен тем, что этот ответ отвечает на вопрос. –

+0

Этот ответ полностью разобрал проблему. Ничего не осталось добавить. Просто возьмите его и реализуйте в буквальном смысле, и он будет работать. – Kagaratsch

1

Я понимаю это как следующая проблема:

Учитывая начальное распределение, чтобы быть на каждом узле в качестве вектора Ь и матрица A, которая хранит вероятность того, чтобы перейти от узла я к узлу J в каждом временном шаге, несколько напоминающий матрицу смежности.

Затем распределение b_1 после однократного шага A x b. Распределение b_2 после двух временных шагов: A x b_1. Аналогично, распределение b_n равно A^n x b.

Для приближения b_infinite, мы можем сделать следующее:

Vector final_probability(Matrix A, Vector b, 
    Function Vector x Vector -> Scalar distance, Scalar threshold){ 
    b_old = b 
    b_current = A x b 
    while(distance(b_old,b_current) < threshold){ 
     b_old = b_current 
     b_current = A x b_current 
    } 
    return b_current 
} 

(я использовал математические имена переменных для convencience)

Другими словами, мы предполагаем, что последовательность распределений сходится хорошо после данный порог. Возможно, это не так, но обычно будет работать.

Возможно, вы захотите добавить к нему максимальное количество итераций.

Euclidean distance должно хорошо работать как расстояние.

(При этом используется понятие Markov Chain, но в большей степени прагматического раствора)

4

Проблема Осветление

ввода данных представляет собой набор из т строк из п столбцов вероятностей, по существу т на п матрицы, где т = п = число вершин на ориентированного графа. Строки являются краевыми источниками, а столбцы - пограничными. Мы будем на основании упоминания циклов в вопросе, что граф является циклическим, что по крайней мере один цикл существует в графе.

Определим стартовую вершину как s. Давайте также определим терминальную вершину как вершину, для которой нет выходящих ребер, а множество из них задано T с размером z. Поэтому мы имеем z наборов маршрутов от s до вершины в T, а размеры множества могут быть бесконечными из-за циклов . В таком сценарии нельзя сделать вывод, что конечная вершина будет достигнута на сколь угодно большом числе шагов.

Во входных данных вероятности для строк, которые соответствуют вершинам, не входящим в T, нормированы на общую величину до 1,0. Будем считать свойство Маркова, что вероятности в каждой вершине не меняются со временем. Это исключает использование вероятности для определения приоритетов маршрутов в графическом поиске .

Конечные математические тексты иногда называют пример проблемы, подобные этому вопросу, как Drunken блуждания подчеркнуть тот факт, что ходунки забывает прошлое, со ссылкой на памяти свободной природы марковских цепей.

Применение Вероятность Маршруты

Вероятность прибытия в терминальной вершине может быть выражена в виде бесконечной серии суммы произведений.

Р т = Пт с -> ∞ Σ ∏ Р I, J,

, где s является индексом шаг, т является индексом конечной вершиной, я ∈ [1. м.] и J ∈ [1 .. п]

Снижение

Когда два или более цикла пересекаются (разделяя одну или несколько вершин), анализ осложняется бесконечным набором шаблонов, связанных с ними. По-видимому, после некоторого анализа и обзора relevant academic work, что получение точного набора вероятностей прибытия конечных вершин с помощью современных математических инструментов лучше всего выполнить с помощью сходящегося алгоритма.

Возможны несколько первоначальных сокращений.

  1. Первое соображение состоит в том, чтобы перечислить конечную вершину, что легко, так как соответствующие строки имеют вероятности нуля.

  2. Следующее соображение состоит в том, чтобы отличить любые дальнейшие сокращения от того, что академическая литература называет неприводимыми субграфами. Первый алгоритм глубины глубины запоминает, какие вершины уже были посещены при построении потенциального маршрута, поэтому его можно легко модифицировать, чтобы определить, какие вершины задействованы в циклах. Однако рекомендуется использовать существующие проверенные, проверенные коллегами библиотеки графов, чтобы идентифицировать и характеризовать субграфы как неприводимые.

Математическое сокращение неприводимых частей графика может быть или не быть правдоподобным. Рассмотрим начальную вершину A и единственную конечную вершину B в графе, представленную в виде {A-> C, C-> A, A-> D, D-> A, C-> D, D-> C, C-> B, D-> B}.

Хотя можно уменьшить график до вероятностных отношений, отсутствующих в циклах через вершину А, вершина А не может быть удалена для дальнейшего восстановления без изменения вероятностей вершин, выходящих из С и D, или допускающих как общие суммы вероятностей ребер, выходящих из С и D меньше 1,0.

конвергентной Ширина первого Прослеживание

широта первого обхода, который игнорирует пересматривает и позволяет циклы могут итерации шаг индекс s, а не к некоторым фиксированному с макс, но в какую-то достаточно стабильную и точную точку в сходящемся тренде , Этот подход особенно называется, если циклы перекрываются, создавая бифуркации в более простой периодичности, вызванной одним циклом.

Σ Р сΔ с.

Для создания разумной сходимости в ы возрастает, необходимо определить требуемую точность в качестве критериев для завершения алгоритма сходимости и метрик для измерения точности, глядя на долгосрочные тенденциях в результатах на все терминальные вершины. Возможно, важно предоставить критерии, в которых сумма вероятностей конечных вершин близка к единице в сочетании с метрикой сходимости тренда, как как проверка на соответствие, так и критерии точности. Практически могут потребоваться четыре критерия конвергенции .

  1. на терминал вершины вероятности тенденция конвергенции дельту
  2. Средняя тенденция вероятности сходимость дельта
  3. Сходимости полной вероятности на единстве
  4. Общего числа шагов (с колпачком глубины для практических вычислений причин)

Даже за этими четырьмя программами может потребоваться ловушка для прерывания, которая позволяет писать и последующую проверку вывода после долгого ожидания без satis сражаясь со всеми четырьмя критериями.

Пример Цикл Устойчива Глубина первого алгоритм

Существуют более эффективные алгоритмы, чем следующие один, но это довольно приемлемо, он компилирует без предупреждения с C++ -Wall, и она производит желаемый результат для всех конечные и законные ориентированные графы и возможные вершины и конечные вершины . Легко загрузить матрицу в форме, заданной в вопросе, используя метод addEdge .

#include <iostream> 
#include <list> 

class DirectedGraph { 

    private: 
     int miNodes; 
     std::list<int> * mnpEdges; 
     bool * mpVisitedFlags; 

    private: 
     void initAlreadyVisited() { 
      for (int i = 0; i < miNodes; ++ i) 
       mpVisitedFlags[i] = false; 
     } 

     void recurse(int iCurrent, int iDestination, 
       int route[], int index, 
       std::list<std::list<int> *> * pnai) { 

      mpVisitedFlags[iCurrent] = true; 
      route[index ++] = iCurrent; 

      if (iCurrent == iDestination) { 
       auto pni = new std::list<int>; 
       for (int i = 0; i < index; ++ i) 
        pni->push_back(route[i]); 
       pnai->push_back(pni); 

      } else { 
       auto it = mnpEdges[iCurrent].begin(); 
       auto itBeyond = mnpEdges[iCurrent].end(); 
       while (it != itBeyond) { 
        if (! mpVisitedFlags[* it]) 
         recurse(* it, iDestination, 
           route, index, pnai); 
        ++ it; 
       } 
      } 

      -- index; 
      mpVisitedFlags[iCurrent] = false; 
     } 

    public: 
     DirectedGraph(int iNodes) { 
      miNodes = iNodes; 
      mnpEdges = new std::list<int>[iNodes]; 
      mpVisitedFlags = new bool[iNodes]; 
     } 

     ~DirectedGraph() { 
      delete mpVisitedFlags; 
     } 

     void addEdge(int u, int v) { 
      mnpEdges[u].push_back(v); 
     } 

     std::list<std::list<int> *> * findRoutes(int iStart, 
       int iDestination) { 
      initAlreadyVisited(); 
      auto route = new int[miNodes]; 
      auto pnpi = new std::list<std::list<int> *>(); 
      recurse(iStart, iDestination, route, 0, pnpi); 
      delete route; 
      return pnpi; 
     } 
}; 

int main() { 

    DirectedGraph dg(5); 

    dg.addEdge(0, 1); 
    dg.addEdge(0, 2); 
    dg.addEdge(0, 3); 
    dg.addEdge(1, 3); 
    dg.addEdge(1, 4); 
    dg.addEdge(2, 0); 
    dg.addEdge(2, 1); 
    dg.addEdge(4, 1); 
    dg.addEdge(4, 3); 

    int startingNode = 2; 
    int destinationNode = 3; 

    auto pnai = dg.findRoutes(startingNode, destinationNode); 

    std::cout 
      << "Unique routes from " 
      << startingNode 
      << " to " 
      << destinationNode 
      << std::endl 
      << std::endl; 

    bool bFirst; 
    std::list<int> * pi; 
    auto it = pnai->begin(); 
    auto itBeyond = pnai->end(); 
    std::list<int>::iterator itInner; 
    std::list<int>::iterator itInnerBeyond; 
    while (it != itBeyond) { 
     bFirst = true; 
     pi = * it ++; 
     itInner = pi->begin(); 
     itInnerBeyond = pi->end(); 
     while (itInner != itInnerBeyond) { 
      if (bFirst) 
       bFirst = false; 
      else 
       std::cout << ' '; 
      std::cout << (* itInner ++); 
     } 
     std::cout << std::endl; 
     delete pi; 
    } 

    delete pnai; 

    return 0; 
} 

Примечание

[1] При ненадлежащем обращении циклов в алгоритме ориентированного графа будут висеть в бесконечном цикле. (Обратите внимание на тривиальный случай, когда количество маршрутов от A до B для ориентированного графа, представленного как {A-> B, B-> A}, бесконечно.)

[2] Вероятности иногда используются для уменьшения CPU циклическая стоимость поиска. Вероятности, в этой стратегии, являются входными значениями мета-правил в очереди приоритетов, чтобы уменьшить вычислительную проблему очень утомительных поисков (даже для компьютера). Ранняя литература в производственных системах назвала экспоненциальный характер неуправляемых крупных поисков комбинационных взрывов.

[3] Это может быть практически необходимо, чтобы обнаружить ширину первой вероятности тенденции в каждой вершине и указать удовлетворительную сходимость в терминах четырех критериев

  1. Δ (Σ ∏ Р) т < = Δ макс & forall; т
  2. Σ т = 0Т Δ (Σ ∏ Р) т/Т = < Δ просп
  3. | Σ Σ ∏ P - 1 | < = и макс, где и максимальное допустимое отклонение от единицы на сумму финальных вероятностей
  4. сек < S макс

[4] При условии, имеется достаточное количество вычислительных ресурсов, доступных для поддержки структуры данных и достаточное время для получения ответа на заданную скорость вычислительной системы.

[5] Вы можете загрузить DirectedGraph dg (7) с входными данными, используя два цикла, вложенные в итерацию по строкам и столбцам, перечисленным в вопросе. Тело внутреннего цикла было бы просто добавлением условного края.

if (prob != 0) dg.addEdge(i, j); 

Переменный проб является Р т, п. Существование маршрута связано только с нулевым/ненулевым статусом.

+0

Я закончил тем, что сделал точное повторение для обходов цикла. Рекурсивный алгоритм с запоминанием выполняется очень быстро для размеров, например, 10 государственных систем, даже при очень низких ресурсах. Вы проверили свой код на примере в моем вопросе? Может быть, мы сможем сравнить, согласуются ли конечные вероятности состояния. – Kagaratsch

+0

'/' эвристический для деления. В принципе, элементы этой матрицы являются рациональными числами. Каждая строка добавляет до 1 (поэтому вероятность перехода в какое-либо другое состояние (или пребывание у оригинала) составляет 100%). Строки со всеми нулями являются конечными состояниями (вероятность оставить их равна 0%). Идентификатор узла - это номер строки. (Первая строка: id = 0, вторая строка: id = 1 и т. Д.) Соответственно, номер столбца является идентификатором узла назначения. Когда в столбце есть ненулевая вероятность, возможен переход к этому узлу из соответствующей строки (стартового узла). – Kagaratsch

+0

Спасибо! Я посмотрю поближе. – Kagaratsch