Example #1
0
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::]
Example #2
0
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::]
Example #3
0
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::]