python中已经有一个多键字典,也有一个多值字典。我需要一个既是Python字典又是Python字典:
例子:
# probabilistically fetch any one of baloon, toy or car
d['red','blue','green']== "baloon" or "car" or "toy"
d ['red'] == d ['green']的概率较高,而d ['red']!= d ['red']的概率较低,但可能
单个输出值应该根据键的规则概率确定(模糊),例如:在上述情况下,规则可能是如果键同时具有“红色”和“蓝色”,则如果只有蓝色,则返回“气球”的时间为80% “玩具”占15%的时间,其他“汽车”占5%的时间。
应该设计setitem方法,以便可以进行以下操作:
d["red", "blue"] =[
("baloon",haseither('red','green'),0.8),
("toy",.....)
,....
]
上面使用谓词函数和相应的概率为字典分配了多个值。而不是上面的作业列表,甚至最好是字典作为作业:
d["red", "blue"] ={
"baloon": haseither('red','green',0.8),
"toy": hasonly("blue",0.15),
"car": default(0.05)
}
在上面的气球中,如果出现“红色”或绿色,将返还80%的时间,如果出现蓝色,则将返还玩具15%的时间,并且无条件返还汽车5%的时间。
是否有任何现有数据结构已经满足python中的上述要求?如果没有,那么如何修改multikeydict代码以满足python中的上述要求?
如果使用字典,则可以使用配置文件或使用适当的嵌套修饰符来配置上述概率谓词逻辑,而无需对\ else语句进行硬编码。
注意:上面是基于规则的自动响应器应用程序的有用自动机,因此,即使它不使用字典结构,也请让我知道是否有类似的基于规则的框架在python中可用?
multi_key_dict
一次不允许__getitem__()
多个键...
(例如d["red", "green"]
)
可以使用tuple
或set
键模拟多键。如果顺序无关紧要,则set
似乎最好(实际上是可散列的frozen set
,因此["red", "blue"]
相同["blue", "red"]
。
多值是使用某些数据类型所固有的,它可以是可以方便地索引的任何存储元素。标准dict
应该提供这一点。
使用规则和假设1定义的概率分布,使用python文档中的此配方执行非确定性选择。
MultiKeyMultiValNonDeterministicDict
班级真叫 \ o /-不错!
此类使用多个键定义多个值的概率规则集。在项创建(__setitem__()
)期间,将对键1的所有组合预先计算所有值概率。在项目访问(__getitem__()
)期间,选择预先计算的概率分布,并基于随机加权选择评估结果。
import random
import operator
import bisect
import itertools
# or use itertools.accumulate in python 3
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
try:
total = next(it)
except StopIteration:
return
yield total
for element in it:
total = func(total, element)
yield total
class MultiKeyMultiValNonDeterministicDict(dict):
def key_combinations(self, keys):
"""get all combinations of keys"""
return [frozenset(subset) for L in range(0, len(keys)+1) for subset in itertools.combinations(keys, L)]
def multi_val_rule_prob(self, rules, rule):
"""
assign probabilities for each value,
spreading undefined result probabilities
uniformly over the leftover results not defined by rule.
"""
all_results = set([result for result_probs in rules.values() for result in result_probs])
prob = rules[rule]
leftover_prob = 1.0 - sum([x for x in prob.values()])
leftover_results = len(all_results) - len(prob)
for result in all_results:
if result not in prob:
# spread undefined prob uniformly over leftover results
prob[result] = leftover_prob/leftover_results
return prob
def multi_key_rule_prob(self, key, val):
"""
assign probability distributions for every combination of keys,
using the default for combinations not defined in rule set
"""
combo_probs = {}
for combo in self.key_combinations(key):
if combo in val:
result_probs = self.multi_val_rule_prob(val, combo).items()
else:
result_probs = self.multi_val_rule_prob(val, frozenset([])).items()
combo_probs[combo] = result_probs
return combo_probs
def weighted_random_choice(self, weighted_choices):
"""make choice from weighted distribution"""
choices, weights = zip(*weighted_choices)
cumdist = list(accumulate(weights))
return choices[bisect.bisect(cumdist, random.random() * cumdist[-1])]
def __setitem__(self, key, val):
"""
set item in dictionary,
assigns values to keys with precomputed probability distributions
"""
precompute_val_probs = self.multi_key_rule_prob(key, val)
# use to show ALL precomputed probabilities for key's rule set
# print precompute_val_probs
dict.__setitem__(self, frozenset(key), precompute_val_probs)
def __getitem__(self, key):
"""
get item from dictionary,
randomly select value based on rule probability
"""
key = frozenset([key]) if isinstance(key, str) else frozenset(key)
val = None
weighted_val = None
if key in self.keys():
val = dict.__getitem__(self, key)
weighted_val = val[key]
else:
for k in self.keys():
if key.issubset(k):
val = dict.__getitem__(self, k)
weighted_val = val[key]
# used to show probabality for key
# print weighted_val
if weighted_val:
prob_results = self.weighted_random_choice(weighted_val)
else:
prob_results = None
return prob_results
d = MultiKeyMultiValNonDeterministicDict()
d["red","blue","green"] = {
# {rule_set} : {result: probability}
frozenset(["red", "green"]): {"ballon": 0.8},
frozenset(["blue"]): {"toy": 0.15},
frozenset([]): {"car": 0.05}
}
检查概率
N = 10000
red_green_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
red_blue_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
blue_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
red_blue_green_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
default_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
for _ in xrange(N):
red_green_test[d["red","green"]] += 1.0
red_blue_test[d["red","blue"]] += 1.0
blue_test[d["blue"]] += 1.0
default_test[d["green"]] += 1.0
red_blue_green_test[d["red","blue","green"]] += 1.0
print 'red,green test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_green_test.items())
print 'red,blue test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_blue_test.items())
print 'blue test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in blue_test.items())
print 'default test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in default_test.items())
print 'red,blue,green test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_blue_green_test.items())
red,green test = car: 09.89% toy: 10.06% ballon: 80.05%
red,blue test = car: 05.30% toy: 47.71% ballon: 46.99%
blue test = car: 41.69% toy: 15.02% ballon: 43.29%
default test = car: 05.03% toy: 47.16% ballon: 47.81%
red,blue,green test = car: 04.85% toy: 49.20% ballon: 45.95%
分配假设
由于尚未完全定义规则集,因此对概率分布进行了假设,其中大部分是在中完成的multi_val_rule_prob()
。基本上,任何未定义的概率将均匀地分布在其余值上。对所有键组合完成此操作,并为随机加权选择创建通用键接口。
给定示例规则集
d["red","blue","green"] = {
# {rule_set} : {result: probability}
frozenset(["red", "green"]): {"ballon": 0.8},
frozenset(["blue"]): {"toy": 0.15},
frozenset([]): {"car": 0.05}
}
这将创建以下分布
'red' = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
'green' = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
'blue' = [('car', 0.425), ('toy', 0.150), ('ballon', 0.425)]
'blue,red' = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
'green,red' = [('car', 0.098), ('toy', 0.098), ('ballon', 0.800)]
'blue,green' = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
'blue,green,red'= [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
default = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
如果不正确,请告知。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句