<s> from __future__ import division <EOL> '''<STR_LIT>''' <EOL> import os <EOL> import csv <EOL> import sys <EOL> import copy <EOL> import inspect <EOL> import random <EOL> from collections import defaultdict <EOL> from itertools import product as iter_product <EOL> from Queue import Queue <EOL> import sqlite3 <EOL> from prettytable import PrettyTable <EOL> from bayesian . persistance import SampleDB , ensure_data_dir_exists <EOL> from bayesian . exceptions import * <EOL> from bayesian . utils import get_args <EOL> DEBUG = False <EOL> GREEN = '<STR_LIT>' <EOL> NORMAL = '<STR_LIT>' <EOL> class Node ( object ) : <EOL> def is_leaf ( self ) : <EOL> if len ( self . neighbours ) == <NUM_LIT:1> : <EOL> return True <EOL> return False <EOL> def send ( self , message ) : <EOL> recipient = message . destination <EOL> if DEBUG : <EOL> print '<STR_LIT>' % ( <EOL> self . name , recipient . name ) , message <EOL> recipient . received_messages [ <EOL> self . name ] = message <EOL> def get_sent_messages ( self ) : <EOL> sent_messages = { } <EOL> for neighbour in self . neighbours : <EOL> if neighbour . received_messages . get ( self . name ) : <EOL> sent_messages [ neighbour . name ] = neighbour . received_messages . get ( self . name ) <EOL> return sent_messages <EOL> def message_report ( self ) : <EOL> '''<STR_LIT>''' <EOL> print '<STR_LIT>' <EOL> print '<STR_LIT>' % self . name <EOL> print '<STR_LIT>' <EOL> for k , v in self . received_messages . iteritems ( ) : <EOL> print '<STR_LIT>' % ( v . source . name , v . argspec ) <EOL> v . list_factors ( ) <EOL> print '<STR_LIT>' <EOL> def get_target ( self ) : <EOL> '''<STR_LIT>''' <EOL> neighbours = self . neighbours <EOL> needed_to_send = defaultdict ( int ) <EOL> for target in neighbours : <EOL> needed_to_send [ target ] = len ( neighbours ) - <NUM_LIT:1> <EOL> for _ , message in self . received_messages . items ( ) : <EOL> for target in neighbours : <EOL> if message . source != target : <EOL> needed_to_send [ target ] -= <NUM_LIT:1> <EOL> for k , v in needed_to_send . items ( ) : <EOL> if v == <NUM_LIT:0> and not self . name in k . received_messages : <EOL> return k <EOL> def get_neighbour_by_name ( self , name ) : <EOL> for node in self . neighbours : <EOL> if node . name == name : <EOL> return node <EOL> class VariableNode ( Node ) : <EOL> def __init__ ( self , name , domain = [ True , False ] ) : <EOL> self . name = name <EOL> self . domain = domain <EOL> self . neighbours = [ ] <EOL> self . received_messages = { } <EOL> self . value = None <EOL> def construct_message ( self ) : <EOL> target = self . get_target ( ) <EOL> message = make_variable_node_message ( self , target ) <EOL> return message <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . name , self . value ) <EOL> def marginal ( self , val , normalizer = <NUM_LIT:1.0> ) : <EOL> '''<STR_LIT>''' <EOL> product = <NUM_LIT:1> <EOL> for _ , message in self . received_messages . iteritems ( ) : <EOL> product *= message ( val ) <EOL> return product / normalizer <EOL> def reset ( self ) : <EOL> self . received_messages = { } <EOL> self . value = None <EOL> def verify_neighbour_types ( self ) : <EOL> '''<STR_LIT>''' <EOL> for node in self . neighbours : <EOL> if not isinstance ( node , FactorNode ) : <EOL> return False <EOL> return True <EOL> class FactorNode ( Node ) : <EOL> def __init__ ( self , name , func , neighbours = [ ] ) : <EOL> self . name = name <EOL> self . func = func <EOL> self . neighbours = neighbours [ : ] <EOL> self . received_messages = { } <EOL> self . func . value = None <EOL> self . cached_functions = [ ] <EOL> def construct_message ( self ) : <EOL> target = self . get_target ( ) <EOL> message = make_factor_node_message ( self , target ) <EOL> return message <EOL> def verify_neighbour_types ( self ) : <EOL> '''<STR_LIT>''' <EOL> for node in self . neighbours : <EOL> if not isinstance ( node , VariableNode ) : <EOL> return False <EOL> return True <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . name , <EOL> self . func . __name__ , <EOL> get_args ( self . func ) ) <EOL> def marginal ( self , val_dict ) : <EOL> product = <NUM_LIT:1> <EOL> neighbours = self . neighbours <EOL> for neighbour in neighbours : <EOL> message = self . received_messages [ neighbour . name ] <EOL> call_args = [ ] <EOL> for arg in get_args ( message ) : <EOL> call_args . append ( val_dict [ arg ] ) <EOL> if not call_args : <EOL> call_args . append ( '<STR_LIT>' ) <EOL> product *= message ( * call_args ) <EOL> call_args = [ ] <EOL> for arg in get_args ( self . func ) : <EOL> call_args . append ( val_dict [ arg ] ) <EOL> if not call_args : <EOL> call_args . append ( '<STR_LIT>' ) <EOL> product *= self . func ( * call_args ) <EOL> return product <EOL> def add_evidence ( self , node , value ) : <EOL> '''<STR_LIT>''' <EOL> args = get_args ( self . func ) <EOL> pos = args . index ( node . name ) <EOL> old_func = self . func <EOL> self . cached_functions . insert ( <NUM_LIT:0> , old_func ) <EOL> def evidence_func ( * args ) : <EOL> if args [ pos ] != value : <EOL> return <NUM_LIT:0> <EOL> return old_func ( * args ) <EOL> evidence_func . argspec = args <EOL> evidence_func . domains = old_func . domains <EOL> self . func = evidence_func <EOL> def reset ( self ) : <EOL> self . received_messages = { } <EOL> if self . cached_functions : <EOL> self . func = self . cached_functions [ - <NUM_LIT:1> ] <EOL> self . cached_functions = [ ] <EOL> class Message ( object ) : <EOL> def list_factors ( self ) : <EOL> print '<STR_LIT>' <EOL> print '<STR_LIT>' % ( self . source . name , self . destination . name ) <EOL> print '<STR_LIT>' <EOL> for factor in self . factors : <EOL> print factor <EOL> def __call__ ( self , var ) : <EOL> '''<STR_LIT>''' <EOL> if getattr ( self . func , '<STR_LIT>' , None ) == '<STR_LIT>' : <EOL> return <NUM_LIT:1> <EOL> assert not isinstance ( var , VariableNode ) <EOL> return self . func ( var ) <EOL> class VariableMessage ( Message ) : <EOL> def __init__ ( self , source , destination , factors , func ) : <EOL> self . source = source <EOL> self . destination = destination <EOL> self . factors = factors <EOL> self . argspec = get_args ( func ) <EOL> self . func = func <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . source . name , self . destination . name , <EOL> len ( self . factors ) , self . argspec ) <EOL> class FactorMessage ( Message ) : <EOL> def __init__ ( self , source , destination , factors , func ) : <EOL> self . source = source <EOL> self . destination = destination <EOL> self . factors = factors <EOL> self . func = func <EOL> self . argspec = get_args ( func ) <EOL> self . domains = func . domains <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . source . name , self . destination . name , <EOL> self . argspec , <EOL> len ( self . factors ) ) <EOL> def connect ( a , b ) : <EOL> '''<STR_LIT>''' <EOL> if not isinstance ( b , list ) : <EOL> b = [ b ] <EOL> for b_ in b : <EOL> a . neighbours . append ( b_ ) <EOL> b_ . neighbours . append ( a ) <EOL> def eliminate_var ( f , var ) : <EOL> '''<STR_LIT>''' <EOL> arg_spec = get_args ( f ) <EOL> pos = arg_spec . index ( var ) <EOL> new_spec = arg_spec [ : ] <EOL> new_spec . remove ( var ) <EOL> eliminated_pos = arg_spec . index ( var ) <EOL> def eliminated ( * args ) : <EOL> template = arg_spec [ : ] <EOL> total = <NUM_LIT:0> <EOL> call_args = template [ : ] <EOL> i = <NUM_LIT:0> <EOL> for arg in args : <EOL> if i == eliminated_pos : <EOL> call_args [ i ] = '<STR_LIT>' <EOL> i += <NUM_LIT:1> <EOL> call_args [ i ] = arg <EOL> i += <NUM_LIT:1> <EOL> for val in f . domains [ var ] : <EOL> call_args [ pos ] = val <EOL> total += f ( * call_args ) <EOL> return total <EOL> eliminated . argspec = new_spec <EOL> eliminated . domains = f . domains <EOL> return eliminated <EOL> def memoize ( f ) : <EOL> '''<STR_LIT>''' <EOL> cache = { } <EOL> def memoized ( * args ) : <EOL> arg_vals = tuple ( args ) <EOL> if not arg_vals in cache : <EOL> cache [ arg_vals ] = f ( * args ) <EOL> return cache [ arg_vals ] <EOL> if hasattr ( f , '<STR_LIT>' ) : <EOL> memoized . domains = f . domains <EOL> if hasattr ( f , '<STR_LIT>' ) : <EOL> memoized . argspec = f . argspec <EOL> return memoized <EOL> def make_not_sum_func ( product_func , keep_var ) : <EOL> '''<STR_LIT>''' <EOL> args = get_args ( product_func ) <EOL> new_func = copy . deepcopy ( product_func ) <EOL> for arg in args : <EOL> if arg != keep_var : <EOL> new_func = eliminate_var ( new_func , arg ) <EOL> new_func = memoize ( new_func ) <EOL> return new_func <EOL> def make_factor_node_message ( node , target_node ) : <EOL> '''<STR_LIT>''' <EOL> if node . is_leaf ( ) : <EOL> not_sum_func = make_not_sum_func ( node . func , target_node . name ) <EOL> message = FactorMessage ( node , target_node , [ node . func ] , not_sum_func ) <EOL> return message <EOL> args = set ( get_args ( node . func ) ) <EOL> factors = [ node . func ] <EOL> neighbours = node . neighbours <EOL> for neighbour in neighbours : <EOL> if neighbour == target_node : <EOL> continue <EOL> in_message = node . received_messages [ neighbour . name ] <EOL> if in_message . destination != node : <EOL> out_message = VariableMessage ( <EOL> neighbour , node , in_message . factors , <EOL> in_message . func ) <EOL> out_message . argspec = in_message . argspec <EOL> else : <EOL> out_message = in_message <EOL> factors . append ( out_message ) <EOL> product_func = make_product_func ( factors ) <EOL> not_sum_func = make_not_sum_func ( product_func , target_node . name ) <EOL> message = FactorMessage ( node , target_node , factors , not_sum_func ) <EOL> return message <EOL> def make_variable_node_message ( node , target_node ) : <EOL> '''<STR_LIT>''' <EOL> if node . is_leaf ( ) : <EOL> message = VariableMessage ( <EOL> node , target_node , [ <NUM_LIT:1> ] , unity ) <EOL> return message <EOL> factors = [ ] <EOL> neighbours = node . neighbours <EOL> for neighbour in neighbours : <EOL> if neighbour == target_node : <EOL> continue <EOL> factors . append ( <EOL> node . received_messages [ neighbour . name ] ) <EOL> product_func = make_product_func ( factors ) <EOL> message = VariableMessage ( <EOL> node , target_node , factors , product_func ) <EOL> return message <EOL> def make_product_func ( factors ) : <EOL> '''<STR_LIT>''' <EOL> args_map = { } <EOL> all_args = [ ] <EOL> domains = { } <EOL> for factor in factors : <EOL> args_map [ factor ] = get_args ( factor ) <EOL> all_args += args_map [ factor ] <EOL> if hasattr ( factor , '<STR_LIT>' ) : <EOL> domains . update ( factor . domains ) <EOL> args = list ( set ( all_args ) ) <EOL> def product_func ( * product_func_args ) : <EOL> arg_dict = dict ( zip ( args , product_func_args ) ) <EOL> result = <NUM_LIT:1> <EOL> for factor in factors : <EOL> factor_args = [ ] <EOL> for arg in get_args ( factor ) : <EOL> if arg in arg_dict : <EOL> factor_args . append ( arg_dict [ arg ] ) <EOL> if not factor_args : <EOL> factor_args . append ( '<STR_LIT>' ) <EOL> result *= factor ( * factor_args ) <EOL> return result <EOL> product_func . argspec = args <EOL> product_func . factors = factors <EOL> product_func . domains = domains <EOL> return memoize ( product_func ) <EOL> def make_unity ( argspec ) : <EOL> def unity ( x ) : <EOL> return <NUM_LIT:1> <EOL> unity . argspec = argspec <EOL> unity . __name__ = '<STR_LIT:1>' <EOL> return unity <EOL> def unity ( ) : <EOL> return <NUM_LIT:1> <EOL> def expand_args ( args ) : <EOL> if not args : <EOL> return [ ] <EOL> return <EOL> def dict_to_tuples ( d ) : <EOL> '''<STR_LIT>''' <EOL> retval = [ ] <EOL> for k , vals in d . iteritems ( ) : <EOL> retval . append ( [ ( k , v ) for v in vals ] ) <EOL> return retval <EOL> def expand_parameters ( arg_vals ) : <EOL> '''<STR_LIT>''' <EOL> arg_tuples = dict_to_tuples ( arg_vals ) <EOL> return [ dict ( args ) for args in iter_product ( * arg_tuples ) ] <EOL> def add_evidence ( node , value ) : <EOL> '''<STR_LIT>''' <EOL> node . value = value <EOL> neighbours = node . neighbours <EOL> for factor_node in neighbours : <EOL> if node . name in get_args ( factor_node . func ) : <EOL> factor_node . add_evidence ( node , value ) <EOL> def discover_sample_ordering ( graph ) : <EOL> '''<STR_LIT>''' <EOL> iterations = <NUM_LIT:0> <EOL> ordering = [ ] <EOL> pmf_ordering = [ ] <EOL> accounted_for = set ( ) <EOL> variable_nodes = [ n for n in graph . nodes if isinstance ( n , VariableNode ) ] <EOL> factor_nodes = [ n for n in graph . nodes if isinstance ( n , FactorNode ) ] <EOL> required = len ( [ n for n in graph . nodes if isinstance ( n , VariableNode ) ] ) <EOL> for node in graph . get_leaves ( ) : <EOL> if isinstance ( node , FactorNode ) : <EOL> ordering . append ( node . neighbours [ <NUM_LIT:0> ] ) <EOL> accounted_for . add ( node . neighbours [ <NUM_LIT:0> ] . name ) <EOL> pmf_ordering . append ( node . func ) <EOL> while len ( ordering ) < required : <EOL> for node in factor_nodes : <EOL> args = set ( get_args ( node . func ) ) <EOL> new_args = args . difference ( accounted_for ) <EOL> if len ( new_args ) == <NUM_LIT:1> : <EOL> arg_name = list ( new_args ) [ <NUM_LIT:0> ] <EOL> var_node = node . get_neighbour_by_name ( arg_name ) <EOL> ordering . append ( var_node ) <EOL> accounted_for . add ( var_node . name ) <EOL> pmf_ordering . append ( node . func ) <EOL> return zip ( ordering , pmf_ordering ) <EOL> def get_sample ( ordering , evidence = { } ) : <EOL> '''<STR_LIT>''' <EOL> sample = [ ] <EOL> sample_dict = dict ( ) <EOL> for var , func in ordering : <EOL> r = random . random ( ) <EOL> total = <NUM_LIT:0> <EOL> for val in var . domain : <EOL> test_var = VariableNode ( var . name ) <EOL> test_var . value = val <EOL> args = [ ] <EOL> for arg in get_args ( func ) : <EOL> if arg == var . name : <EOL> args . append ( val ) <EOL> else : <EOL> args . append ( sample_dict [ arg ] . value ) <EOL> total += func ( * args ) <EOL> if total > r : <EOL> if var . name in evidence : <EOL> if test_var . value == evidence [ var . name ] : <EOL> sample . append ( test_var ) <EOL> sample_dict [ var . name ] = test_var <EOL> else : <EOL> sample . append ( test_var ) <EOL> sample_dict [ var . name ] = test_var <EOL> break <EOL> if not var . name in sample_dict : <EOL> print '<STR_LIT>' % ( var . name , func . __name__ ) <EOL> raise InvalidSampleException <EOL> return sample <EOL> class FactorGraph ( object ) : <EOL> def __init__ ( self , nodes , name = None , n_samples = <NUM_LIT:100> ) : <EOL> self . nodes = nodes <EOL> self . _inference_method = '<STR_LIT>' <EOL> function_args = dict ( ) <EOL> arg_domains = dict ( ) <EOL> for node in self . nodes : <EOL> if isinstance ( node , VariableNode ) : <EOL> arg_domains [ node . name ] = node . domain <EOL> elif isinstance ( node , FactorNode ) : <EOL> function_args [ node . func . __name__ ] = get_args ( node . func ) <EOL> for node in self . nodes : <EOL> if isinstance ( node , FactorNode ) : <EOL> if hasattr ( node . func , '<STR_LIT>' ) : <EOL> continue <EOL> domains = dict ( ) <EOL> for arg in get_args ( node . func ) : <EOL> if not arg in arg_domains : <EOL> print '<STR_LIT>' % arg <EOL> else : <EOL> domains . update ( { arg : arg_domains [ arg ] } ) <EOL> node . func . domains = domains <EOL> self . name = name <EOL> self . n_samples = n_samples <EOL> try : <EOL> if self . has_cycles ( ) : <EOL> self . inference_method = '<STR_LIT>' <EOL> else : <EOL> self . inference_method = '<STR_LIT>' <EOL> except : <EOL> print '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> self . inference_method = '<STR_LIT>' <EOL> self . enforce_minimum_samples = False <EOL> @ property <EOL> def inference_method ( self ) : <EOL> return self . _inference_method <EOL> @ inference_method . setter <EOL> def inference_method ( self , value ) : <EOL> if value == '<STR_LIT>' : <EOL> ensure_data_dir_exists ( self . sample_db_filename ) <EOL> sample_ordering = self . discover_sample_ordering ( ) <EOL> domains = dict ( [ ( var , var . domain ) for var , _ in sample_ordering ] ) <EOL> if not os . path . isfile ( self . sample_db_filename ) : <EOL> self . sample_db = SampleDB ( <EOL> self . sample_db_filename , <EOL> domains , <EOL> initialize = True ) <EOL> else : <EOL> self . sample_db = SampleDB ( <EOL> self . sample_db_filename , <EOL> domains , <EOL> initialize = False ) <EOL> self . _inference_method = value <EOL> @ property <EOL> def sample_db_filename ( self ) : <EOL> '''<STR_LIT>''' <EOL> home = os . path . expanduser ( '<STR_LIT>' ) <EOL> return os . path . join ( <EOL> home , '<STR_LIT>' , <EOL> '<STR_LIT:data>' , <EOL> '<STR_LIT>' % ( self . name or '<STR_LIT:default>' ) ) <EOL> def reset ( self ) : <EOL> '''<STR_LIT>''' <EOL> for node in self . nodes : <EOL> node . reset ( ) <EOL> def has_cycles ( self ) : <EOL> '''<STR_LIT>''' <EOL> discovered_nodes = set ( ) <EOL> traversed_edges = set ( ) <EOL> q = Queue ( ) <EOL> for node in self . nodes : <EOL> if node . is_leaf ( ) : <EOL> start_node = node <EOL> break <EOL> q . put ( start_node ) <EOL> while not q . empty ( ) : <EOL> current_node = q . get ( ) <EOL> if DEBUG : <EOL> print "<STR_LIT>" , current_node <EOL> print "<STR_LIT>" , discovered_nodes <EOL> if current_node . name in discovered_nodes : <EOL> if DEBUG : <EOL> print '<STR_LIT>' , current_node <EOL> return True <EOL> discovered_nodes . add ( current_node . name ) <EOL> if DEBUG : <EOL> print "<STR_LIT>" , discovered_nodes <EOL> for neighbour in current_node . neighbours : <EOL> edge = [ current_node . name , neighbour . name ] <EOL> edge . sort ( ) <EOL> edge = tuple ( edge ) <EOL> if edge not in traversed_edges : <EOL> if neighbour . name in discovered_nodes : <EOL> return True <EOL> if neighbour . name not in discovered_nodes : <EOL> if DEBUG : <EOL> print '<STR_LIT>' % neighbour <EOL> q . put ( neighbour ) <EOL> traversed_edges . add ( edge ) <EOL> return False <EOL> def verify ( self ) : <EOL> '''<STR_LIT>''' <EOL> for node in self . nodes : <EOL> if not isinstance ( node , VariableNode ) and not isinstance ( node , FactorNode ) : <EOL> bases = node . __class__ . __bases__ <EOL> if not VariableNode in bases and not FactorNode in bases : <EOL> print ( '<STR_LIT>' <EOL> '<STR_LIT>' % node . __class__ ) <EOL> raise InvalidGraphException <EOL> print '<STR_LIT>' <EOL> for node in self . nodes : <EOL> if not node . verify_neighbour_types ( ) : <EOL> print '<STR_LIT>' % node <EOL> return False <EOL> print '<STR_LIT>' <EOL> for node in self . nodes : <EOL> if isinstance ( node , FactorNode ) : <EOL> if not hasattr ( node . func , '<STR_LIT>' ) : <EOL> print '<STR_LIT>' % node <EOL> raise InvalidGraphException <EOL> elif not node . func . domains : <EOL> print '<STR_LIT>' % node <EOL> raise InvalidGraphException <EOL> print '<STR_LIT>' + '<STR_LIT>' <EOL> variables = set ( [ vn . name for vn in self . nodes <EOL> if isinstance ( vn , VariableNode ) ] ) <EOL> largs = [ get_args ( fn . func ) for fn in <EOL> self . nodes if isinstance ( fn , FactorNode ) ] <EOL> args = set ( reduce ( lambda x , y : x + y , largs ) ) <EOL> if not variables . issubset ( args ) : <EOL> print '<STR_LIT>' <EOL> print variables . difference ( args ) <EOL> return False <EOL> print '<STR_LIT>' <EOL> if not args . issubset ( variables ) : <EOL> print '<STR_LIT>' <EOL> print args . difference ( variables ) <EOL> return False <EOL> print '<STR_LIT>' <EOL> leaf_nodes = filter ( <EOL> lambda x : x . is_leaf ( ) , <EOL> self . nodes ) <EOL> if not leaf_nodes : <EOL> print '<STR_LIT>' <EOL> raise InvalidGraphException <EOL> return True <EOL> def get_leaves ( self ) : <EOL> return [ node for node in self . nodes if node . is_leaf ( ) ] <EOL> def get_eligible_senders ( self ) : <EOL> '''<STR_LIT>''' <EOL> eligible = [ ] <EOL> for node in self . nodes : <EOL> if node . get_target ( ) : <EOL> eligible . append ( node ) <EOL> return eligible <EOL> def propagate ( self ) : <EOL> '''<STR_LIT>''' <EOL> step = <NUM_LIT:1> <EOL> while True : <EOL> eligible_senders = self . get_eligible_senders ( ) <EOL> if not eligible_senders : <EOL> break <EOL> for node in eligible_senders : <EOL> message = node . construct_message ( ) <EOL> node . send ( message ) <EOL> step += <NUM_LIT:1> <EOL> def variable_nodes ( self ) : <EOL> return [ n for n in self . nodes if isinstance ( n , VariableNode ) ] <EOL> def factor_nodes ( self ) : <EOL> return [ n for n in self . nodes if isinstance ( n , FactorNode ) ] <EOL> def get_normalizer ( self ) : <EOL> for node in self . variable_nodes ( ) : <EOL> if node . value is not None : <EOL> normalizer = node . marginal ( node . value ) <EOL> return normalizer <EOL> return <NUM_LIT:1> <EOL> def status ( self , omit = [ False , <NUM_LIT:0> ] ) : <EOL> normalizer = self . get_normalizer ( ) <EOL> retval = dict ( ) <EOL> for node in self . variable_nodes ( ) : <EOL> for value in node . domain : <EOL> m = node . marginal ( value , normalizer ) <EOL> retval [ ( node . name , value ) ] = m <EOL> return retval <EOL> def query_by_propagation ( self , ** kwds ) : <EOL> self . reset ( ) <EOL> for k , v in kwds . items ( ) : <EOL> for node in self . variable_nodes ( ) : <EOL> if node . name == k : <EOL> add_evidence ( node , v ) <EOL> self . propagate ( ) <EOL> return self . status ( ) <EOL> def query ( self , ** kwds ) : <EOL> if self . inference_method == '<STR_LIT>' : <EOL> return self . query_by_external_samples ( ** kwds ) <EOL> elif self . inference_method == '<STR_LIT>' : <EOL> return self . query_by_sampling ( ** kwds ) <EOL> elif self . inference_method == '<STR_LIT>' : <EOL> return self . query_by_propagation ( ** kwds ) <EOL> raise InvalidInferenceMethod <EOL> def q ( self , ** kwds ) : <EOL> '''<STR_LIT>''' <EOL> result = self . query ( ** kwds ) <EOL> tab = PrettyTable ( [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] , sortby = '<STR_LIT>' ) <EOL> tab . align = '<STR_LIT:l>' <EOL> tab . align [ '<STR_LIT>' ] = '<STR_LIT:r>' <EOL> tab . float_format = '<STR_LIT>' <EOL> for ( node , value ) , prob in result . items ( ) : <EOL> if kwds . get ( node , '<STR_LIT>' ) == value : <EOL> tab . add_row ( [ '<STR_LIT>' % node , <EOL> '<STR_LIT>' % ( GREEN , value , NORMAL ) , <EOL> '<STR_LIT>' % prob ] ) <EOL> else : <EOL> tab . add_row ( [ node , value , '<STR_LIT>' % prob ] ) <EOL> print tab <EOL> def discover_sample_ordering ( self ) : <EOL> return discover_sample_ordering ( self ) <EOL> def get_sample ( self , evidence = { } ) : <EOL> '''<STR_LIT>''' <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . sample_ordering = self . discover_sample_ordering ( ) <EOL> return get_sample ( self . sample_ordering , evidence ) <EOL> def query_by_sampling ( self , ** kwds ) : <EOL> counts = defaultdict ( int ) <EOL> valid_samples = <NUM_LIT:0> <EOL> while valid_samples < self . n_samples : <EOL> print "<STR_LIT>" % ( valid_samples , self . n_samples ) <EOL> try : <EOL> sample = self . get_sample ( kwds ) <EOL> valid_samples += <NUM_LIT:1> <EOL> except : <EOL> print '<STR_LIT>' <EOL> print '<STR_LIT>' <EOL> continue <EOL> for var in sample : <EOL> key = ( var . name , var . value ) <EOL> counts [ key ] += <NUM_LIT:1> <EOL> normalized = dict ( <EOL> [ ( k , v / valid_samples ) for k , v in counts . items ( ) ] ) <EOL> return normalized <EOL> def generate_samples ( self , n ) : <EOL> '''<STR_LIT>''' <EOL> if self . inference_method != '<STR_LIT>' : <EOL> raise IncorrectInferenceMethodError ( <EOL> '<STR_LIT>' % self . inference_method ) <EOL> valid_samples = <NUM_LIT:0> <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . sample_ordering = self . discover_sample_ordering ( ) <EOL> fn = [ x [ <NUM_LIT:0> ] . name for x in self . sample_ordering ] <EOL> sdb = self . sample_db <EOL> while valid_samples < n : <EOL> try : <EOL> sample = self . get_sample ( ) <EOL> except InvalidSampleException : <EOL> continue <EOL> sdb . save_sample ( [ ( v . name , v . value ) for v in sample ] ) <EOL> valid_samples += <NUM_LIT:1> <EOL> sdb . commit ( ) <EOL> print '<STR_LIT>' % ( n , self . sample_db_filename ) <EOL> def query_by_external_samples ( self , ** kwds ) : <EOL> counts = defaultdict ( int ) <EOL> samples = self . sample_db . get_samples ( self . n_samples , ** kwds ) <EOL> if len ( samples ) == <NUM_LIT:0> : <EOL> raise NoSamplesInDB ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> if len ( samples ) < self . n_samples and self . enforce_minimum_samples : <EOL> raise InsufficientSamplesException ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> for sample in samples : <EOL> for name , val in sample . items ( ) : <EOL> key = ( name , val ) <EOL> counts [ key ] += <NUM_LIT:1> <EOL> normalized = dict ( <EOL> [ ( k , v / len ( samples ) ) for k , v in counts . items ( ) ] ) <EOL> return normalized <EOL> def export ( self , filename = None , format = '<STR_LIT>' ) : <EOL> '''<STR_LIT>''' <EOL> if filename : <EOL> fh = open ( filename , '<STR_LIT:w>' ) <EOL> else : <EOL> fh = sys . stdout <EOL> if format != '<STR_LIT>' : <EOL> raise '<STR_LIT>' <EOL> fh . write ( '<STR_LIT>' ) <EOL> fh . write ( '<STR_LIT>' ) <EOL> edges = set ( ) <EOL> for node in self . nodes : <EOL> if isinstance ( node , FactorNode ) : <EOL> fh . write ( '<STR_LIT>' % node . name ) <EOL> else : <EOL> fh . write ( '<STR_LIT>' % node . name ) <EOL> for node in self . nodes : <EOL> for neighbour in node . neighbours : <EOL> edge = [ node . name , neighbour . name ] <EOL> edge = tuple ( sorted ( edge ) ) <EOL> edges . add ( edge ) <EOL> for source , target in edges : <EOL> fh . write ( '<STR_LIT>' % ( source , target ) ) <EOL> fh . write ( '<STR_LIT>' ) <EOL> def build_graph ( * args , ** kwds ) : <EOL> '''<STR_LIT>''' <EOL> variables = set ( ) <EOL> domains = kwds . get ( '<STR_LIT>' , { } ) <EOL> name = kwds . get ( '<STR_LIT:name>' ) <EOL> variable_nodes = dict ( ) <EOL> factor_nodes = [ ] <EOL> if isinstance ( args [ <NUM_LIT:0> ] , list ) : <EOL> args = args [ <NUM_LIT:0> ] <EOL> for factor in args : <EOL> factor_args = get_args ( factor ) <EOL> variables . update ( factor_args ) <EOL> factor_node = FactorNode ( factor . __name__ , factor ) <EOL> factor_nodes . append ( factor_node ) <EOL> for variable in variables : <EOL> node = VariableNode ( <EOL> variable , <EOL> domain = domains . get ( variable , [ True , False ] ) ) <EOL> variable_nodes [ variable ] = node <EOL> for factor_node in factor_nodes : <EOL> factor_args = get_args ( factor_node . func ) <EOL> connect ( factor_node , [ variable_nodes [ x ] for x in factor_args ] ) <EOL> graph = FactorGraph ( variable_nodes . values ( ) + factor_nodes , name = name ) <EOL> return graph </s>
