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

  1. 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

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -