Multikey Multivalue Non Deterministic python dictionary -
there multi key dict in python , multivalued dict. needed python dictionary both:
example:
# probabilistically fetch 1 of baloon, toy or car d['red','blue','green']== "baloon" or "car" or "toy"
probability of d['red']==d['green'] high , probability of d['red']!=d['red'] low possible
the single output value should probabilistically determined (fuzzy) based on rule keys eg:in above case rule if keys have both "red" , "blue" return "baloon" 80% of time if blue return "toy" 15% of time else "car" 5% of time.
the setitem method should designed such following possible:
d["red", "blue"] =[ ("baloon",haseither('red','green'),0.8), ("toy",.....) ,.... ]
above assigns multiple values dictionary predicate function , corresponding probability. , instead of assignment list above dictionary assignment preferable:
d["red", "blue"] ={ "baloon": haseither('red','green',0.8), "toy": hasonly("blue",0.15), "car": default(0.05) }
in above baloon returned 80% of time if "red" or green present , return toy 15% of time if blue present , return car 5% of time without condition.
are there existing data structures satisfy above requirements in python? if no how can multikeydict code modified meet above requirements in python?
if using dictionary there can configuration file or use of appropriate nested decorators configures above probabilistic predicate logics without having hard code if \else statements .
note: above useful automata rule based auto responder application hence let me know if similar rule based framework available in python if not use dictionary structure?
simulated multikey dictionary
multi_key_dict
did not allow __getitem__()
multiple keys @ onces...
(e.g. d["red", "green"]
)
a multi key can simulated tuple
or set
keys. if order not matter, set
seems best (actually hashable frozen set
, ["red", "blue"]
same ["blue", "red"]
.
simulated multival dictionary
multi values inherent using datatypes, can any storage element may conveniently indexed. standard dict
should provide that.
non-determinism
using probability distribution defined rules , assumptions1, non-deterministic selection performed using this recipe python docs.
multikeymultivalnondeterministicdict
class
what name. \o/-nice!
this class takes multiple keys define probabilistic rule set of multiple values. during item creation (__setitem__()
) value probabilities precomputed combinations of keys1. during item access (__getitem__()
) precomputed probability distribution selected , result evaluated based on random weighted selection.
definition
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 = iter(iterable) try: total = next(it) except stopiteration: return yield total element in it: total = func(total, element) yield total class multikeymultivalnondeterministicdict(dict): def key_combinations(self, keys): """get combinations of keys""" return [frozenset(subset) l in range(0, len(keys)+1) subset in itertools.combinations(keys, l)] def multi_val_rule_prob(self, rules, rule): """ assign probabilities each value, spreading undefined result probabilities uniformly on leftover results not defined rule. """ all_results = set([result result_probs in rules.values() result in result_probs]) prob = rules[rule] leftover_prob = 1.0 - sum([x x in prob.values()]) leftover_results = len(all_results) - len(prob) result in all_results: if result not in prob: # spread undefined prob uniformly on leftover results prob[result] = leftover_prob/leftover_results return prob def multi_key_rule_prob(self, key, val): """ assign probability distributions every combination of keys, using default combinations not defined in rule set """ combo_probs = {} 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 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 keys precomputed probability distributions """ precompute_val_probs = self.multi_key_rule_prob(key, val) # use show precomputed probabilities key's rule set # print precompute_val_probs dict.__setitem__(self, frozenset(key), precompute_val_probs) def __getitem__(self, key): """ item 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: k in self.keys(): if key.issubset(k): val = dict.__getitem__(self, k) weighted_val = val[key] # used show probabality key # print weighted_val if weighted_val: prob_results = self.weighted_random_choice(weighted_val) else: prob_results = none return prob_results
usage
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} }
testing
check probabilities
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} _ 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) key, val in red_green_test.items()) print 'red,blue test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/n) key, val in red_blue_test.items()) print 'blue test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/n) key, val in blue_test.items()) print 'default test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/n) key, val in default_test.items()) print 'red,blue,green test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/n) 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%
probabilities match rules!
footnotes
distribution assumption
since rule set not defined, assumptions made probability distributions, of done in
multi_val_rule_prob()
. undefined probability spread uniformly on remaining values. done all combinations of keys, , creates generalized key interface random weighted selection.given example rule set
d["red","blue","green"] = { # {rule_set} : {result: probability} frozenset(["red", "green"]): {"ballon": 0.8}, frozenset(["blue"]): {"toy": 0.15}, frozenset([]): {"car": 0.05} }
this create following distributions
'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)]
if incorrect, please advise.
Comments
Post a Comment