def probMxl(paramFix, paramRnd, paramRnd2, xFix, xFix_transBool, xFix_trans,
            nFix, xRnd, xRnd_transBool, xRnd_trans, nRnd, xRnd2,
            xRnd2_transBool, xRnd2_trans, nRnd2, nInd, rowsPerInd,
            map_obs_to_ind, map_avail_to_obs):
    """
    vFix = 0; vRnd = 0; vRnd2 = 0;
    if nFix > 0:
        if xFix_transBool: paramFix = transFix(paramFix, xFix_trans)
        vFix = xFix @ paramFix    
    if nRnd > 0:
        if xRnd_transBool: paramRnd = transRnd(paramRnd, xRnd_trans)
        paramRndPerRow = np.repeat(paramRnd, rowsPerInd, axis = 0)
        vRnd = np.sum(xRnd * paramRndPerRow, axis = 1) 
    if nRnd2 > 0:
        if xRnd2_transBool: paramRnd2 = transRnd(paramRnd2, xRnd_trans)
        paramRnd2PerRow = np.repeat(paramRnd2, rowsPerInd, axis = 0)
        vRnd2 = np.sum(xRnd2 * paramRnd2PerRow, axis = 1)            
    v = vFix + vRnd + vRnd2
    """
    if xRnd_transBool: paramRnd = transRnd(paramRnd, xRnd_trans)
    paramRndPerRow = np.repeat(paramRnd, rowsPerInd, axis=0)
    if xRnd2_transBool: paramRnd2 = transRnd(paramRnd2, xRnd2_trans)
    paramRnd2PerRow = np.repeat(paramRnd2, rowsPerInd, axis=0)

    v = xRnd[:,0] * paramRndPerRow[:,0] \
        + paramRndPerRow[:,1] * (xRnd[:,1] + np.sum(xRnd2 * paramRnd2PerRow, axis = 1))

    ev = np.exp(v)
    ev[ev > 1e+200] = 1e+200
    ev[ev < 1e-300] = 1e-300
    nev = map_avail_to_obs.T @ ev + 1
    pChosen = 1 / nev
    lPChosen = np.log(pChosen)
    lPInd = map_obs_to_ind.T @ lPChosen
    return lPInd
def mcmcChainPredW(
        chainID, seed,
        mcmc_iterSampleThin, mcmc_disp,
        modelName,
        xFix, xFix_transBool, xFix_trans, nFix, 
        xRnd, xRnd_transBool, xRnd_trans, nRnd, 
        xRnd2, xRnd2_transBool, xRnd2_trans, nRnd2, 
        nInd, nObs, nRow,
        rowsPerInd, map_avail_to_obs, chosenIdx, nonChosenIdx):   
    
    np.random.seed(seed + chainID)
    
    ###
    #Retrieve draws
    ###
    
    fileName = modelName + '_draws_chain' + str(chainID + 1) + '.hdf5'
    file = h5py.File(fileName, "r")
    
    paramFix_store = None
    paramRnd_store = None
    paramRnd2_store = None
    if nFix: paramFix_store = np.array(file['paramFix_store'])
    if nRnd: paramRnd_store = np.array(file['paramRnd_store'][:,:nInd,:])
    if nRnd2: paramRnd2_store = np.array(file['paramRnd2_store'][:,:nInd,:])
    
    ###
    #Simulate
    ###

    pPred = np.zeros((mcmc_iterSampleThin, nRow + nObs))
    vFix = 0; vRnd = 0; vRnd2 = 0;
    
    for i in np.arange(mcmc_iterSampleThin):
        if nFix: 
            paramFix = np.array(paramFix_store[i,:])
            if xFix_transBool: paramFix = transFix(paramFix, xFix_trans)
            #vFix = xFix @ paramFix
        if nRnd:
            paramRnd = paramRnd_store[i,:,:]
            if xRnd_transBool: paramRnd = transRnd(paramRnd, xRnd_trans)
            paramRndPerRow = np.repeat(paramRnd, rowsPerInd, axis = 0)
            #vRnd = np.sum(xRnd * paramRndPerRow, axis = 1)
        if nRnd2:
            paramRnd2 = paramRnd2_store[i,:,:]
            if xRnd2_transBool: paramRnd2 = transRnd(paramRnd2, xRnd2_trans)
            paramRnd2PerRow = np.repeat(paramRnd2, rowsPerInd, axis = 0)
            #vRnd2 = np.sum(xRnd2 * paramRnd2PerRow, axis = 1)
        #v = vFix + vRnd + vRnd2
        v = xRnd[:,0] * paramRndPerRow[:,0] \
        + paramRndPerRow[:,1] * (xRnd[:,1] + np.sum(xRnd[:,2:] * paramRndPerRow[:,2:], axis = 1))
        pPred[i,:] = pPredMxl(v, map_avail_to_obs, 1, chosenIdx, nonChosenIdx)
        
        if ((i + 1) % mcmc_disp) == 0:
            print('Chain ' + str(chainID + 1) + '; iteration: ' + str(i + 1) + ' (predictive simulation)')
            sys.stdout.flush()
    return pPred
def condExpInd(paramFix_est, paramRndUc_mu_est, paramRndUc_sd_est,
               paramRndCo_mu_est, paramRndCo_ch_est, xFix, xFix_transBool,
               xFix_trans, nFix, xRndUc, xRndUc_transBool, xRndUc_trans,
               nRndUc, xRndCo, xRndCo_transBool, xRndCo_trans, nRndCo, nInd,
               rowsPerInd, map_obs_to_ind, map_avail_to_obs, nSim):

    if nRndUc: paramRndUc_draws = np.zeros((nSim, nInd, nRndUc))
    if nRndCo: paramRndCo_draws = np.zeros((nSim, nInd, nRndCo))
    pInd_draws = np.zeros((nSim, nInd))

    vFix = 0
    vRndUc = 0
    vRndCo = 0

    if nFix > 0: vFix = xFix @ paramFix_est

    for i in np.arange(nSim):
        if nRndUc > 0:
            paramRndUc = paramRndUc_mu_est + paramRndUc_sd_est * np.random.randn(
                nInd, nRndUc)
            paramRndUc_draws[i, :, :] = paramRndUc
            if xRndUc_transBool:
                paramRndUc = np.array(transRnd(paramRndUc, xRndUc_trans))
            paramRndUcPerRow = np.repeat(paramRndUc, rowsPerInd, axis=0)
            vRndUc = np.sum(xRndUc * paramRndUcPerRow, axis=1)

        if nRndCo > 0:
            paramRndCo = paramRndCo_mu_est + (
                paramRndCo_ch_est @ np.random.randn(nRndCo, nInd)).T
            paramRndCo_draws[i, :, :] = paramRndCo
            if xRndCo_transBool:
                paramRndCo = np.array(transRnd(paramRndCo, xRndCo_trans))
            paramRndCoPerRow = np.repeat(paramRndCo, rowsPerInd, axis=0)
            vRndCo = np.sum(xRndCo * paramRndCoPerRow, axis=1)

        v = vFix + vRndUc + vRndCo
        pInd_draws[i, :] = probMxl(v, map_obs_to_ind, map_avail_to_obs)

    denom = np.mean(pInd_draws, axis=0)
    pInd_draws = np.array(pInd_draws).reshape((nSim, nInd, 1))

    paramRndUc_ind = None
    paramRndCo_ind = None

    if nRndUc > 0:
        numer = np.mean(paramRndUc_draws * pInd_draws, axis=0)
        paramRndUc_ind = numer / denom.reshape((nInd, 1))
    if nRndCo > 0:
        numer = np.mean(paramRndCo_draws * pInd_draws, axis=0)
        paramRndCo_ind = numer / denom.reshape((nInd, 1))

    return paramRndUc_ind, paramRndCo_ind
Ejemplo n.º 4
0
def probMxl(paramFix, paramRnd, xFix, xFix_transBool, xFix_trans, nFix, xRnd,
            xRnd_transBool, xRnd_trans, nRnd, nInd, rowsPerInd, map_obs_to_ind,
            map_avail_to_obs):
    vFix = 0
    vRnd = 0
    if nFix > 0:
        if xFix_transBool: paramFix = transFix(paramFix, xFix_trans)
        vFix = xFix @ paramFix
        vFix = xFix[:,0] * paramFix[0] \
            + np.exp(paramFix[1]) * (xFix[:,1] + xFix[:,2:] @ paramFix[2:])
    if nRnd > 0:
        if xRnd_transBool: paramRnd = transRnd(paramRnd, xRnd_trans)
        paramRndPerRow = np.repeat(paramRnd, rowsPerInd, axis=0)
        #vRnd = paramRndPerRow[:,0] * (xRnd[:,0] + np.sum(xRnd[:,1:] * paramRndPerRow[:,1:], axis = 1))
        vRnd = xRnd[:,0] * paramRndPerRow[:,0] \
        + paramRndPerRow[:,1] * (xRnd[:,1] + np.sum(xRnd[:,2:] * paramRndPerRow[:,2:], axis = 1))
    v = vFix + vRnd
    ev = np.exp(v)
    ev[ev > 1e+200] = 1e+200
    ev[ev < 1e-300] = 1e-300
    nev = map_avail_to_obs.T @ ev + 1
    pChosen = 1 / nev
    lPChosen = np.log(pChosen)
    lPInd = map_obs_to_ind.T @ lPChosen
    return lPInd
Ejemplo n.º 5
0
def probMxl(paramRndW, xRnd, xRnd_transBool, xRnd_trans, rowsPerObs,
            map_avail_to_obs):

    if xRnd_transBool: paramRndW = transRnd(paramRndW, xRnd_trans)
    paramRndWPerRow = np.repeat(paramRndW, rowsPerObs, axis=0)
    v = np.sum(xRnd * paramRndWPerRow, axis=1)

    ev = np.exp(v)
    ev[ev > 1e+200] = 1e+200
    ev[ev < 1e-300] = 1e-300
    nev = map_avail_to_obs.T @ ev + 1
    pChosen = 1 / nev
    lPChosen = np.log(pChosen)
    return pChosen, lPChosen
def mcmcChainPredB(chainID, seed, mcmc_iterSampleThin, mcmc_disp, nTakes, nSim,
                   modelName, xFix, xFix_transBool, xFix_trans, nFix, sim_xRnd,
                   xRnd_transBool, xRnd_trans, nRnd, sim_xRnd2,
                   xRnd2_transBool, xRnd2_trans, nRnd2, nInd, nObs, nRow,
                   sim_rowsPerInd, sim_map_avail_to_obs, chosenIdx,
                   nonChosenIdx):

    np.random.seed(seed + chainID)

    ###
    #Retrieve draws
    ###

    fileName = modelName + '_draws_chain' + str(chainID + 1) + '.hdf5'
    file = h5py.File(fileName, "r")

    paramFix_store = None
    zeta_store = None
    Omega_store = None
    zeta2_store = None
    Omega2_store = None
    pi_store = None
    nComp = None
    if nFix:
        paramFix_store = np.array(file['paramFix_store'])
    if nRnd:
        zeta_store = np.array(file['zeta_store'])
        Omega_store = np.array(file['Omega_store'])
    if nRnd2:
        zeta2_store = np.array(file['zeta2_store'])
        Omega2_store = np.array(file['Omega2_store'])
        pi_store = np.array(file['pi_store'])
        nComp = pi_store.shape[1]

    ###
    #Simulate
    ###

    pPred = np.zeros((mcmc_iterSampleThin, nRow + nObs))
    vFix = 0
    vRnd = 0
    vRnd2 = 0

    for i in np.arange(mcmc_iterSampleThin):

        if nFix:
            paramFix = paramFix_store[i, :]
            if xFix_transBool: paramFix = transFix(paramFix, xFix_trans)
            vFix = np.tile(xFix @ paramFix, (nSim, ))
        if nRnd:
            zeta_tmp = zeta_store[i, :]
            ch_tmp = np.linalg.cholesky(Omega_store[i, :, :])
        if nRnd2:
            zeta2_tmp = zeta2_store[i, :, :]
            Omega2_tmp = Omega2_store[i, :, :, :]
            pi_tmp = pi_store[i, :]

        pPred_take = 0

        for t in np.arange(nTakes):
            if nRnd:
                paramRnd = zeta_tmp + (
                    ch_tmp @ np.random.randn(nRnd, nInd * nSim)).T
                if xRnd_transBool: paramRnd = transRnd(paramRnd, xRnd_trans)
                paramRndPerRow = np.repeat(paramRnd, sim_rowsPerInd, axis=0)
                #vRnd = np.sum(sim_xRnd * paramRndPerRow, axis = 1)
            if nRnd2:
                q = np.random.choice(np.arange(nComp),
                                     size=nInd * nSim,
                                     replace=True,
                                     p=pi_tmp)
                paramRnd2 = monrnd(zeta2_tmp, Omega2_tmp, q)
                if xRnd2_transBool:
                    paramRnd2 = transRnd(paramRnd2, xRnd2_trans)
                paramRnd2PerRow = np.repeat(paramRnd2, sim_rowsPerInd, axis=0)
                #vRnd2 = np.sum(sim_xRnd2 * paramRnd2PerRow, axis = 1)
            #v = vFix + vRnd + vRnd2
            v = sim_xRnd[:,0] * paramRndPerRow[:,0] \
                + paramRndPerRow[:,1] * (sim_xRnd[:,1] + np.sum(sim_xRnd2 * paramRnd2PerRow, axis = 1))
            pPred_take += pPredMxl(v, sim_map_avail_to_obs, nSim, chosenIdx,
                                   nonChosenIdx)

        pPred[i, :] = pPred_take / nTakes

        if ((i + 1) % mcmc_disp) == 0:
            print('Chain ' + str(chainID + 1) + '; iteration: ' + str(i + 1) +
                  ' (predictive simulation)')
            sys.stdout.flush()
    return pPred
def probGrMxl(param, sim_xFix, xFix_transBool, xFix_trans, nFix, sim_xRndUc,
              xRndUc_transBool, xRndUc_trans, nRndUc, sim_xRndCo,
              xRndCo_transBool, xRndCo_trans, nRndCo, chIdx, drawsUcTake,
              drawsCoTake, nDrawsMem, nInd, sim_rowsPerInd, sim_map_obs_to_ind,
              sim_map_avail_to_obs, sim_map_ind_to_avail,
              sim_map_draws_to_ind):
    ###
    #Utility
    ###

    vFix = 0
    vRndUc = 0
    vRndCo = 0
    u = 0
    if nFix > 0:
        l = u
        u += nFix
        paramFix = np.array(param[l:u])
        if xFix_transBool: paramFix = np.array(transFix(paramFix, xFix_trans))
        vFix = sim_xFix @ paramFix
    if nRndUc > 0:
        l = u
        u += nRndUc
        paramRndUc_mu = np.array(param[l:u])
        l = u
        u += nRndUc
        paramRndUc_sd = np.array(param[l:u])
        paramRndUc = paramRndUc_mu + paramRndUc_sd * drawsUcTake
        if xRndUc_transBool:
            paramRndUc = np.array(transRnd(paramRndUc, xRndUc_trans))
        paramRndUcPerRow = np.repeat(paramRndUc, sim_rowsPerInd, axis=0)
        vRndUc = np.sum(sim_xRndUc * paramRndUcPerRow, axis=1)
    if nRndCo > 0:
        l = u
        u += nRndCo
        paramRndCo_mu = np.array(param[l:u])
        l = u
        paramRndCo_ch = np.zeros((nRndCo, nRndCo))
        paramRndCo_ch[chIdx] = np.array(param[l:])
        paramRndCo = paramRndCo_mu + (paramRndCo_ch @ drawsCoTake.T).T
        if xRndCo_transBool:
            paramRndCo = np.array(transRnd(paramRndCo, xRndCo_trans))
        paramRndCoPerRow = np.repeat(paramRndCo, sim_rowsPerInd, axis=0)
        vRndCo = np.sum(sim_xRndCo * paramRndCoPerRow, axis=1)

    v = vFix + vRndUc + vRndCo

    ###
    #Probability
    ###

    ev = np.exp(v)
    ev[ev > 1e+200] = 1e+200
    ev[ev < 1e-200] = 1e-200
    nev = sim_map_avail_to_obs.T @ ev + 1
    nnev = sim_map_avail_to_obs * nev
    pChosen = 1 / nev
    pChosen[pChosen < 1e-200] = 1e-200
    pNonChosen = ev / nnev
    pNonChosen[pNonChosen < 1e-200] = 1e-200
    lPChosen = np.log(pChosen)
    lPInd = sim_map_obs_to_ind.T @ lPChosen
    pIndVec = np.exp(lPInd)
    pInd = pIndVec.reshape((nDrawsMem, nInd)).sum(axis=0)

    ###
    #Gradient
    ###

    def calcGradient(der):
        frac = -pNonChosen.reshape((-1, 1)) * der
        summation = sim_map_ind_to_avail @ frac
        prod = pIndVec.reshape((-1, 1)) * summation
        sgr = sim_map_draws_to_ind @ prod
        return sgr

    sgrFix = np.empty((nInd, 0))
    sgrRndUc_mu = np.empty((nInd, 0))
    sgrRndUc_sd = np.empty((nInd, 0))
    sgrRndCo_mu = np.empty((nInd, 0))
    sgrRndCo_ch = np.empty((nInd, 0))

    if nFix > 0:
        derFix = sim_xFix
        if xFix_transBool:
            derFix = np.array(transDerFix(derFix, paramFix, xFix_trans))
        sgrFix = calcGradient(derFix)

    if nRndUc > 0:
        derRndUc_mu, derRndUc_sd = derRnd(nInd, nDrawsMem, nRndUc,
                                          xRndUc_transBool, paramRndUc,
                                          xRndUc_trans, chIdx, drawsUcTake,
                                          sim_rowsPerInd, True)
        derRndUc_mu *= sim_xRndUc
        derRndUc_sd *= sim_xRndUc
        sgrRndUc_mu = calcGradient(derRndUc_mu)
        sgrRndUc_sd = calcGradient(derRndUc_sd)

    if nRndCo > 0:
        derRndCo_mu, derRndCo_ch = derRnd(nInd, nDrawsMem, nRndCo,
                                          xRndCo_transBool, paramRndCo,
                                          xRndCo_trans, chIdx, drawsCoTake,
                                          sim_rowsPerInd, False)
        derRndCo_mu *= sim_xRndCo
        derRndCo_ch *= sim_xRndCo[:, chIdx[0]]
        sgrRndCo_mu = calcGradient(derRndCo_mu)
        sgrRndCo_ch = calcGradient(derRndCo_ch)

    sgr = np.concatenate(
        (sgrFix, sgrRndUc_mu, sgrRndUc_sd, sgrRndCo_mu, sgrRndCo_ch), axis=1)

    return pInd, sgr
def probGrMxl(param, sim_xFix, xFix_transBool, xFix_trans, nFix, sim_xRndUc,
              xRndUc_transBool, xRndUc_trans, nRndUc, sim_xRndCo,
              xRndCo_transBool, xRndCo_trans, nRndCo, chIdx, sim_xRnd2Uc,
              xRnd2Uc_transBool, xRnd2Uc_trans, nRnd2Uc, sim_xRnd2Co,
              xRnd2Co_transBool, xRnd2Co_trans, nRnd2Co, ch2Idx, drawsUcTake,
              drawsCoTake, nDrawsMem, drawsUcBTake, drawsCoBTake, nDrawsBMem,
              drawsUcWTake, drawsCoWTake, nDrawsWMem, nInd, nObs,
              simB_rowsPerInd, simB_obsPerInd, simW_rowsPerObs,
              simW_map_avail_to_obs, simW_map_drawsB_to_obs):
    ###
    #Utility
    ###

    vFix = 0
    vRndUc = 0
    vRndCo = 0
    vRnd2Uc = 0
    vRnd2Co = 0
    u = 0
    if nFix > 0:
        l = u
        u += nFix
        paramFix = np.array(param[l:u])
        if xFix_transBool: paramFix = np.array(transFix(paramFix, xFix_trans))
        vFix = sim_xFix @ paramFix  #Good
    if nRndUc > 0:
        l = u
        u += nRndUc
        paramRndUc_mu = np.array(param[l:u])
        l = u
        u += nRndUc
        paramRndUc_sd = np.array(param[l:u])
        paramRndUc = paramRndUc_mu + paramRndUc_sd * drawsUcTake
        if xRndUc_transBool:
            paramRndUc = np.array(transRnd(paramRndUc, xRndUc_trans))
        paramRndUcPerRow = np.tile(
            np.repeat(paramRndUc, simB_rowsPerInd, axis=0),
            (nDrawsWMem, 1))  #Good
        vRndUc = np.sum(sim_xRndUc * paramRndUcPerRow, axis=1)
    if nRndCo > 0:
        l = u
        u += nRndCo
        paramRndCo_mu = np.array(param[l:u])
        l = u
        u += int((nRndCo * (nRndCo + 1)) / 2)
        paramRndCo_ch = np.zeros((nRndCo, nRndCo))
        paramRndCo_ch[chIdx] = np.array(param[l:u])
        paramRndCo = paramRndCo_mu + (paramRndCo_ch @ drawsCoTake.T).T
        if xRndCo_transBool:
            paramRndCo = np.array(transRnd(paramRndCo, xRndCo_trans))
        paramRndCoPerRow = np.tile(
            np.repeat(paramRndCo, simB_rowsPerInd, axis=0),
            (nDrawsWMem, 1))  #Good
        vRndCo = np.sum(sim_xRndCo * paramRndCoPerRow, axis=1)
    if nRnd2Uc > 0:
        l = u
        u += nRnd2Uc
        paramRnd2Uc_mu = np.array(param[l:u])
        l = u
        u += nRnd2Uc
        paramRnd2Uc_sdB = np.array(param[l:u])
        l = u
        u += nRnd2Uc
        paramRnd2Uc_sdW = np.array(param[l:u])
        paramRnd2Uc_ind = paramRnd2Uc_mu + paramRnd2Uc_sdB * drawsUcBTake  #Good
        paramRnd2Uc_obs = paramRnd2Uc_sdW * drawsUcWTake  #Good
        paramRnd2Uc = np.tile(
            np.repeat(paramRnd2Uc_ind, simB_obsPerInd, axis=0),
            (nDrawsWMem, 1)) + paramRnd2Uc_obs  #Good
        if xRnd2Uc_transBool:
            paramRnd2Uc = np.array(transRnd(paramRnd2Uc, xRnd2Uc_trans))
        paramRnd2UcPerRow = np.repeat(paramRnd2Uc, simW_rowsPerObs,
                                      axis=0)  #Good
        vRnd2Uc = np.sum(sim_xRnd2Uc * paramRnd2UcPerRow, axis=1)
    if nRnd2Co > 0:
        l = u
        u += nRnd2Co
        paramRnd2Co_mu = np.array(param[l:u])
        l = u
        u += int((nRnd2Co * (nRnd2Co + 1)) / 2)
        paramRnd2Co_chB = np.zeros((nRnd2Co, nRnd2Co))
        paramRnd2Co_chB[ch2Idx] = np.array(param[l:u])
        l = u
        u += int((nRnd2Co * (nRnd2Co + 1)) / 2)
        paramRnd2Co_chW = np.zeros((nRnd2Co, nRnd2Co))
        paramRnd2Co_chW[ch2Idx] = np.array(param[l:u])
        paramRnd2Co_ind = paramRnd2Co_mu + (
            paramRnd2Co_chB @ drawsCoBTake.T).T  #Good
        paramRnd2Co_obs = (paramRnd2Co_chW @ drawsCoWTake.T).T  #Good
        paramRnd2Co = np.tile(
            np.repeat(paramRnd2Co_ind, simB_obsPerInd, axis=0),
            (nDrawsWMem, 1)) + paramRnd2Co_obs  #Good
        if xRnd2Co_transBool:
            paramRnd2Co = np.array(transRnd(paramRnd2Co, xRnd2Co_trans))
        paramRnd2CoPerRow = np.repeat(paramRnd2Co, simW_rowsPerObs,
                                      axis=0)  #Good
        vRnd2Co = np.sum(sim_xRnd2Co * paramRnd2CoPerRow, axis=1)

    v = vFix + vRndUc + vRndCo + vRnd2Uc + vRnd2Co

    ###
    #Probability
    ###

    ev = np.exp(v)
    ev[ev > 1e+200] = 1e+200
    ev[ev < 1e-200] = 1e-200
    nev = simW_map_avail_to_obs.T @ ev + 1
    nnev = simW_map_avail_to_obs @ nev
    sim_pChosen = 1 / nev
    sim_pChosen[sim_pChosen < 1e-200] = 1e-200
    sim_pNonChosen = ev / nnev
    sim_pNonChosen[sim_pNonChosen < 1e-200] = 1e-200
    pChosen = sim_pChosen.reshape(
        (nDrawsWMem, nDrawsBMem, nObs)).sum(axis=0).reshape((-1, 1))

    ###
    #Gradient
    ###

    def calcGradient(der):
        t1 = -sim_pNonChosen.reshape((-1, 1)) * der
        t2 = simW_map_avail_to_obs.T @ t1
        numer = sim_pChosen.reshape((-1, 1)) * t2
        sgr = simW_map_drawsB_to_obs @ numer
        return sgr

    sgrFix = np.empty((nObs * nDrawsBMem, 0))
    sgrRndUc_mu = np.empty((nObs * nDrawsBMem, 0))
    sgrRndUc_sd = np.empty((nObs * nDrawsBMem, 0))
    sgrRndCo_mu = np.empty((nObs * nDrawsBMem, 0))
    sgrRndCo_ch = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Uc_mu = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Uc_sdB = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Uc_sdW = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Co_mu = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Co_chB = np.empty((nObs * nDrawsBMem, 0))
    sgrRnd2Co_chW = np.empty((nObs * nDrawsBMem, 0))

    if nFix > 0:
        derFix = sim_xFix
        if xFix_transBool:
            derFix = np.array(transDerFix(derFix, paramFix, xFix_trans))
        sgrFix = calcGradient(derFix)

    if nRndUc > 0:
        derRndUc_mu, derRndUc_sd = derRnd(nInd, nDrawsBMem, nRndUc,
                                          xRndUc_transBool, paramRndUc,
                                          xRndUc_trans, chIdx, drawsUcTake,
                                          simB_rowsPerInd, True)
        derRndUc_mu = np.tile(derRndUc_mu, (nDrawsWMem, 1))
        derRndUc_sd = np.tile(derRndUc_sd, (nDrawsWMem, 1))
        derRndUc_mu *= sim_xRndUc
        derRndUc_sd *= sim_xRndUc
        sgrRndUc_mu = calcGradient(derRndUc_mu)
        sgrRndUc_sd = calcGradient(derRndUc_sd)

    if nRndCo > 0:
        derRndCo_mu, derRndCo_ch = derRnd(nInd, nDrawsBMem, nRndCo,
                                          xRndCo_transBool, paramRndCo,
                                          xRndCo_trans, chIdx, drawsCoTake,
                                          simB_rowsPerInd, False)
        derRndCo_mu = np.tile(derRndCo_mu, (nDrawsWMem, 1))
        derRndCo_ch = np.tile(derRndCo_ch, (nDrawsWMem, 1))
        derRndCo_mu *= sim_xRndCo
        derRndCo_ch *= sim_xRndCo[:, chIdx[0]]
        sgrRndCo_mu = calcGradient(derRndCo_mu)
        sgrRndCo_ch = calcGradient(derRndCo_ch)

    if nRnd2Uc > 0:
        derRnd2Uc_mu, derRnd2Uc_sdB = derRnd(nInd, nDrawsBMem, nRnd2Uc,
                                             xRnd2Uc_transBool,
                                             paramRnd2Uc_ind, xRnd2Uc_trans,
                                             ch2Idx, drawsUcBTake,
                                             simB_rowsPerInd, True)
        derRnd2Uc_mu = np.tile(derRnd2Uc_mu, (nDrawsWMem, 1))
        derRnd2Uc_sdB = np.tile(derRnd2Uc_sdB, (nDrawsWMem, 1))
        derRnd2Uc_sdW = derRnd_ch(nObs, nDrawsMem, nRnd2Uc, xRnd2Uc_transBool,
                                  paramRnd2Uc_obs, xRnd2Uc_trans, ch2Idx,
                                  drawsUcBTake, simW_rowsPerObs, True)
        derRnd2Uc_mu *= sim_xRnd2Uc
        derRnd2Uc_sdB *= sim_xRnd2Uc
        derRnd2Uc_sdW *= sim_xRnd2Uc
        sgrRnd2Uc_mu = calcGradient(derRnd2Uc_mu)
        sgrRnd2Uc_sdB = calcGradient(derRnd2Uc_sdB)
        sgrRnd2Uc_sdW = calcGradient(derRnd2Uc_sdW)

    if nRnd2Co > 0:
        derRnd2Co_mu, derRnd2Co_chB = derRnd(nInd, nDrawsBMem, nRnd2Co,
                                             xRnd2Co_transBool,
                                             paramRnd2Co_ind, xRnd2Co_trans,
                                             ch2Idx, drawsCoBTake,
                                             simB_rowsPerInd, False)
        derRnd2Co_mu = np.tile(derRnd2Co_mu, (nDrawsWMem, 1))
        derRnd2Co_chB = np.tile(derRnd2Co_chB, (nDrawsWMem, 1))
        derRnd2Co_chW = derRnd_ch(nObs, nDrawsMem, nRnd2Co, xRnd2Co_transBool,
                                  paramRnd2Co_obs, xRnd2Co_trans, ch2Idx,
                                  drawsCoWTake, simW_rowsPerObs, False)
        derRnd2Co_mu *= sim_xRnd2Co
        derRnd2Co_chB *= sim_xRnd2Co[:, ch2Idx[0]]
        derRnd2Co_chW *= sim_xRnd2Co[:, ch2Idx[0]]
        sgrRnd2Co_mu = calcGradient(derRnd2Co_mu)
        sgrRnd2Co_chB = calcGradient(derRnd2Co_chB)
        sgrRnd2Co_chW = calcGradient(derRnd2Co_chW)

    sgr = np.concatenate(
        (sgrFix, sgrRndUc_mu, sgrRndUc_sd, sgrRndCo_mu, sgrRndCo_ch,
         sgrRnd2Uc_mu, sgrRnd2Uc_sdB, sgrRnd2Uc_sdW, sgrRnd2Co_mu,
         sgrRnd2Co_chB, sgrRnd2Co_chW),
        axis=1)

    return pChosen, sgr