def objGrad_u(u, sumLogPi, nDoc, gamma, alpha0):
  assert not np.any(np.isnan(u))

  # UNPACK AND PREPARE building-block quantities
  u1, u0 = _unpack(u)
  K = u1.size
  E = _calcExpectations(u1, u0)
  dU1, dU0 = _calcGradients(u1, u0, E=E)

  kvec = K + 1 - np.arange(1, K+1)

  digammaU1 = digamma(u1)
  digammaU0 = digamma(u0)
  digammaBoth = digamma(u1+u0)

  dU1_Elogpmq_v = digammaU1 - digammaBoth \
                  + (1 - u1) * dU1['Elogv'] \
                  - E['logv'] \
                  + (alpha0 - u0) * dU1['Elog1-v']
  dU0_Elogpmq_v = digammaU0 - digammaBoth \
                  + (1 - u1) * dU0['Elogv'] \
                  - E['log1-v'] \
                  + (alpha0 - u0) * dU0['Elog1-v']

  if nDoc > 0:
    dU1_Elogp_pi = dU1['Elogv'] + kvec * dU1['Elog1-v'] \
                  + gamma * np.dot(dU1['Ebeta'], sumLogPi/nDoc)
    dU0_Elogp_pi = dU0['Elogv'] + kvec * dU0['Elog1-v'] \
                  + gamma * np.dot(dU0['Ebeta'], sumLogPi/nDoc)
    dU1_Elogpmq_v /= nDoc
    dU0_Elogpmq_v /= nDoc
  else:
    dU1_Elogp_pi = 0
    dU0_Elogp_pi = 0

  gvecU1 = dU1_Elogp_pi + dU1_Elogpmq_v
  gvecU0 = dU0_Elogp_pi + dU0_Elogpmq_v
  gvecU = np.hstack([gvecU1, gvecU0])
  return -1.0 * gvecU


########################################################### calcExpectations
###########################################################
Returns 2K-vector gradient of the constrained objective
dataset/ETHPy150Open daeilkim/refinery/refinery/bnpy/bnpy-dev/bnpy/allocmodel/admix/OptimizerForHDPFullVarModel.py/objGrad_u