Example #1
0
double MapOptimizer::compute_relentropy_cpu (MatrixXf & dH) const
{
  const MatrixXf & H = m_conditional;
  const MatrixSf & P = dom_flow.joint;

  MatrixXf HP(H.rows(), H.cols());
  MatrixXf HPt(H.rows(), H.cols());

  #pragma omp parallel sections
  {
    #pragma omp section
    HP.noalias() = H * P;

    #pragma omp section
    HPt.noalias() = H * P.transpose();
  }

  MatrixXf HPH = HP * H.transpose();

  const float sum_P = m_dom_flow_sum;
  const float sum_Q = m_cod_flow_sum;
  const float dQ_scale = sum_P / sum_Q;

  const MatrixSf & Q = cod_flow.joint;
  MatrixSf & dQ = m_temp_dQ;

  double relentropy = 0;
  for (int i = 0; i < Q.outerSize(); ++i) {
    for (MatrixSf::InnerIterator iter(Q,i); iter; ++iter) {

      const float Q_yy = iter.value();
      const float HPH_yy = HPH(iter.row(), iter.col());
      const float dQ_yy = dQ_scale * Q_yy / HPH_yy;

      relentropy += Q_yy * log(dQ_yy);

      dQ.coeffRef(iter.row(), iter.col()) = dQ_yy;
    }
  }
  relentropy /= sum_Q;
  ASSERT_LE(0, relentropy);

  MatrixXf dH2(H.rows(), H.cols());

  #pragma omp parallel sections
  {
    #pragma omp section
    dH.noalias() = dQ.transpose() * HP;

    #pragma omp section
    dH2.noalias() = dQ * HPt;
  }

  dH += dH2;

  return relentropy;
}