Source code for pynfg.pgtsolutions.intelligence.iq

# -*- coding: utf-8 -*-
"""
Implements PGT intelligence for SemiNFG objects

Part of: PyNFG - a Python package for modeling and solving Network Form Games

Created on Mon Feb 25 12:07:49 2013

Copyright (C) 2013 James Bono (jwbono@gmail.com)

GNU Affero General Public License

"""
from __future__ import division
import copy
import numpy as np
#from classes import *
from iq_iterated import mh_decision

[docs]def iq_MC(G, S, X, M, integrand=None, mix=False): """Run MC outer loop on random policies for SemiNFG IQ calcs :arg G: the semiNFG to be evaluated :type G: SemiNFG :arg S: number of policy profiles to sample :type S: int :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 integrand: a user-supplied function of G that is evaluated for each s in S :type integrand: func :arg pure: True if restricting sampling to pure strategies. False if mixed strategies are included in sampling. Default is True. """ intel = {} #keys are dn names, vals are iq time series funcout = {} #keys are s in S, vals are eval of integrand of G(s) dnlist = [d.name for d in G.nodes if isinstance(d, pynfg.DecisionNode)] for dn in dnlist: intel[dn] = [] for s in xrange(S): #sampling S policy profiles for dn in dnlist: G.node_dict[dn].randomCPT(mixed=mix, setCPT=True) #drawing current policy for dn in dnlist: #find the iq of each player's policy in turn intel[dn].append(iq_calc(dn, G, X, M)) if integrand is not None: funcout[s] = integrand(G) #eval integrand G(s), assign to funcout return intel, funcout
[docs]def iq_MH(G, S, X, M, noise, dens, integrand=None, mix=False, seed=[]): """Run MH for SemiNFG with IQ calcs :arg G: the SemiNFG to be evaluated :type G: SemiNFG :arg S: number of MH iterations :type S: int :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 dens: the function that assigns weights to iq :type dens: func :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 delta: the discount factor :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 seed: list of names of DecisionNodes that have been seeded. DecisionNodes that are not named in seed use a uniform CPT as a starting point. :type seed: list """ intel = {} #keys are s in S, vals are iq dict (dict of dicts) dnlist = [d.name for d in G.nodes if isinstance(d, pynfg.DecisionNode)] for dn in dnlist: intel[dn] = [0] #init intel dict funcout = {} #keys are s in S, vals are eval of integrand of G(s) funcout[0] = 0 propiq = {} #dict of proposal iq, keys are names seedlist = [dn for dn in dnlist if dn not in seed] for x in seedlist: #if not seeded, DNs start uniform G.node_dict[dn].uniformCPT() for s in xrange(1,S+1): #sampling S sequences of policy profiles GG = copy.deepcopy(G) for dn in dnlist: GG.node_dict[dn].CPT = G.node_dict[dn].perturbCPT(noise, mixed=mix, \ setCPT=False) #drawing current policy for dn in dnlist: propiq[dn] = iq_calc(dn, GG, X, M) #getting iq # The MH decision verdict = mh_decision(dens(propiq[dn]), dens(intel[dn][-1])) if verdict: #accepting new CPT intel[dn].append(propiq[dn]) G.node_dict[dn].CPT = GG.node_dict[dn].CPT else: intel[dn].append(intel[dn][-1]) if integrand is not None: funcout[s] = integrand(G) #eval integrand G(s), assign to funcout return intel, funcout
[docs]def iq_calc(dn, G, X, M): """Calc IQ of policy at dn in G :arg dn: the name of the DN to be evaluated :type dn: str :arg G: the semiNFG to be evaluated :type G: SemiNFG :arg X: number of samples of each policy profile :type X: int :arg M: number of random alt policies with which to compare :type M: int """ p = G.node_dict[dn].player util = 0 for x in xrange(1,X+1): G.sample() util = (G.utility(p)+(x-1)*util)/x altutil = [0]*M G1 = copy.deepcopy(G) for m in range(0,M): #Sample M alt policies for the player G1.node_dict[dn].randomCPT(setCPT=True) #rand for the DN G1.sample() #sample altpolicy prof. to end of net altutil[m] = G1.utility(p) #get alt utility worse = [j for j in altutil if j<=util] #alts worse than G return len(worse)/M #fraction of alts worse than G is IQ