【问题标题】:Good data structure for storing agent path probabilities用于存储代理路径概率的良好数据结构
【发布时间】:2021-05-16 17:44:58
【问题描述】:

我正在研究基于代理的模型,在该模型中,代理可以有一定概率选择不同的路线。对于每条路线,都有多个路径点(即p1, p2, ..., p_end)。目前,我将其表示为 JSON 文件,例如:

{    
   "paths": [
        {"[p3, p4, p_end]": 0.25},
        {"[p3, p2, p1, p_end]": 0.25},
        {"[p3, p4, p5, p7, p5, p_end]": 0.1},
        {"[p3, p4, p5, p7, p8, p5, p_end]": 0.1},
        {"[p3, p4, p5, p7, p10, p5, p_end]": 0.3}
    ]
}

其中每个字典键是一个路由,其值是关联概率。

但是,我有比这更多的路由选项(即 50-100),我想知道是否有更好的方法来表示 python 的这种数据结构,而不是显式地编写所有内容。

对不起,如果这是一个非常基本的问题,并提前感谢:)

【问题讨论】:

  • 你能给每一步分配一个概率吗(例如 P{p_n -> p-2} = 0.3)?如果是这样,您的数据结构会简单得多。
  • 您的路径中似乎有循环,例如同一路径中有多个 p5,是故意的吗?
  • @Malo 是的,这是有意的,这就是为什么我需要提及整个路径以避免无限循环
  • @SalmanShaukat,好的,您能否将概率分配给每个小步骤,例如 p3->p4 0.8 和 p3->2 0.2 ?还是必须将其分配给整个路径?
  • @Malo 是的,我可以一步一步来。一个问题是:在某些情况下如何避免循环,例如,P1 -> P2 & P2 -> P1 是允许的,但像 P1 -> P2 -> P1 -> P1 这样的事情不应该被允许。我想我会通过记录已经访问过的状态来使用“内存”概念,从而避免循环

标签: python json data-structures


【解决方案1】:

我认为字典很好在一天结束时。但是,如果您可以得到在任何状态之间移动的概率,那么就有更好的方法来表示它。

您的问题表述类似于基本的马尔可夫链(如果您不熟悉,它是一个包含转换到不同状态的概率的图)。听起来用带有加权边的类似图形的结构来表示问题是很自然的,它显示了概率。

有了这个,你就可以使用基本的图遍历算法来构建一个字典,就像你上面的字典一样。这样做有很多好处,比如能够使用马尔可夫模型分析技术,还能够通过修改链来更改字典。

路径看起来像这样:

"paths": [ 
    {(1, 2): ?},
    {(1, 3): ?},
    ...
]

不过,这只是一个建议。由于甜蜜的查询效率,字符串到概率的哈希可能是最终目标。

编辑:

刚刚注意到您的后续问题。我拼凑了一个快速功能,您当然可以根据自己的目的进行优化。如果我在某个地方搞砸了,请告诉我(我认为这很好)。

对于以下示例,请考虑链:

假设路径被作为边缘列表获取,则可以使用以下过程。

# Very small set of edges. 
paths = {
    (1, 2) : 0.9,
    (1, 3) : 0.1,
    (2, 1) : 0.8,
    (2, 3) : 0.2,
}

from collections import defaultdict

# Make a simple dictionary to keep track of out paths
edge_dict = defaultdict(list)
for k,v in paths.items():
    edge_dict[k[0]].append((k[1], v))
print(dict(edge_dict))
# > {1: [(2, 0.9), (3, 0.1)], 2: [(1, 0.8), (3, 0.2)]}

# Recursively construct a hash or probabilities
def dfs_from_state(start, edge_dict):
    path_hash = dict()
    dfs_from_state_recur(start, path_hash, edge_dict)
    return path_hash

def dfs_from_state_recur(state, path_hash, edge_dict, chain = [], prob = 1):
    if state not in edge_dict.keys(): 
        # If it's a terminal state, base case: hash the prob
        chain += [(state, )] 
        chain_str = "->".join([str(c[0]) for c in chain])
        path_hash[chain_str] = prob
        return 
    for adj, weight in edge_dict[state]:
        # Otherwise, dfs 
        link = (state, adj)
        if link not in chain: 
            dfs_from_state_recur(
                adj, path_hash, edge_dict, 
                chain+[link], prob*weight
            )


# Actually do DFS from every possible starting state
path_hash = dict()
for start in edge_dict.keys():
    path_hash.update(dfs_from_state(start, edge_dict))

[print("%12s : %0.4f" % e) for e in path_hash.items()]

#  1->2->1->3 : 0.0720
#     1->2->3 : 0.1800
#        1->3 : 0.1000
#  2->1->2->3 : 0.1440
#     2->1->3 : 0.0800
#        2->3 : 0.2000

【讨论】:

  • 我也在考虑这样的图形结构,我遇到的问题是:在某些情况下如何避免循环例如,P1 -> P2 & P2 -> P1 是允许的,但是像 P1 - > P2 -> P1 -> P1 不应该被允许。我想我会通过记录已经访问过的状态来使用“内存”概念,从而避免循环。
  • @SalmanShaukat 请查看更新。让我知道这是否是您想要的。
猜你喜欢
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
相关资源
最近更新 更多