Dr *_*hil 3 algorithm graph probability fractals fractions
假设有一个游戏,每一步都有可能的路径,具体取决于掷出的花式骰子。根据结果,可能会向前、向后转换或停留在一个地方。最终(即使在无限次抛出之后)该图会导致最终状态。每条边都用概率 加权。
对于没有循环的情况,如果我从同一个顶点(单元)开始,我可以简单地求和+相乘并重新标准化每个结果的概率。
但是,如果我有循环,它就会开始变得混乱。例如,假设每条边的概率相同:
start0
/\ ^
/ \ |
end1 tr2
/
end2
Run Code Online (Sandbox Code Playgroud)
该图从start0开始,有 50% 的机会在end1处终止或过渡到tr2。从tr2开始,再次有 50% 的机会在end2处终止或返回到start0。
我如何计算到达每个站点end1和end2 的总概率。如果我尝试使用这样的收敛级数:
pEnd1=1/2 + 1/2*1/2+1/8+.. ->lim->1。这是没有意义的,因为end2没有得到任何概率。显然我在那里有一个错误。
所以我的问题是,如果我有每个边的概率但可能有循环,我如何计算到达最终节点的概率。
示例 1) 带循环的简单分叉 所有边的概率为 50%
start0-> p=50% ->end1
start0-> p=50% ->tr1
tr2-> p=50% ->start0
tr2-> p=50% ->end2
Run Code Online (Sandbox Code Playgroud)
示例 2) 更多循环
start0-> p=1/3 ->e1
start0-> p=1/3 ->tr1
start0-> p=1/3 ->start0
tr1-> p=1/3 ->tr2
tr1-> p=2/3 ->start0
tr2-> p=7/9 ->start0
tr2-> p=2/9 ->end2
Run Code Online (Sandbox Code Playgroud)
示例 3 ) - 退化测试用例 - 因为所有路径都以e1结束- 它最终应该有 100% 的概率
start0-> p=1/3 ->e1
start0-> p=2/3 ->tr1
tr1-> p=3/4 ->start0
tr2-> p=1/4 ->e1
Run Code Online (Sandbox Code Playgroud)
这实际上并不是一个编程问题,尽管您可以编写一个模拟并执行 100000 次来查看分布情况。
\n你写了:
\n\n\npEnd1=1/2 + 1/2*1/2+1/8+.. ->lim->1。这是没有意义的,因为 end2 没有得到任何概率。显然我在那里有一个错误。
\n
确实,有一个错误。您没有考虑从 tr2 到 start0 的概率 (50%)。路径循环一次到 start0 然后在 end1 结束的概率为 1/2(前往 tr2)* 1/2(返回 start0)* 1/2(前往 end1)。当以 end1 结束时,决策数量(50%)总是奇数。即使在end2结束时也是如此。所以公式是:
\npEnd1 = 2 -1 + 2 -3 + 2 -5 + ... -> lim = 2/3
\npEnd2 = 2 -2 + 2 -4 + 2 -6 + ... -> lim = 1/3
\n为了使这个问题成为一个编程问题,下面是用 JavaScript 进行的模拟:
\nfunction run(transitions, state) {\n while (transitions[state][state] != 1) { // not in sink\n let probs = transitions[state];\n let rnd = Math.random(); // in range [0, 1)\n for (let i = 0; i < probs.length; i++) {\n rnd -= probs[i];\n if (rnd < 0) {\n state = i; // transition\n break;\n }\n }\n }\n return state;\n}\n\n// Define graph\nlet names = ["start0", "end1", "tr2", "end2"]\nlet transitions = [\n [0.0, 0.5, 0.5, 0.0],\n [0.0, 1.0, 0.0, 0.0], // sink\n [0.5, 0.0, 0.0, 0.5],\n [0.0, 0.0, 0.0, 1.0] // sink\n];\n\n// Start sampling\nlet numResults = [0, 0, 0, 0];\nlet numSamples = 0;\nsetInterval(function () {\n let endstate = run(transitions, 0);\n numSamples++;\n numResults[endstate]++;\n document.querySelector("#" + names[endstate]).textContent = (100 * numResults[endstate] / numSamples).toFixed(4) + "%";\n}, 1);Run Code Online (Sandbox Code Playgroud)\r\n<div>Arriving in end1: <span id="end1"></span></div>\n<div>Arriving in end2: <span id="end2"></span></div>Run Code Online (Sandbox Code Playgroud)\r\n您可能还想阅读有关吸收马尔可夫链的内容。由此我们得知“吸收概率”矩阵 B 可以用以下公式计算:
\nB = NR
\n在哪里:
\n下面是一个脚本(包括相关的矩阵函数),用于计算您所描述的示例问题的 B:
\n// Probabilities to go from one non-final state to another\nlet Q = [\n [0.0, 0.5], // from start0 to [start0, tr2]\n [0.5, 0.0] // from tr2 to [tr2, start0]\n];\n// Probabilities to go from one non-final state to a final one\nlet R = [\n [0.5, 0.0], // from start0 to [end1, end2]\n [0.0, 0.5] // from tr2 to [end1, end2]\n];\n// See https://en.wikipedia.org/wiki/Absorbing_Markov_chain#Absorbing_probabilities\nlet N = inversed(sum(identity(Q.length), scalarProduct(Q, -1)));\nlet B = product(N, R);\nconsole.log("B = (I-Q)\xe2\x81\xbb\xc2\xb9R:\\n" + str(B));\n\n// Generic matrix utility functions:\n// cofactor is copy of given matrix without given column and given row \nfunction cofactor(a, y, x) {\n return a.slice(0, y).concat(a.slice(y+1)).map(row => row.slice(0, x).concat(row.slice(x+1)));\n} \n\nfunction determinant(a) {\n return a.length == 1 ? a[0][0] : a.reduceRight((sum, row, y) =>\n a[y][0] * determinant(cofactor(a, y, 0)) - sum\n , 0);\n} \n\nfunction adjoint(a) {\n return a.length == 1 ? [[1]] : transposed(a.map((row, y) => \n row.map((_, x) => ((x + y) % 2 ? -1 : 1) * determinant(cofactor(a, y, x)))\n ));\n} \n\nfunction transposed(a) {\n return a[0].map((_, x) => a.map((_, y) => a[y][x]));\n}\n\nfunction scalarProduct(a, coeff) {\n return a.map((row, y) => row.map((val, x) => val * coeff));\n}\n\nfunction inversed(a) {\n return scalarProduct(adjoint(a), 1 / determinant(a));\n}\n\nfunction product(a, b) {\n return a.map((rowa) =>\n b[0].map((_, x) =>\n b.reduce((sum, rowb, z) =>\n sum + rowa[z] * rowb[x]\n , 0)\n )\n );\n}\n\nfunction sum(a, b) {\n return a.map((row, y) => row.map((val, x) => val + b[y][x]));\n}\n\nfunction identity(length) {\n return Array.from({length}, (_, y) => \n Array.from({length}, (_, x) => +(y == x))\n );\n}\n\nfunction str(a) {\n return a.map(row => JSON.stringify(row)).join("\\n");\n}Run Code Online (Sandbox Code Playgroud)\r\n输出是:
\n[\n [2/3, 1/3] // probabilities when starting in start0 and ending in [end1, end2]\n [1/3, 2/3] // probabilities when starting in tr2 and ending in [end1, end2]\n]\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
422 次 |
| 最近记录: |