def neighbors(self, node): """returns a list of the neighboring nodes of node. """ var = self.variables[len(node)] # the next variable res = [] for val in self.csp.domains[var]: new_env = dict_union(node, {var: val}) #dictionary union if self.csp.consistent(new_env): res.append(Arc(node, new_env)) return res
def query(self,var,obs={},elim_order=None): """computes P(var|obs) where var is a variable obs is a variable:value dictionary elim_order is a list of the non-observed non-query variables in gm""" if var in obs: return {val:(1 if val == obs[var] else 0) for val in var.domain} else: if elim_order == None: elim_order = [v for v in self.gm.variables if (v not in obs) and v != var] unnorm = [self.rc(dict_union({var:val},obs), self.gm.factors, elim_order) for val in var.domain] p_obs = sum(unnorm) return {val:pr/p_obs for val,pr in zip(var.domain, unnorm)}
def rc0(self, context, factors, elim_order): """simplest search algorithm""" self.display(1,"calling rc,",(context,factors)) if elim_order == []: # evaluate factors when all variables are assigned self.display(2,"rc evaluating factors") return prod(fac.get_value(context) for fac in factors) else: total = 0 var = elim_order[-1] self.display(2, "rc branching on", var) for val in var.domain: total += self.rc0(dict_union({var:val},context), factors, elim_order[:-1]) self.display(2, "rc branching on", var,"returning", total) return total
def rc(self, context, factors, elim_order): """ returns the number \sum_{elim_order} \prod_{factors} given assignments in context context is a variable:value dictionary factors is a list of factors elim_order is a list of variables in factors that are not in context """ self.display(1,"calling rc,",(context,factors)) ce = CacheElt(context, factors) # key for the appropriate cache entry if ce in self.cache: self.display(2,"rc cache lookup") return self.cache[ce] elif factors == []: # needed if you don't have forgetting and caching return 1 vars_not_in_any_factor = [var for var in context if not any(var in fac.variables for fac in factors)] if vars_not_in_any_factor != []: # forget variables not in any factor self.display(2,"rc forgetting variables", vars_not_in_any_factor) return self.rc({key:val for (key,val) in context.items() if key not in vars_not_in_any_factor}, factors, elim_order) to_eval = [fac for fac in factors if all(v in context for v in fac.variables)] if to_eval: # evaluate factors when all variables are assigned self.display(2,"rc evaluating factors") val = prod(fac.get_value(context) for fac in to_eval) if val == 0: return 0 else: return val * self.rc(context, [fac for fac in factors if fac not in to_eval], elim_order) comp = connected_components(context, factors, elim_order) if len(comp) >= 1: # there are disconnected components self.display(2,"splitting into conected components",comp) return(prod(self.rc(context,f,eo) for (f,eo) in comp)) else: assert elim_order, "elim_order should not be empty to get here" total = 0 var = elim_order[-1] self.display(2, "rc branching on", var) for val in var.domain: total += self.rc(dict_union({var:val},context), factors, elim_order[:-1]) self.cache[ce] = total self.display(2, "rc branching on", var,"returning", total) return total
else: return val * self.rc( context, [fac for fac in factors if fac not in to_eval], elim_order) elif len(comp := connected_components(context, factors, elim_order)) >= 1: # there are disconnected components self.display(2, "splitting into conected components", comp) return (prod(self.rc(context, f, eo) for (f, eo) in comp)) else: assert elim_order, "elim_order should not be empty to get here" total = 0 var = elim_order[-1] self.display(2, "rc branching on", var) for val in var.domain: total += self.rc(dict_union({var: val}, context), factors, elim_order[:-1]) self.cache[ce] = total self.display(2, "rc branching on", var, "returning", total) return total def rc0(self, context, factors, elim_order): """simplest search algorithm""" self.display(1, "calling rc,", (context, factors)) if elim_order == []: # evaluate factors when all variables are assigned self.display(2, "rc evaluating factors") return prod(fac.get_value(context) for fac in factors) else: total = 0 var = elim_order[-1]