def coordinated_MH(G, S, density, noise, X, M, innoise=1, delta=1, integrand=None, mix=False, satisfice=None): """Run Metropolis-Hastings on strategies for PGT Intelligence Calculations For examples, see below or PyNFG/bin/stackelberg.py for SemiNFG or PyNFG/bin/hideandseek.py for iterSemiNFG :arg G: the game to be evaluated :type G: SemiNFG or iterSemiNFG :arg S: number of MH iterations :type S: int :arg density: the function that assigns weights to iq :type density: func :arg noise: the degree of independence of the proposal distribution on the current value. 1 is independent, 0 returns no perturbation. :type noise: float :arg X: number of samples of each policy profile :type X: int :arg M: number of random alt policies to compare :type M: int :arg innoise: the perturbation noise for the loop within iq_calc to draw alt CPTs to compare utilities to current CPT. :type innoise: float :arg delta: the discount factor (ignored if SemiNFG) :type delta: float :arg integrand: a user-supplied function of G that is evaluated for each s in S :type integrand: func :arg mix: if true, proposal distribution is over mixed CPTs. Default is False. :type mix: bool :arg satisfice: game G such that the CPTs of G together with innoise determine the intelligence satisficing distribution. :type satisfice: SemiNFG or iterSemiNFG :returns: * intel - a sample-keyed dictionary of player-keyed iq dictionaries * funcout - a sample-keyed dictionary of the output of the user-supplied integrand. * dens - a list of the density values, one for each MH draw. .. note:: This is the coordinated-approach because intelligence is assigned to a player instead of being assigned to a DecisionNode Example:: def density(iqdict): #calculate the PGT density for a given iqdict x = iqdict.values() y = np.power(x,2) z = np.product(y) return z def welfare(G): #calculate the welfare of a single sample of the SemiNFG G G.sample() w = G.utility('1')+G.utility('2') #'1' & '2' are player names in G return w import copy GG = copy.deepcopy(G) #G is a SemiNFG S = 50 #number of MH samples X = 10 #number of samples of utility of G in calculating iq M = 20 #number of alternative strategies sampled in calculating iq noise = .2 #noise in the perturbations of G for MH sampling from pynfg.pgtsolutions.intelligence.coordinated import coordinated_MH intelMH, funcoutMH, densMH = coordinated_MH(GG, S, density, noise, X, M, innoise=.2, delta=1, integrand=welfare, mix=False, satisfice=GG) """ intel = {} # keys are s in S, vals are iq dict (dict of dicts) iq = {} # keys are base names, iq timestep series funcout = {} # keys are s in S, vals are eval of integrand of G(s) dens = np.zeros(S + 1) # storing densities for return for s in xrange(1, S + 1): # sampling S sequences of policy profiles sys.stdout.write("\r") sys.stdout.write("MH Sample " + str(s)) sys.stdout.flush() GG = copy.deepcopy(G) for p in GG.players: for dn in GG.partition[p]: # drawing current policy dn.perturbCPT(noise, mixed=mix) for p in GG.players: # getting iq iq[p] = coordinated_calciq(p, GG, X, M, mix, delta, innoise, satisfice) # The MH decision current_dens = density(iq) verdict = mh_decision(current_dens, dens[s - 1]) if verdict: # accepting new CPT intel[s] = copy.deepcopy(iq) G = copy.deepcopy(GG) dens[s] = current_dens else: intel[s] = intel[s - 1] dens[s] = dens[s - 1] if integrand is not None: funcout[s] = integrand(G) # eval integrand G(s), assign to funcout return intel, funcout, dens[1::]
def iterated_MH(G, S, density, noise, X, M, innoise=1, delta=1, \ integrand=None, mix=False, satisfice=None): """Run Metropolis-Hastings on policy sequences for PGT IQ Calculations For examples, see below or PyNFG/bin/hideandseek.py :arg G: the game to be evaluated :type G: iterSemiNFG :arg S: number of MH iterations :type S: int :arg density: the function that assigns weights to iq :type density: func :arg noise: the degree of independence of the proposal distribution on the current value. 1 is independent, 0 returns no perturbation. :type noise: float :arg X: number of samples of each policy profile :type X: int :arg M: number of random alt policies to compare :type M: int :arg innoise: the perturbation noise for the loop within iq_calc to draw alt CPTs to compare utilities to current CPT. :type innoise: float :arg delta: the discount factor (ignored if SemiNFG) :type delta: float :arg integrand: a user-supplied function of G that is evaluated for each s in S :type integrand: func :arg mix: if true, proposal distribution is over mixed CPTs. Default is False. :type mix: bool :arg satisfice: game G such that the CPTs of G together with innoise determine the intelligence satisficing distribution. :type satisfice: iterSemiNFG :returns: * intel - a sample-keyed dictionary of basename-keyed timestep iq lists * funcout - a sample-keyed dictionary of the output of the user-supplied integrand. * dens - a list of the density values, one for each MH draw. .. warning:: This will throw an error if there is a decision node in G.starttime that is not repeated throughout the net. .. note:: This is an uncoordinated approach because intelligence is assigned to a decision node instead of players. As a result, it takes much longer to run than pynfg.pgtsolutions.intelligence.policy.policy_MH Example:: def density(iqdict): #calculate the PGT density for a given iqdict x = iqdict.values() y = np.power(x,2) z = np.product(y) return z def welfare(G): #calculate the welfare of a single sample of the iterSemiNFG G G.sample() w = 0 for p in G.players: w += G.npv_reward(p, G.starttime, 1.0) return w import copy GG = copy.deepcopy(G) #G is an iterSemiNFG S = 50 #number of MH samples X = 10 #number of samples of utility of G in calculating iq M = 20 #number of alternative strategies sampled in calculating iq noise = .2 #noise in the perturbations of G for MH sampling from pynfg.pgtsolutions.intelligence.iterated import iterated_MH intelMH, funcoutMH, densMH = iterated_MH(GG, S, density, noise, X, M, innoise=.2, delta=1, integrand=welfare, mix=False, satisfice=GG) """ T0 = G.starttime T = G.endtime dnlist = [d.basename for d in G.time_partition[T0] if \ isinstance(d, DecisionNode)] intel = {} #keys are MC iterations s, values are iq dicts iq = {} #keys are base names, iq timestep series for dn in dnlist: iq[dn] = np.zeros(T-T0+1) #preallocating iqs funcout = {} #keys are s in S, vals are eval of integrand of G(s) dens = np.zeros(S+1) # gather list of decision nodes in base game for s in xrange(1, S+1): #sampling S sequences of policy profiles sys.stdout.write('\r') sys.stdout.write('MH Sample ' + str(s)) sys.stdout.flush() GG = copy.deepcopy(G) for t in xrange(T0, T+1): for dn in dnlist: GG.bn_part[dn][t-T0].CPT = G.bn_part[dn][t-T0].perturbCPT(\ noise, mixed=mix) for dd in GG.bn_part[dn][t-T0+1::]: dd.CPT = GG.bn_part[dn][t-T0].CPT #apply policy to future iq[dn][t-T0] = iterated_calciq(dn, G, X, M, mix, delta, t, \ innoise, satisfice=None) #getting iq # The MH decision current_dens = density(iq) #evaluating density of current draw's iq verdict = mh_decision(current_dens, dens[s-1]) #True if accept new draw if verdict: #accepting new CPT intel[s] = copy.deepcopy(iq) G = copy.deepcopy(GG) dens[s] = current_dens else: intel[s] = intel[s-1] dens[s] = dens[s-1] if integrand is not None: funcout[s] = integrand(G) #eval integrand G(s), assign to funcout return intel, funcout, dens[1::]
def coordinated_MH(G, S, density, noise, X, M, innoise=1, delta=1, \ integrand=None, mix=False, satisfice=None): """Run Metropolis-Hastings on strategies for PGT Intelligence Calculations For examples, see below or PyNFG/bin/stackelberg.py for SemiNFG or PyNFG/bin/hideandseek.py for iterSemiNFG :arg G: the game to be evaluated :type G: SemiNFG or iterSemiNFG :arg S: number of MH iterations :type S: int :arg density: the function that assigns weights to iq :type density: func :arg noise: the degree of independence of the proposal distribution on the current value. 1 is independent, 0 returns no perturbation. :type noise: float :arg X: number of samples of each policy profile :type X: int :arg M: number of random alt policies to compare :type M: int :arg innoise: the perturbation noise for the loop within iq_calc to draw alt CPTs to compare utilities to current CPT. :type innoise: float :arg delta: the discount factor (ignored if SemiNFG) :type delta: float :arg integrand: a user-supplied function of G that is evaluated for each s in S :type integrand: func :arg mix: if true, proposal distribution is over mixed CPTs. Default is False. :type mix: bool :arg satisfice: game G such that the CPTs of G together with innoise determine the intelligence satisficing distribution. :type satisfice: SemiNFG or iterSemiNFG :returns: * intel - a sample-keyed dictionary of player-keyed iq dictionaries * funcout - a sample-keyed dictionary of the output of the user-supplied integrand. * dens - a list of the density values, one for each MH draw. .. note:: This is the coordinated-approach because intelligence is assigned to a player instead of being assigned to a DecisionNode Example:: def density(iqdict): #calculate the PGT density for a given iqdict x = iqdict.values() y = np.power(x,2) z = np.product(y) return z def welfare(G): #calculate the welfare of a single sample of the SemiNFG G G.sample() w = G.utility('1')+G.utility('2') #'1' & '2' are player names in G return w import copy GG = copy.deepcopy(G) #G is a SemiNFG S = 50 #number of MH samples X = 10 #number of samples of utility of G in calculating iq M = 20 #number of alternative strategies sampled in calculating iq noise = .2 #noise in the perturbations of G for MH sampling from pynfg.pgtsolutions.intelligence.coordinated import coordinated_MH intelMH, funcoutMH, densMH = coordinated_MH(GG, S, density, noise, X, M, innoise=.2, delta=1, integrand=welfare, mix=False, satisfice=GG) """ intel = {} #keys are s in S, vals are iq dict (dict of dicts) iq = {} #keys are base names, iq timestep series funcout = {} #keys are s in S, vals are eval of integrand of G(s) dens = np.zeros(S + 1) #storing densities for return for s in xrange(1, S + 1): #sampling S sequences of policy profiles sys.stdout.write('\r') sys.stdout.write('MH Sample ' + str(s)) sys.stdout.flush() GG = copy.deepcopy(G) for p in GG.players: for dn in GG.partition[p]: #drawing current policy dn.perturbCPT(noise, mixed=mix) for p in GG.players: #getting iq iq[p] = coordinated_calciq(p, GG, X, M, mix, delta, innoise, \ satisfice) # The MH decision current_dens = density(iq) verdict = mh_decision(current_dens, dens[s - 1]) if verdict: #accepting new CPT intel[s] = copy.deepcopy(iq) G = copy.deepcopy(GG) dens[s] = current_dens else: intel[s] = intel[s - 1] dens[s] = dens[s - 1] if integrand is not None: funcout[s] = integrand(G) #eval integrand G(s), assign to funcout return intel, funcout, dens[1::]