<commit_before>/**
 * @file nca_softmax_impl.h
 * @author Ryan Curtin
 *
 * Implementation of the Softmax error function.
 */
#ifndef __MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTCLIN_IMPL_H
#define __MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTCLIN_IMPL_H

// In case it hasn't been included already.
#include "nca_softmax_error_function.hpp"

namespace mlpack {
namespace nca {

// Initialize with the given kernel.
template<typename MetricType>
SoftmaxErrorFunction<MetricType>::SoftmaxErrorFunction(const arma::mat& dataset,
                                                       const arma::uvec& labels,
                                                       MetricType metric) :
  dataset(dataset),
  labels(labels),
  metric(metric),
  precalculated(false)
{ /* nothing to do */ }

//! The non-separable implementation, which uses Precalculate() to save time.
template<typename MetricType>
double SoftmaxErrorFunction<MetricType>::Evaluate(const arma::mat& coordinates)
{
  // Calculate the denominators and numerators, if necessary.
  Precalculate(coordinates);

  return -accu(p); // Sum of p_i for all i.  We negate because our solver
                   // minimizes, not maximizes.
};

//! The separated objective function, which does not use Precalculate().
template<typename MetricType>
double SoftmaxErrorFunction<MetricType>::Evaluate(const arma::mat& coordinates,
                                                  const size_t i)
{
  // Unfortunately each evaluation will take O(N) time because it requires a
  // scan over all points in the dataset.  Our objective is to compute p_ij.
  double denominator = 0;
  double numerator = 0;

  // It's quicker to do this now than one point at a time later.
  stretchedDataset = coordinates * dataset;

  for (size_t k = 0; k < dataset.n_cols; ++k)
  {
    // Don't consider the case where the points are the same.
    if (k == i)
      continue;

    // We want to evaluate exp(-D(A x_i, A x_k)).
    double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                            stretchedDataset.unsafe_col(k)));

    // If they are in the same
    if (labels[i] == labels[k])
      numerator += eval;

    denominator += eval;
  }

  // Now the result is just a simple division, but we have to be sure that the
  // denominator is not 0.
  if (denominator == 0.0)
  {
    Log::Warn << "Denominator of p_" << i << " is 0!" << std::endl;
    return 0;
  }

  return -(numerator / denominator); // Negate because the optimizer is a
                                     // minimizer.
}

//! The non-separable implementation, where Precalculate() is used.
template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Gradient(const arma::mat& coordinates,
                                                arma::mat& gradient)
{
  // Calculate the denominators and numerators, if necessary.
  Precalculate(coordinates);

  // Now, we handle the summation over i:
  //   sum_i (p_i sum_k (p_ik x_ik x_ik^T) -
  //       sum_{j in class of i} (p_ij x_ij x_ij^T)
  // We can algebraically manipulate the whole thing to produce a more
  // memory-friendly way to calculate this.  Looping over each i and k (again
  // O((n * (n + 1)) / 2) as with the last step, we can add the following to the
  // sum:
  //
  //   if class of i is the same as the class of k, add
  //     (((p_i - (1 / p_i)) p_ik) + ((p_k - (1 / p_k)) p_ki)) x_ik x_ik^T
  //   otherwise, add
  //     (p_i p_ik + p_k p_ki) x_ik x_ik^T
  arma::mat sum;
  sum.zeros(stretchedDataset.n_rows, stretchedDataset.n_rows);
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    for (size_t k = (i + 1); k < stretchedDataset.n_cols; k++)
    {
      // Calculate p_ik and p_ki first.
      double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                         stretchedDataset.unsafe_col(k)));
      double p_ik = 0, p_ki = 0;
      p_ik = eval / denominators(i);
      p_ki = eval / denominators(k);

      // Subtract x_i from x_k.  We are not using stretched points here.
      arma::vec x_ik = dataset.col(i) - dataset.col(k);
      arma::mat secondTerm = (x_ik * trans(x_ik));

      if (labels[i] == labels[k])
        sum += ((p[i] - 1) * p_ik + (p[k] - 1) * p_ki) * secondTerm;
      else
        sum += (p[i] * p_ik + p[k] * p_ki) * secondTerm;
    }
  }

  // Assemble the final gradient.
  gradient = -2 * coordinates * sum;
}

//! The separable implementation.
template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Gradient(const arma::mat& coordinates,
                                                const size_t i,
                                                arma::mat& gradient)
{
  // We will need to calculate p_i before this evaluation is done, so these two
  // variables will hold the information necessary for that.
  double numerator = 0;
  double denominator = 0;

  // The gradient involves two matrix terms which are eventually combined into
  // one.
  arma::mat firstTerm;
  arma::mat secondTerm;

  firstTerm.zeros(coordinates.n_rows, coordinates.n_cols);
  secondTerm.zeros(coordinates.n_rows, coordinates.n_cols);

  // Compute the stretched dataset.
  stretchedDataset = coordinates * dataset;

  for (size_t k = 0; k < dataset.n_cols; ++k)
  {
    // Don't consider the case where the points are the same.
    if (i == k)
      continue;

    // Calculate the numerator of p_ik.
    double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                       stretchedDataset.unsafe_col(k)));

    // If the points are in the same class, we must add to the second term of
    // the gradient as well as the numerator of p_i.  We will divide by the
    // denominator of p_ik later.  For x_ik we are not using stretched points.
    arma::vec x_ik = dataset.col(i) - dataset.col(k);
    if (labels[i] == labels[k])
    {
      numerator += eval;
      secondTerm += eval * x_ik * trans(x_ik);
    }

    // We always have to add to the denominator of p_i and the first term of the
    // gradient computation.  We will divide by the denominator of p_ik later.
    denominator += eval;
    firstTerm += eval * x_ik * trans(x_ik);
  }

  // Calculate p_i.
  double p = 0;
  if (denominator == 0)
  {
    Log::Warn << "Denominator of p_" << i << " is 0!" << std::endl;
    // If the denominator is zero, then all p_ik should be zero and there is
    // no gradient contribution from this point.
    gradient.zeros(coordinates.n_rows, coordinates.n_rows);
    return;
  }
  else
  {
    p = numerator / denominator;
    firstTerm /= denominator;
    secondTerm /= denominator;
  }

  // Now multiply the first term by p_i, and add the two together and multiply
  // all by 2 * A.  We negate it though, because our optimizer is a minimizer.
  gradient = -2 * coordinates * (p * firstTerm - secondTerm);
}

template<typename MetricType>
const arma::mat SoftmaxErrorFunction<MetricType>::GetInitialPoint() const
{
  return arma::eye<arma::mat>(dataset.n_rows, dataset.n_rows);
}

template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Precalculate(
    const arma::mat& coordinates)
{
  // Ensure it is the right size.
  lastCoordinates.set_size(coordinates.n_rows, coordinates.n_cols);

  // Make sure the calculation is necessary.
  if ((accu(coordinates == lastCoordinates) == coordinates.n_elem) &&
      precalculated)
    return; // No need to calculate; we already have this stuff saved.

  // Coordinates are different; save the new ones, and stretch the dataset.
  lastCoordinates = coordinates;
  stretchedDataset = coordinates * dataset;

  // For each point i, we must evaluate the softmax function:
  //   p_ij = exp( -K(x_i, x_j) ) / ( sum_{k != i} ( exp( -K(x_i, x_k) )))
  //   p_i = sum_{j in class of i} p_ij
  // We will do this by keeping track of the denominators for each i as well as
  // the numerators (the sum for all j in class of i).  This will be on the
  // order of O((n * (n + 1)) / 2), which really isn't all that great.
  p.zeros(stretchedDataset.n_cols);
  denominators.zeros(stretchedDataset.n_cols);
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    for (size_t j = (i + 1); j < stretchedDataset.n_cols; j++)
    {
      // Evaluate exp(-d(x_i, x_j)).
      double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                         stretchedDataset.unsafe_col(j)));

      // Add this to the denominators of both i and j: p_ij = p_ji.
      denominators[i] += eval;
      denominators[j] += eval;

      // If i and j are the same class, add to numerator of both.
      if (labels[i] == labels[j])
      {
        p[i] += eval;
        p[j] += eval;
      }
    }
  }

  // Divide p_i by their denominators.
  p /= denominators;

  // Clean up any bad values.
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    if (denominators[i] == 0.0)
    {
      Log::Debug << "Denominator of p_{" << i << ", j} is 0." << std::endl;

      // Set to usable values.
      denominators[i] = std::numeric_limits<double>::infinity();
      p[i] = 0;
    }
  }

  // We've done a precalculation.  Mark it as done.
  precalculated = true;
}

}; // namespace nca
}; // namespace mlpack

#endif
<commit_msg>Update comments for correctness to resolve #261.<commit_after>/**
 * @file nca_softmax_impl.h
 * @author Ryan Curtin
 *
 * Implementation of the Softmax error function.
 */
#ifndef __MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTCLIN_IMPL_H
#define __MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTCLIN_IMPL_H

// In case it hasn't been included already.
#include "nca_softmax_error_function.hpp"

namespace mlpack {
namespace nca {

// Initialize with the given kernel.
template<typename MetricType>
SoftmaxErrorFunction<MetricType>::SoftmaxErrorFunction(const arma::mat& dataset,
                                                       const arma::uvec& labels,
                                                       MetricType metric) :
  dataset(dataset),
  labels(labels),
  metric(metric),
  precalculated(false)
{ /* nothing to do */ }

//! The non-separable implementation, which uses Precalculate() to save time.
template<typename MetricType>
double SoftmaxErrorFunction<MetricType>::Evaluate(const arma::mat& coordinates)
{
  // Calculate the denominators and numerators, if necessary.
  Precalculate(coordinates);

  return -accu(p); // Sum of p_i for all i.  We negate because our solver
                   // minimizes, not maximizes.
};

//! The separated objective function, which does not use Precalculate().
template<typename MetricType>
double SoftmaxErrorFunction<MetricType>::Evaluate(const arma::mat& coordinates,
                                                  const size_t i)
{
  // Unfortunately each evaluation will take O(N) time because it requires a
  // scan over all points in the dataset.  Our objective is to compute p_ij.
  double denominator = 0;
  double numerator = 0;

  // It's quicker to do this now than one point at a time later.
  stretchedDataset = coordinates * dataset;

  for (size_t k = 0; k < dataset.n_cols; ++k)
  {
    // Don't consider the case where the points are the same.
    if (k == i)
      continue;

    // We want to evaluate exp(-D(A x_i, A x_k)).
    double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                            stretchedDataset.unsafe_col(k)));

    // If they are in the same
    if (labels[i] == labels[k])
      numerator += eval;

    denominator += eval;
  }

  // Now the result is just a simple division, but we have to be sure that the
  // denominator is not 0.
  if (denominator == 0.0)
  {
    Log::Warn << "Denominator of p_" << i << " is 0!" << std::endl;
    return 0;
  }

  return -(numerator / denominator); // Negate because the optimizer is a
                                     // minimizer.
}

//! The non-separable implementation, where Precalculate() is used.
template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Gradient(const arma::mat& coordinates,
                                                arma::mat& gradient)
{
  // Calculate the denominators and numerators, if necessary.
  Precalculate(coordinates);

  // Now, we handle the summation over i:
  //   sum_i (p_i sum_k (p_ik x_ik x_ik^T) -
  //       sum_{j in class of i} (p_ij x_ij x_ij^T)
  // We can algebraically manipulate the whole thing to produce a more
  // memory-friendly way to calculate this.  Looping over each i and k (again
  // O((n * (n + 1)) / 2) as with the last step, we can add the following to the
  // sum:
  //
  //   if class of i is the same as the class of k, add
  //     (((p_i - (1 / p_i)) p_ik) + ((p_k - (1 / p_k)) p_ki)) x_ik x_ik^T
  //   otherwise, add
  //     (p_i p_ik + p_k p_ki) x_ik x_ik^T
  arma::mat sum;
  sum.zeros(stretchedDataset.n_rows, stretchedDataset.n_rows);
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    for (size_t k = (i + 1); k < stretchedDataset.n_cols; k++)
    {
      // Calculate p_ik and p_ki first.
      double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                         stretchedDataset.unsafe_col(k)));
      double p_ik = 0, p_ki = 0;
      p_ik = eval / denominators(i);
      p_ki = eval / denominators(k);

      // Subtract x_i from x_k.  We are not using stretched points here.
      arma::vec x_ik = dataset.col(i) - dataset.col(k);
      arma::mat secondTerm = (x_ik * trans(x_ik));

      if (labels[i] == labels[k])
        sum += ((p[i] - 1) * p_ik + (p[k] - 1) * p_ki) * secondTerm;
      else
        sum += (p[i] * p_ik + p[k] * p_ki) * secondTerm;
    }
  }

  // Assemble the final gradient.
  gradient = -2 * coordinates * sum;
}

//! The separable implementation.
template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Gradient(const arma::mat& coordinates,
                                                const size_t i,
                                                arma::mat& gradient)
{
  // We will need to calculate p_i before this evaluation is done, so these two
  // variables will hold the information necessary for that.
  double numerator = 0;
  double denominator = 0;

  // The gradient involves two matrix terms which are eventually combined into
  // one.
  arma::mat firstTerm;
  arma::mat secondTerm;

  firstTerm.zeros(coordinates.n_rows, coordinates.n_cols);
  secondTerm.zeros(coordinates.n_rows, coordinates.n_cols);

  // Compute the stretched dataset.
  stretchedDataset = coordinates * dataset;

  for (size_t k = 0; k < dataset.n_cols; ++k)
  {
    // Don't consider the case where the points are the same.
    if (i == k)
      continue;

    // Calculate the numerator of p_ik.
    double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                       stretchedDataset.unsafe_col(k)));

    // If the points are in the same class, we must add to the second term of
    // the gradient as well as the numerator of p_i.  We will divide by the
    // denominator of p_ik later.  For x_ik we are not using stretched points.
    arma::vec x_ik = dataset.col(i) - dataset.col(k);
    if (labels[i] == labels[k])
    {
      numerator += eval;
      secondTerm += eval * x_ik * trans(x_ik);
    }

    // We always have to add to the denominator of p_i and the first term of the
    // gradient computation.  We will divide by the denominator of p_ik later.
    denominator += eval;
    firstTerm += eval * x_ik * trans(x_ik);
  }

  // Calculate p_i.
  double p = 0;
  if (denominator == 0)
  {
    Log::Warn << "Denominator of p_" << i << " is 0!" << std::endl;
    // If the denominator is zero, then all p_ik should be zero and there is
    // no gradient contribution from this point.
    gradient.zeros(coordinates.n_rows, coordinates.n_rows);
    return;
  }
  else
  {
    p = numerator / denominator;
    firstTerm /= denominator;
    secondTerm /= denominator;
  }

  // Now multiply the first term by p_i, and add the two together and multiply
  // all by 2 * A.  We negate it though, because our optimizer is a minimizer.
  gradient = -2 * coordinates * (p * firstTerm - secondTerm);
}

template<typename MetricType>
const arma::mat SoftmaxErrorFunction<MetricType>::GetInitialPoint() const
{
  return arma::eye<arma::mat>(dataset.n_rows, dataset.n_rows);
}

template<typename MetricType>
void SoftmaxErrorFunction<MetricType>::Precalculate(
    const arma::mat& coordinates)
{
  // Ensure it is the right size.
  lastCoordinates.set_size(coordinates.n_rows, coordinates.n_cols);

  // Make sure the calculation is necessary.
  if ((accu(coordinates == lastCoordinates) == coordinates.n_elem) &&
      precalculated)
    return; // No need to calculate; we already have this stuff saved.

  // Coordinates are different; save the new ones, and stretch the dataset.
  lastCoordinates = coordinates;
  stretchedDataset = coordinates * dataset;

  // For each point i, we must evaluate the softmax function:
  //   p_ij = exp( -K(x_i, x_j) ) / ( sum_{k != i} ( exp( -K(x_i, x_k) )))
  //   p_i = sum_{j in class of i} p_ij
  // We will do this by keeping track of the denominators for each i as well as
  // the numerators (the sum for all j in class of i).  This will be on the
  // order of O((n * (n + 1)) / 2), which really isn't all that great.
  p.zeros(stretchedDataset.n_cols);
  denominators.zeros(stretchedDataset.n_cols);
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    for (size_t j = (i + 1); j < stretchedDataset.n_cols; j++)
    {
      // Evaluate exp(-d(x_i, x_j)).
      double eval = exp(-metric.Evaluate(stretchedDataset.unsafe_col(i),
                                         stretchedDataset.unsafe_col(j)));

      // Add this to the denominators of both p_i and p_j: K(i, j) = K(j, i).
      denominators[i] += eval;
      denominators[j] += eval;

      // If i and j are the same class, add to numerator of both.
      if (labels[i] == labels[j])
      {
        p[i] += eval;
        p[j] += eval;
      }
    }
  }

  // Divide p_i by their denominators.
  p /= denominators;

  // Clean up any bad values.
  for (size_t i = 0; i < stretchedDataset.n_cols; i++)
  {
    if (denominators[i] == 0.0)
    {
      Log::Debug << "Denominator of p_{" << i << ", j} is 0." << std::endl;

      // Set to usable values.
      denominators[i] = std::numeric_limits<double>::infinity();
      p[i] = 0;
    }
  }

  // We've done a precalculation.  Mark it as done.
  precalculated = true;
}

}; // namespace nca
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/certificate_manager_model.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/base/net_errors.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/x509_certificate.h"

using content::BrowserThread;

namespace {

net::NSSCertDatabase* g_nss_cert_database = nullptr;

net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
    content::ResourceContext* context,
    base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
  // This initialization is not thread safe. This CHECK ensures that this code
  // is only run on a single thread.
  CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  if (!g_nss_cert_database) {
    // Linux has only a single persistent slot compared to ChromeOS's separate
    // public and private slot.
    // Redirect any slot usage to this persistent slot on Linux.
    g_nss_cert_database = new net::NSSCertDatabase(
        crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* public slot */,
        crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* private slot */);
  }
  return g_nss_cert_database;
}

}  // namespace

// CertificateManagerModel is created on the UI thread. It needs a
// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
// needs to be done on the IO thread.
//
// The initialization flow is roughly:
//
//               UI thread                              IO Thread
//
//   CertificateManagerModel::Create
//                  \--------------------------------------v
//                                CertificateManagerModel::GetCertDBOnIOThread
//                                                         |
//                                     GetNSSCertDatabaseForResourceContext
//                                                         |
//                               CertificateManagerModel::DidGetCertDBOnIOThread
//                  v--------------------------------------/
// CertificateManagerModel::DidGetCertDBOnUIThread
//                  |
//     new CertificateManagerModel
//                  |
//               callback

// static
void CertificateManagerModel::Create(content::BrowserContext* browser_context,
                                     CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTask(FROM_HERE, {BrowserThread::IO},
                 base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
                                browser_context->GetResourceContext(),
                                std::move(callback)));
}

CertificateManagerModel::CertificateManagerModel(
    net::NSSCertDatabase* nss_cert_database,
    bool is_user_db_available)
    : cert_db_(nss_cert_database), is_user_db_available_(is_user_db_available) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

CertificateManagerModel::~CertificateManagerModel() = default;

int CertificateManagerModel::ImportFromPKCS12(
    PK11SlotInfo* slot_info,
    const std::string& data,
    const base::string16& password,
    bool is_extractable,
    net::ScopedCERTCertificateList* imported_certs) {
  return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
                                    imported_certs);
}

int CertificateManagerModel::ImportUserCert(const std::string& data) {
  return cert_db_->ImportUserCert(data);
}

bool CertificateManagerModel::ImportCACerts(
    const net::ScopedCERTCertificateList& certificates,
    net::NSSCertDatabase::TrustBits trust_bits,
    net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  return cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
}

bool CertificateManagerModel::ImportServerCert(
    const net::ScopedCERTCertificateList& certificates,
    net::NSSCertDatabase::TrustBits trust_bits,
    net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  return cert_db_->ImportServerCert(certificates, trust_bits, not_imported);
}

bool CertificateManagerModel::SetCertTrust(
    CERTCertificate* cert,
    net::CertType type,
    net::NSSCertDatabase::TrustBits trust_bits) {
  return cert_db_->SetCertTrust(cert, type, trust_bits);
}

bool CertificateManagerModel::Delete(CERTCertificate* cert) {
  return cert_db_->DeleteCertAndKey(cert);
}

// static
void CertificateManagerModel::DidGetCertDBOnUIThread(
    net::NSSCertDatabase* cert_db,
    bool is_user_db_available,
    CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::unique_ptr<CertificateManagerModel> model(
      new CertificateManagerModel(cert_db, is_user_db_available));
  std::move(callback).Run(std::move(model));
}

// static
void CertificateManagerModel::DidGetCertDBOnIOThread(
    CreationCallback callback,
    net::NSSCertDatabase* cert_db) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  bool is_user_db_available = !!cert_db->GetPublicSlot();
  base::PostTask(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread, cert_db,
                     is_user_db_available, std::move(callback)));
}

// static
void CertificateManagerModel::GetCertDBOnIOThread(
    content::ResourceContext* context,
    CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  auto did_get_cert_db_callback = base::AdaptCallbackForRepeating(
      base::BindOnce(&CertificateManagerModel::DidGetCertDBOnIOThread,
                     std::move(callback)));

  net::NSSCertDatabase* cert_db =
      GetNSSCertDatabaseForResourceContext(context, did_get_cert_db_callback);

  // If the NSS database was already available, |cert_db| is non-null and
  // |did_get_cert_db_callback| has not been called. Call it explicitly.
  if (cert_db)
    did_get_cert_db_callback.Run(cert_db);
}
<commit_msg>fix: app.importCertificate crash on Linux (#25523)<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/certificate_manager_model.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/base/net_errors.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/x509_certificate.h"

using content::BrowserThread;

namespace {

net::NSSCertDatabase* g_nss_cert_database = nullptr;

net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
    content::ResourceContext* context,
    base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
  // This initialization is not thread safe. This CHECK ensures that this code
  // is only run on a single thread.
  CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  if (!g_nss_cert_database) {
    // Linux has only a single persistent slot compared to ChromeOS's separate
    // public and private slot.
    // Redirect any slot usage to this persistent slot on Linux.
    crypto::EnsureNSSInit();
    g_nss_cert_database = new net::NSSCertDatabase(
        crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* public slot */,
        crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* private slot */);
  }
  return g_nss_cert_database;
}

}  // namespace

// CertificateManagerModel is created on the UI thread. It needs a
// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
// needs to be done on the IO thread.
//
// The initialization flow is roughly:
//
//               UI thread                              IO Thread
//
//   CertificateManagerModel::Create
//                  \--------------------------------------v
//                                CertificateManagerModel::GetCertDBOnIOThread
//                                                         |
//                                     GetNSSCertDatabaseForResourceContext
//                                                         |
//                               CertificateManagerModel::DidGetCertDBOnIOThread
//                  v--------------------------------------/
// CertificateManagerModel::DidGetCertDBOnUIThread
//                  |
//     new CertificateManagerModel
//                  |
//               callback

// static
void CertificateManagerModel::Create(content::BrowserContext* browser_context,
                                     CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTask(FROM_HERE, {BrowserThread::IO},
                 base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
                                browser_context->GetResourceContext(),
                                std::move(callback)));
}

CertificateManagerModel::CertificateManagerModel(
    net::NSSCertDatabase* nss_cert_database,
    bool is_user_db_available)
    : cert_db_(nss_cert_database), is_user_db_available_(is_user_db_available) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

CertificateManagerModel::~CertificateManagerModel() = default;

int CertificateManagerModel::ImportFromPKCS12(
    PK11SlotInfo* slot_info,
    const std::string& data,
    const base::string16& password,
    bool is_extractable,
    net::ScopedCERTCertificateList* imported_certs) {
  return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
                                    imported_certs);
}

int CertificateManagerModel::ImportUserCert(const std::string& data) {
  return cert_db_->ImportUserCert(data);
}

bool CertificateManagerModel::ImportCACerts(
    const net::ScopedCERTCertificateList& certificates,
    net::NSSCertDatabase::TrustBits trust_bits,
    net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  return cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
}

bool CertificateManagerModel::ImportServerCert(
    const net::ScopedCERTCertificateList& certificates,
    net::NSSCertDatabase::TrustBits trust_bits,
    net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  return cert_db_->ImportServerCert(certificates, trust_bits, not_imported);
}

bool CertificateManagerModel::SetCertTrust(
    CERTCertificate* cert,
    net::CertType type,
    net::NSSCertDatabase::TrustBits trust_bits) {
  return cert_db_->SetCertTrust(cert, type, trust_bits);
}

bool CertificateManagerModel::Delete(CERTCertificate* cert) {
  return cert_db_->DeleteCertAndKey(cert);
}

// static
void CertificateManagerModel::DidGetCertDBOnUIThread(
    net::NSSCertDatabase* cert_db,
    bool is_user_db_available,
    CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::unique_ptr<CertificateManagerModel> model(
      new CertificateManagerModel(cert_db, is_user_db_available));
  std::move(callback).Run(std::move(model));
}

// static
void CertificateManagerModel::DidGetCertDBOnIOThread(
    CreationCallback callback,
    net::NSSCertDatabase* cert_db) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  bool is_user_db_available = !!cert_db->GetPublicSlot();
  base::PostTask(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread, cert_db,
                     is_user_db_available, std::move(callback)));
}

// static
void CertificateManagerModel::GetCertDBOnIOThread(
    content::ResourceContext* context,
    CreationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  auto did_get_cert_db_callback = base::AdaptCallbackForRepeating(
      base::BindOnce(&CertificateManagerModel::DidGetCertDBOnIOThread,
                     std::move(callback)));

  net::NSSCertDatabase* cert_db =
      GetNSSCertDatabaseForResourceContext(context, did_get_cert_db_callback);

  // If the NSS database was already available, |cert_db| is non-null and
  // |did_get_cert_db_callback| has not been called. Call it explicitly.
  if (cert_db)
    did_get_cert_db_callback.Run(cert_db);
}
<|endoftext|>


<commit_before>#include <queso/GslVector.h>
#include <queso/GslMatrix.h>
#include <queso/UniformVectorRV.h>
#include <queso/StatisticalInverseProblem.h>
#include <queso/VectorSet.h>
#include <queso/GPMSA.h>

#include <cstdio>

// Read in data files
double readData(const std::vector<QUESO::GslVector *> & simulationScenarios,
    const std::vector<QUESO::GslVector *> & simulationParameters,
    const std::vector<QUESO::GslVector *> & simulationOutputs,
    const std::vector<QUESO::GslVector *> & experimentScenarios,
    const std::vector<QUESO::GslVector *> & experimentOutputs) {
  FILE * fp_in = fopen("gp/scalar/dakota_pstudy.dat", "r");
  unsigned int i, id, size = 512;
  double k_tmasl, k_tmoml, k_tnrgl, k_xkwlx, k_cd, pressure;
  char line[size];

  // The user should know what the bounds on the data are
  double mins[] = {0.95, 0.9, 0.9, 0.9, 0.9};
  double maxs[] = {1.05, 1.1, 1.1, 1.1, 1.1};

  double meansim = 0;
  double m2sim = 0;

  // First line is a header, so we ignore it
  fgets(line, size, fp_in);

  i = 0;
  while (fscanf(fp_in, "%d %lf %lf %lf %lf %lf %lf\n", &id, &k_tmasl, &k_tmoml,
        &k_tnrgl, &k_xkwlx, &k_cd, &pressure) != EOF) {
    (*(simulationScenarios[i]))[0] = 0.5;

    (*(simulationParameters[i]))[0] = (k_tmasl - mins[0]) / (maxs[0] - mins[0]);
    (*(simulationParameters[i]))[1] = (k_tmoml - mins[1]) / (maxs[1] - mins[1]);
    (*(simulationParameters[i]))[2] = (k_tnrgl - mins[2]) / (maxs[2] - mins[2]);
    (*(simulationParameters[i]))[3] = (k_xkwlx - mins[3]) / (maxs[3] - mins[3]);
    (*(simulationParameters[i]))[4] = (k_cd    - mins[4]) / (maxs[4] - mins[4]);

    (*(simulationOutputs[i]))[0] = pressure;
    i++;

    double delta = pressure - meansim;
    meansim += delta / i;
    m2sim += delta * (pressure - meansim);
  }

  double stdsim = m2sim / (double)(i - 1);

  // The user is required to standardise the experimental and simulation data
  for (unsigned int j = 0; j < i; j++) {
    (*(simulationOutputs[j]))[0] -= meansim;
    (*(simulationOutputs[j]))[0] /= stdsim;
  }

  fclose(fp_in);  // Done with simulation data

  // Read in experimental data
  fp_in = fopen("gp/scalar/ctf_dat.txt", "r");
  i = 0;
  while (fscanf(fp_in, "%lf\n", &pressure) != EOF) {
    (*(experimentOutputs[i]))[0] = pressure;
    i++;
  }

  // Also required to standardise experimental data too
  for (unsigned int j = 0; j < i; j++) {
    (*(experimentOutputs[j]))[0] -= meansim;
    (*(experimentOutputs[j]))[0] /= stdsim;
  }

  fclose(fp_in);

  // Returning standard deviation of data (simulation data is treated as
  // plentiful and the standard deviation of this data is treated as the 'true'
  // standard deviation of the data.  This can be argued.)
  return stdsim;
}

int main(int argc, char ** argv) {
  // Step 0: Set up some variables
  unsigned int numExperiments = 10;  // Number of experiments
  unsigned int numUncertainVars = 5;  // Number of things to calibrate
  unsigned int numSimulations = 50;  // Number of simulations
  unsigned int numConfigVars = 1;  // Dimension of configuration space
  unsigned int numEta = 1;  // Number of responses the model is returning
  unsigned int experimentSize = 1;  // Size of each experiment

  MPI_Init(&argc, &argv);

  // Step 1: Set up QUESO environment
  QUESO::FullEnvironment env(MPI_COMM_WORLD, argv[1], "", NULL);

  // Step 2: Set up prior for calibration parameters
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> paramSpace(env,
      "param_", numUncertainVars, NULL);

  // Parameter (theta) bounds:
  //   descriptors   'k_tmasl' 'k_xkle' 'k_xkwew' 'k_xkwlx' 'k_cd'
  //   upper_bounds   1.05      1.1      1.1       1.1       1.1
  //   lower_bounds   0.95      0.9      0.9       0.9       0.9
  //
  // These bounds are dealt with when reading in the data
  QUESO::GslVector paramMins(paramSpace.zeroVector());
  QUESO::GslVector paramMaxs(paramSpace.zeroVector());

  paramMins.cwSet(0.0);
  paramMaxs.cwSet(1.0);

  QUESO::BoxSubset<QUESO::GslVector, QUESO::GslMatrix> paramDomain("param_",
      paramSpace, paramMins, paramMaxs);

  QUESO::UniformVectorRV<QUESO::GslVector, QUESO::GslMatrix> priorRv("prior_",
      paramDomain);

  // Step 3: Instantiate the 'scenario' and 'output' spaces for simulation
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> configSpace(env,
      "scenario_", numConfigVars, NULL);

  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> nEtaSpace(env,
      "output_", numEta, NULL);

  // Step 4: Instantiate the 'output' space for the experiments
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> experimentSpace(env,
      "experimentspace_", experimentSize, NULL);

  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> totalExperimentSpace(env,
      "experimentspace_", experimentSize * numExperiments, NULL);

  // Step 5: Instantiate the Gaussian process emulator object
  //
  // Regarding simulation scenario input values, the user should standardise
  // them so that they exist inside a hypercube.
  //
  // Regarding simulation output data, the user should transform it so that the
  // mean is zero and the variance is one.
  //
  // Regarding experimental scenario input values, the user should standardize
  // them so that they exist inside a hypercube.
  //
  // Regarding experimental data, the user should transformed it so that it has
  // zero mean and variance one.

  // GPMSA stores all the information about our simulation
  // data and experimental data.  It also stores default information about the
  // hyperparameter distributions.
  QUESO::GPMSAFactory<QUESO::GslVector, QUESO::GslMatrix>
    gpmsaFactory(env,
                 NULL,
                 priorRv,
                 configSpace,
                 paramSpace,
                 nEtaSpace,
                 experimentSpace,
                 numSimulations,
                 numExperiments);

  // std::vector containing all the points in scenario space where we have
  // simulations
  std::vector<QUESO::GslVector *> simulationScenarios(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the points in parameter space where we have
  // simulations
  std::vector<QUESO::GslVector *> paramVecs(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the simulation output data
  std::vector<QUESO::GslVector *> outputVecs(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the points in scenario space where we have
  // experiments
  std::vector<QUESO::GslVector *> experimentScenarios(numExperiments,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the experimental output data
  std::vector<QUESO::GslVector *> experimentVecs(numExperiments,
      (QUESO::GslVector *) NULL);

  // The experimental output data observation error covariance matrix
  QUESO::GslMatrix experimentMat(totalExperimentSpace.zeroVector());

  // Instantiate each of the simulation points/outputs
  for (unsigned int i = 0; i < numSimulations; i++) {
    simulationScenarios[i] = new QUESO::GslVector(configSpace.zeroVector());  // 'x_{i+1}^*' in paper
    paramVecs          [i] = new QUESO::GslVector(paramSpace.zeroVector());  // 't_{i+1}^*' in paper
    outputVecs         [i] = new QUESO::GslVector(nEtaSpace.zeroVector());  // 'eta_{i+1}' in paper
  }

  for (unsigned int i = 0; i < numExperiments; i++) {
    experimentScenarios[i] = new QUESO::GslVector(configSpace.zeroVector()); // 'x_{i+1}' in paper
    experimentVecs[i] = new QUESO::GslVector(experimentSpace.zeroVector());
  }

  // Read in data and store the standard deviation of the simulation data.  We
  // will need the standard deviation when we pass the experiment error
  // covariance matrix to QUESO.
  double stdsim = readData(simulationScenarios,
                           paramVecs,
                           outputVecs,
                           experimentScenarios,
                           experimentVecs);

  for (unsigned int i = 0; i < numExperiments; i++) {
    // Passing in error of experiments (standardised).
    experimentMat(i, i) = (0.025 / stdsim) * (0.025 / stdsim);
  }

  // Add simulation and experimental data
  gpmsaFactory.addSimulations(simulationScenarios, paramVecs, outputVecs);
  gpmsaFactory.addExperiments(experimentScenarios, experimentVecs, &experimentMat);

  QUESO::GenericVectorRV<QUESO::GslVector, QUESO::GslMatrix> postRv(
      "post_",
      gpmsaFactory.prior().imageSet().vectorSpace());
  QUESO::StatisticalInverseProblem<QUESO::GslVector, QUESO::GslMatrix> ip("",
      NULL, gpmsaFactory, postRv);

  QUESO::GslVector paramInitials(
      gpmsaFactory.prior().imageSet().vectorSpace().zeroVector());

  // Initial condition of the chain
  // Have to set each of these by hand, *and* the sampler is sensitive to these
  // values
  paramInitials[0] = 0.5; // param 1
  paramInitials[1] = 0.5; // param 2
  paramInitials[2] = 0.5; // param 3
  paramInitials[3] = 0.5; // param 4
  paramInitials[4] = 0.5; // param 5
  paramInitials[5]  = 0.4;  // not used.  emulator mean
  paramInitials[6]  = 0.4; // emulator precision
  paramInitials[7]  = 0.97; // emulator corr str
  paramInitials[8]  = 0.97; // emulator corr str
  paramInitials[9]  = 0.97; // emulator corr str
  paramInitials[10]  = 0.97; // emulator corr str
  paramInitials[11]  = 0.20; // emulator corr str
  paramInitials[12]  = 0.80; // emulator corr str
  paramInitials[13]  = 10.0; // discrepancy precision
  paramInitials[14]  = 0.97; // discrepancy corr str
  paramInitials[15]  = 8000.0; // emulator data precision

  QUESO::GslMatrix proposalCovMatrix(
      gpmsaFactory.prior().imageSet().vectorSpace().zeroVector());

  // Setting the proposal covariance matrix by hand.  This requires great
  // forethough, and can generally be referred to as a massive hack.  These
  // values were taken from the gpmsa matlab code and fiddled with.
  double scale = 600.0;
  proposalCovMatrix(0, 0)   = 3.1646 / 10.0;  // param 1
  proposalCovMatrix(1, 1)   = 3.1341 / 10.0;  // param 2
  proposalCovMatrix(2, 2)   = 3.1508 / 10.0;  // param 3
  proposalCovMatrix(3, 3)   = 0.3757 / 10.0;  // param 4
  proposalCovMatrix(4, 4)   = 0.6719 / 10.0;  // param 5
  proposalCovMatrix(5, 5)   = 0.1 / scale;  // not used.  emulator mean
  proposalCovMatrix(6, 6)   = 0.4953 / scale;  // emulator precision
  proposalCovMatrix(7, 7)   = 0.6058 / scale;  // emulator corr str
  proposalCovMatrix(8, 8)   = 7.6032e-04 / scale;  // emulator corr str
  proposalCovMatrix(9, 9)   = 8.3815e-04 / scale;  // emulator corr str
  proposalCovMatrix(10, 10) = 7.5412e-04 / scale;  // emulator corr str
  proposalCovMatrix(11, 11) = 0.2682 / scale;  // emulator corr str
  proposalCovMatrix(12, 12) = 0.0572 / scale;  // emulator corr str
  proposalCovMatrix(13, 13) = 1.3417 / scale;  // discrepancy precision
  proposalCovMatrix(14, 14) = 0.3461 / scale;  // discrepancy corr str
  proposalCovMatrix(15, 15) = 495.3 / scale;  // emulator data precision

  // Square to get variances
  for (unsigned int i = 0; i < 16; i++) {
    proposalCovMatrix(i, i) = proposalCovMatrix(i, i) * proposalCovMatrix(i, i);
  }

  ip.solveWithBayesMetropolisHastings(NULL, paramInitials, &proposalCovMatrix);

  MPI_Finalize();

  return 0;
}
<commit_msg>Backup, failure reporting for fopen<commit_after>#include <queso/GslVector.h>
#include <queso/GslMatrix.h>
#include <queso/UniformVectorRV.h>
#include <queso/StatisticalInverseProblem.h>
#include <queso/VectorSet.h>
#include <queso/GPMSA.h>

#include <cstdio>

// Read in data files
double readData(const std::vector<QUESO::GslVector *> & simulationScenarios,
    const std::vector<QUESO::GslVector *> & simulationParameters,
    const std::vector<QUESO::GslVector *> & simulationOutputs,
    const std::vector<QUESO::GslVector *> & experimentScenarios,
    const std::vector<QUESO::GslVector *> & experimentOutputs) {
  FILE * fp_in = fopen("gp/scalar/dakota_pstudy.dat", "r");
  if (!fp_in)
    fp_in = fopen("dakota_pstudy.dat", "r");
  if (!fp_in)
    queso_error_msg("Cannot find dakota_pstudy.dat");

  unsigned int i, id, size = 512;
  double k_tmasl, k_tmoml, k_tnrgl, k_xkwlx, k_cd, pressure;
  char line[size];

  // The user should know what the bounds on the data are
  double mins[] = {0.95, 0.9, 0.9, 0.9, 0.9};
  double maxs[] = {1.05, 1.1, 1.1, 1.1, 1.1};

  double meansim = 0;
  double m2sim = 0;

  // First line is a header, so we ignore it
  fgets(line, size, fp_in);

  i = 0;
  while (fscanf(fp_in, "%d %lf %lf %lf %lf %lf %lf\n", &id, &k_tmasl, &k_tmoml,
        &k_tnrgl, &k_xkwlx, &k_cd, &pressure) != EOF) {
    (*(simulationScenarios[i]))[0] = 0.5;

    (*(simulationParameters[i]))[0] = (k_tmasl - mins[0]) / (maxs[0] - mins[0]);
    (*(simulationParameters[i]))[1] = (k_tmoml - mins[1]) / (maxs[1] - mins[1]);
    (*(simulationParameters[i]))[2] = (k_tnrgl - mins[2]) / (maxs[2] - mins[2]);
    (*(simulationParameters[i]))[3] = (k_xkwlx - mins[3]) / (maxs[3] - mins[3]);
    (*(simulationParameters[i]))[4] = (k_cd    - mins[4]) / (maxs[4] - mins[4]);

    (*(simulationOutputs[i]))[0] = pressure;
    i++;

    double delta = pressure - meansim;
    meansim += delta / i;
    m2sim += delta * (pressure - meansim);
  }

  double stdsim = m2sim / (double)(i - 1);

  // The user is required to standardise the experimental and simulation data
  for (unsigned int j = 0; j < i; j++) {
    (*(simulationOutputs[j]))[0] -= meansim;
    (*(simulationOutputs[j]))[0] /= stdsim;
  }

  fclose(fp_in);  // Done with simulation data

  // Read in experimental data
  fp_in = fopen("gp/scalar/ctf_dat.txt", "r");
  if (!fp_in)
    fp_in = fopen("ctf_dat.txt", "r");
  if (!fp_in)
    queso_error_msg("Cannot find ctf_dat.txt");

  i = 0;
  while (fscanf(fp_in, "%lf\n", &pressure) != EOF) {
    (*(experimentOutputs[i]))[0] = pressure;
    i++;
  }

  // Also required to standardise experimental data too
  for (unsigned int j = 0; j < i; j++) {
    (*(experimentOutputs[j]))[0] -= meansim;
    (*(experimentOutputs[j]))[0] /= stdsim;
  }

  fclose(fp_in);

  // Returning standard deviation of data (simulation data is treated as
  // plentiful and the standard deviation of this data is treated as the 'true'
  // standard deviation of the data.  This can be argued.)
  return stdsim;
}

int main(int argc, char ** argv) {
  // Step 0: Set up some variables
  unsigned int numExperiments = 10;  // Number of experiments
  unsigned int numUncertainVars = 5;  // Number of things to calibrate
  unsigned int numSimulations = 50;  // Number of simulations
  unsigned int numConfigVars = 1;  // Dimension of configuration space
  unsigned int numEta = 1;  // Number of responses the model is returning
  unsigned int experimentSize = 1;  // Size of each experiment

  MPI_Init(&argc, &argv);

  // Step 1: Set up QUESO environment
  QUESO::FullEnvironment env(MPI_COMM_WORLD, argv[1], "", NULL);

  // Step 2: Set up prior for calibration parameters
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> paramSpace(env,
      "param_", numUncertainVars, NULL);

  // Parameter (theta) bounds:
  //   descriptors   'k_tmasl' 'k_xkle' 'k_xkwew' 'k_xkwlx' 'k_cd'
  //   upper_bounds   1.05      1.1      1.1       1.1       1.1
  //   lower_bounds   0.95      0.9      0.9       0.9       0.9
  //
  // These bounds are dealt with when reading in the data
  QUESO::GslVector paramMins(paramSpace.zeroVector());
  QUESO::GslVector paramMaxs(paramSpace.zeroVector());

  paramMins.cwSet(0.0);
  paramMaxs.cwSet(1.0);

  QUESO::BoxSubset<QUESO::GslVector, QUESO::GslMatrix> paramDomain("param_",
      paramSpace, paramMins, paramMaxs);

  QUESO::UniformVectorRV<QUESO::GslVector, QUESO::GslMatrix> priorRv("prior_",
      paramDomain);

  // Step 3: Instantiate the 'scenario' and 'output' spaces for simulation
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> configSpace(env,
      "scenario_", numConfigVars, NULL);

  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> nEtaSpace(env,
      "output_", numEta, NULL);

  // Step 4: Instantiate the 'output' space for the experiments
  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> experimentSpace(env,
      "experimentspace_", experimentSize, NULL);

  QUESO::VectorSpace<QUESO::GslVector, QUESO::GslMatrix> totalExperimentSpace(env,
      "experimentspace_", experimentSize * numExperiments, NULL);

  // Step 5: Instantiate the Gaussian process emulator object
  //
  // Regarding simulation scenario input values, the user should standardise
  // them so that they exist inside a hypercube.
  //
  // Regarding simulation output data, the user should transform it so that the
  // mean is zero and the variance is one.
  //
  // Regarding experimental scenario input values, the user should standardize
  // them so that they exist inside a hypercube.
  //
  // Regarding experimental data, the user should transformed it so that it has
  // zero mean and variance one.

  // GPMSA stores all the information about our simulation
  // data and experimental data.  It also stores default information about the
  // hyperparameter distributions.
  QUESO::GPMSAFactory<QUESO::GslVector, QUESO::GslMatrix>
    gpmsaFactory(env,
                 NULL,
                 priorRv,
                 configSpace,
                 paramSpace,
                 nEtaSpace,
                 experimentSpace,
                 numSimulations,
                 numExperiments);

  // std::vector containing all the points in scenario space where we have
  // simulations
  std::vector<QUESO::GslVector *> simulationScenarios(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the points in parameter space where we have
  // simulations
  std::vector<QUESO::GslVector *> paramVecs(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the simulation output data
  std::vector<QUESO::GslVector *> outputVecs(numSimulations,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the points in scenario space where we have
  // experiments
  std::vector<QUESO::GslVector *> experimentScenarios(numExperiments,
      (QUESO::GslVector *) NULL);

  // std::vector containing all the experimental output data
  std::vector<QUESO::GslVector *> experimentVecs(numExperiments,
      (QUESO::GslVector *) NULL);

  // The experimental output data observation error covariance matrix
  QUESO::GslMatrix experimentMat(totalExperimentSpace.zeroVector());

  // Instantiate each of the simulation points/outputs
  for (unsigned int i = 0; i < numSimulations; i++) {
    simulationScenarios[i] = new QUESO::GslVector(configSpace.zeroVector());  // 'x_{i+1}^*' in paper
    paramVecs          [i] = new QUESO::GslVector(paramSpace.zeroVector());  // 't_{i+1}^*' in paper
    outputVecs         [i] = new QUESO::GslVector(nEtaSpace.zeroVector());  // 'eta_{i+1}' in paper
  }

  for (unsigned int i = 0; i < numExperiments; i++) {
    experimentScenarios[i] = new QUESO::GslVector(configSpace.zeroVector()); // 'x_{i+1}' in paper
    experimentVecs[i] = new QUESO::GslVector(experimentSpace.zeroVector());
  }

  // Read in data and store the standard deviation of the simulation data.  We
  // will need the standard deviation when we pass the experiment error
  // covariance matrix to QUESO.
  double stdsim = readData(simulationScenarios,
                           paramVecs,
                           outputVecs,
                           experimentScenarios,
                           experimentVecs);

  for (unsigned int i = 0; i < numExperiments; i++) {
    // Passing in error of experiments (standardised).
    experimentMat(i, i) = (0.025 / stdsim) * (0.025 / stdsim);
  }

  // Add simulation and experimental data
  gpmsaFactory.addSimulations(simulationScenarios, paramVecs, outputVecs);
  gpmsaFactory.addExperiments(experimentScenarios, experimentVecs, &experimentMat);

  QUESO::GenericVectorRV<QUESO::GslVector, QUESO::GslMatrix> postRv(
      "post_",
      gpmsaFactory.prior().imageSet().vectorSpace());
  QUESO::StatisticalInverseProblem<QUESO::GslVector, QUESO::GslMatrix> ip("",
      NULL, gpmsaFactory, postRv);

  QUESO::GslVector paramInitials(
      gpmsaFactory.prior().imageSet().vectorSpace().zeroVector());

  // Initial condition of the chain
  // Have to set each of these by hand, *and* the sampler is sensitive to these
  // values
  paramInitials[0] = 0.5; // param 1
  paramInitials[1] = 0.5; // param 2
  paramInitials[2] = 0.5; // param 3
  paramInitials[3] = 0.5; // param 4
  paramInitials[4] = 0.5; // param 5
  paramInitials[5]  = 0.4;  // not used.  emulator mean
  paramInitials[6]  = 0.4; // emulator precision
  paramInitials[7]  = 0.97; // emulator corr str
  paramInitials[8]  = 0.97; // emulator corr str
  paramInitials[9]  = 0.97; // emulator corr str
  paramInitials[10]  = 0.97; // emulator corr str
  paramInitials[11]  = 0.20; // emulator corr str
  paramInitials[12]  = 0.80; // emulator corr str
  paramInitials[13]  = 10.0; // discrepancy precision
  paramInitials[14]  = 0.97; // discrepancy corr str
  paramInitials[15]  = 8000.0; // emulator data precision

  QUESO::GslMatrix proposalCovMatrix(
      gpmsaFactory.prior().imageSet().vectorSpace().zeroVector());

  // Setting the proposal covariance matrix by hand.  This requires great
  // forethough, and can generally be referred to as a massive hack.  These
  // values were taken from the gpmsa matlab code and fiddled with.
  double scale = 600.0;
  proposalCovMatrix(0, 0)   = 3.1646 / 10.0;  // param 1
  proposalCovMatrix(1, 1)   = 3.1341 / 10.0;  // param 2
  proposalCovMatrix(2, 2)   = 3.1508 / 10.0;  // param 3
  proposalCovMatrix(3, 3)   = 0.3757 / 10.0;  // param 4
  proposalCovMatrix(4, 4)   = 0.6719 / 10.0;  // param 5
  proposalCovMatrix(5, 5)   = 0.1 / scale;  // not used.  emulator mean
  proposalCovMatrix(6, 6)   = 0.4953 / scale;  // emulator precision
  proposalCovMatrix(7, 7)   = 0.6058 / scale;  // emulator corr str
  proposalCovMatrix(8, 8)   = 7.6032e-04 / scale;  // emulator corr str
  proposalCovMatrix(9, 9)   = 8.3815e-04 / scale;  // emulator corr str
  proposalCovMatrix(10, 10) = 7.5412e-04 / scale;  // emulator corr str
  proposalCovMatrix(11, 11) = 0.2682 / scale;  // emulator corr str
  proposalCovMatrix(12, 12) = 0.0572 / scale;  // emulator corr str
  proposalCovMatrix(13, 13) = 1.3417 / scale;  // discrepancy precision
  proposalCovMatrix(14, 14) = 0.3461 / scale;  // discrepancy corr str
  proposalCovMatrix(15, 15) = 495.3 / scale;  // emulator data precision

  // Square to get variances
  for (unsigned int i = 0; i < 16; i++) {
    proposalCovMatrix(i, i) = proposalCovMatrix(i, i) * proposalCovMatrix(i, i);
  }

  ip.solveWithBayesMetropolisHastings(NULL, paramInitials, &proposalCovMatrix);

  MPI_Finalize();

  return 0;
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "mediasource.h"
#include "mediasource_p.h"
#include "iodevicestream.h"
#include "abstractmediastream_p.h"

#include <QtCore/QFileInfo>
#include <QtCore/QFile>

QT_BEGIN_NAMESPACE

namespace Phonon
{

MediaSource::MediaSource(MediaSourcePrivate &dd)
    : d(&dd)
{
}

MediaSource::MediaSource()
    : d(new MediaSourcePrivate(Invalid))
{
}

MediaSource::MediaSource(const QString &filename)
    : d(new MediaSourcePrivate(LocalFile))
{
    if (filename.size() > 0 && filename.startsWith(QLatin1Char(':'))) {
        // it's a Qt resource -> use QFile
        d->type = Stream;
        d->ioDevice = new QFile(filename);
        d->stream = new IODeviceStream(d->ioDevice, d->ioDevice);
    } else {
        const QFileInfo fileInfo(filename);
        if (fileInfo.exists()) {
            d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
        } else {
            d->type = Invalid;
        }
    }
}

MediaSource::MediaSource(const QUrl &url)
    : d(new MediaSourcePrivate(Url))
{
    if (url.isValid()) {
        d->url = url;
    } else {
        d->type = Invalid;
    }
}

MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName)
    : d(new MediaSourcePrivate(Disc))
{
    if (dt == NoDisc) {
        d->type = Invalid;
        return;
    }
    d->discType = dt;
    d->deviceName = deviceName;
}

MediaSource::MediaSource(AbstractMediaStream *stream)
    : d(new MediaSourcePrivate(Stream))
{
    if (stream) {
        d->stream = stream;
    } else {
        d->type = Invalid;
    }
}

MediaSource::MediaSource(QIODevice *ioDevice)
    : d(new MediaSourcePrivate(Stream))
{
    if (ioDevice) {
        d->stream = new IODeviceStream(ioDevice, ioDevice);
        d->ioDevice = ioDevice;
    } else {
        d->type = Invalid;
    }
}

/* post 4.0
MediaSource::MediaSource(const QList<MediaSource> &mediaList)
    : d(new MediaSourcePrivate(Link))
{
    d->linkedSources = mediaList;
    foreach (MediaSource ms, mediaList) {
        Q_ASSERT(ms.type() != Link);
    }
}

QList<MediaSource> MediaSource::substreams() const
{
    return d->linkedSources;
}
*/

MediaSource::~MediaSource()
{
}

MediaSource::MediaSource(const MediaSource &rhs)
    : d(rhs.d)
{
}

MediaSource &MediaSource::operator=(const MediaSource &rhs)
{
    d = rhs.d;
    return *this;
}

bool MediaSource::operator==(const MediaSource &rhs) const
{
    return d == rhs.d;
}

void MediaSource::setAutoDelete(bool autoDelete)
{
    d->autoDelete = autoDelete;
}

bool MediaSource::autoDelete() const
{
    return d->autoDelete;
}

MediaSource::Type MediaSource::type() const
{
    if (d->type == Stream && d->stream == 0) {
        return Invalid;
    }
    return d->type;
}

QString MediaSource::fileName() const
{
    return d->url.toLocalFile();
}

QUrl MediaSource::url() const
{
    return d->url;
}

Phonon::DiscType MediaSource::discType() const
{
    return d->discType;
}

QString MediaSource::deviceName() const
{
    return d->deviceName;
}

AbstractMediaStream *MediaSource::stream() const
{
    return d->stream;
}

//X AudioCaptureDevice MediaSource::audioCaptureDevice() const
//X {
//X     return d->audioCaptureDevice;
//X }
//X
//X VideoCaptureDevice MediaSource::videoCaptureDevice() const
//X {
//X     return d->videoCaptureDevice;
//X }

} // namespace Phonon

QT_END_NAMESPACE

// vim: sw=4 sts=4 et tw=100
<commit_msg>handling of url as strings<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "mediasource.h"
#include "mediasource_p.h"
#include "iodevicestream.h"
#include "abstractmediastream_p.h"

#include <QtCore/QFileInfo>
#include <QtCore/QFile>

QT_BEGIN_NAMESPACE

namespace Phonon
{

MediaSource::MediaSource(MediaSourcePrivate &dd)
    : d(&dd)
{
}

MediaSource::MediaSource()
    : d(new MediaSourcePrivate(Invalid))
{
}

MediaSource::MediaSource(const QString &filename)
    : d(new MediaSourcePrivate(LocalFile))
{
    if (filename.size() > 0 && filename.startsWith(QLatin1Char(':'))) {
        // it's a Qt resource -> use QFile
        d->type = Stream;
        d->ioDevice = new QFile(filename);
        d->stream = new IODeviceStream(d->ioDevice, d->ioDevice);
    } else if (filename.contains(QLatin1String("://"))) {
        d->url = filename;
        d->type = Url;
    } else {
        const QFileInfo fileInfo(filename);
        if (fileInfo.exists()) {
            d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
        } else {
            d->type = Invalid;
        }
    }
}

MediaSource::MediaSource(const QUrl &url)
    : d(new MediaSourcePrivate(Url))
{
    if (url.isValid()) {
        d->url = url;
    } else {
        d->type = Invalid;
    }
}

MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName)
    : d(new MediaSourcePrivate(Disc))
{
    if (dt == NoDisc) {
        d->type = Invalid;
        return;
    }
    d->discType = dt;
    d->deviceName = deviceName;
}

MediaSource::MediaSource(AbstractMediaStream *stream)
    : d(new MediaSourcePrivate(Stream))
{
    if (stream) {
        d->stream = stream;
    } else {
        d->type = Invalid;
    }
}

MediaSource::MediaSource(QIODevice *ioDevice)
    : d(new MediaSourcePrivate(Stream))
{
    if (ioDevice) {
        d->stream = new IODeviceStream(ioDevice, ioDevice);
        d->ioDevice = ioDevice;
    } else {
        d->type = Invalid;
    }
}

/* post 4.0
MediaSource::MediaSource(const QList<MediaSource> &mediaList)
    : d(new MediaSourcePrivate(Link))
{
    d->linkedSources = mediaList;
    foreach (MediaSource ms, mediaList) {
        Q_ASSERT(ms.type() != Link);
    }
}

QList<MediaSource> MediaSource::substreams() const
{
    return d->linkedSources;
}
*/

MediaSource::~MediaSource()
{
}

MediaSource::MediaSource(const MediaSource &rhs)
    : d(rhs.d)
{
}

MediaSource &MediaSource::operator=(const MediaSource &rhs)
{
    d = rhs.d;
    return *this;
}

bool MediaSource::operator==(const MediaSource &rhs) const
{
    return d == rhs.d;
}

void MediaSource::setAutoDelete(bool autoDelete)
{
    d->autoDelete = autoDelete;
}

bool MediaSource::autoDelete() const
{
    return d->autoDelete;
}

MediaSource::Type MediaSource::type() const
{
    if (d->type == Stream && d->stream == 0) {
        return Invalid;
    }
    return d->type;
}

QString MediaSource::fileName() const
{
    return d->url.toLocalFile();
}

QUrl MediaSource::url() const
{
    return d->url;
}

Phonon::DiscType MediaSource::discType() const
{
    return d->discType;
}

QString MediaSource::deviceName() const
{
    return d->deviceName;
}

AbstractMediaStream *MediaSource::stream() const
{
    return d->stream;
}

//X AudioCaptureDevice MediaSource::audioCaptureDevice() const
//X {
//X     return d->audioCaptureDevice;
//X }
//X
//X VideoCaptureDevice MediaSource::videoCaptureDevice() const
//X {
//X     return d->videoCaptureDevice;
//X }

} // namespace Phonon

QT_END_NAMESPACE

// vim: sw=4 sts=4 et tw=100
<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#ifndef xeumeuleu_translate_hpp
#define xeumeuleu_translate_hpp

#define XEUMEULEU_TRANSCODER_ENCODING "utf-8"
#define XEUMEULEU_TRANSCODER_BUFFER_SIZE 128

#include <xeumeuleu/bridges/xerces/detail/xerces.hpp>
#include <vector>
#include <string>

namespace xml
{
// =============================================================================
/** @class  translate
    @brief  String translation helpers
*/
// Created: MAT 2006-01-04
// =============================================================================
class translate
{
public:
    //! @name Constructors/Destructor
    //@{
    explicit translate( const std::string& str )
        : transcoder_( create() )
        , s_         ( transcode( str ) )
        , ch_        ( &s_[0] )
    {}
    explicit translate( const XMLCh* const ch )
        : transcoder_( create() )
        , ch_        ( ch )
    {}
    translate( const translate& rhs )
        : transcoder_( create() )
        , s_         ( rhs.s_ )
        , ch_        ( s_.empty() ? rhs.ch_ : &s_[0] )
    {}
    //@}

    //! @name Operators
    //@{
    operator const XMLCh*() const
    {
        return ch_;
    }
    operator std::string() const
    {
        std::string result;
        const XMLSize_t size = XERCES_CPP_NAMESPACE::XMLString::stringLen( ch_ );
        XMLByte s[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        XMLSize_t done = 0;
        while( done < size )
        {
            Count_t read = 0;
            Count_t written = transcoder_->transcodeTo(
                ch_ + done, size - done,
                s, XEUMEULEU_TRANSCODER_BUFFER_SIZE,
                read, XERCES_CPP_NAMESPACE::XMLTranscoder::UnRep_RepChar );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            result.append( reinterpret_cast< const char* >( s ), written );
        }
        return result;
    }

    bool operator==( const XMLCh* const ch ) const
    {
        return XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator==( const std::string& str ) const
    {
        return translate( str ) == ch_;
    }
    bool operator!=( const XMLCh* const ch ) const
    {
        return ! XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator!=( const std::string& str ) const
    {
        return translate( str ) != ch_;
    }
    //@}

private:
    //! @name Helpers
    //@{
    XERCES_CPP_NAMESPACE::XMLTranscoder* create() const
    {
        XERCES_CPP_NAMESPACE::XMLTransService::Codes result;
        XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder(
            XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
                XEUMEULEU_TRANSCODER_ENCODING, result, 16 * 1024 ) );
        if( result != XERCES_CPP_NAMESPACE::XMLTransService::Ok )
            throw xml::exception( std::string( "unable to create transcoder for " ) + XEUMEULEU_TRANSCODER_ENCODING );
        return transcoder.release();
    }
    std::vector< XMLCh > transcode( const std::string& str ) const
    {
        std::vector< XMLCh > result;
        const XMLByte* in = reinterpret_cast< const XMLByte* >( str.c_str() );
        const XMLSize_t length = str.length();
        XMLCh s[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        unsigned char sizes[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        XMLSize_t done = 0;
        while( done < length )
        {
            Count_t read = 0;
            XMLSize_t written = transcoder_->transcodeFrom(
                in + done, length - done,
                s, XEUMEULEU_TRANSCODER_BUFFER_SIZE,
                read, sizes );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            result.insert( result.end(), s, s + written );
        }
        result.resize( result.size() + 4 );
        return result;
    }
    //@}

private:
    //! @name Copy/Assignment
    //@{
    translate& operator=( const translate& ); //!< Assignment operator
    //@}

private:
    //! @name Member data
    //@{
    XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder_;
    const std::vector< XMLCh > s_;
    const XMLCh* const ch_;
    //@}
};

inline bool operator==( const XMLCh* const ch, const translate& tr )
{
    return tr == ch;
}
inline bool operator==( const std::string& str, const translate& tr )
{
    return tr == str;
}

inline bool operator!=( const XMLCh* const ch, const translate& tr )
{
    return tr != ch;
}
inline bool operator!=( const std::string& str, const translate& tr )
{
    return tr != str;
}

inline std::string operator+( const translate& tr, const std::string& str )
{
    return std::string( tr ) + str;
}
inline std::string operator+( const std::string& str, const translate& tr )
{
    return str + std::string( tr );
}

}

#endif // xeumeuleu_translate_hpp
<commit_msg>Added missing const<commit_after>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#ifndef xeumeuleu_translate_hpp
#define xeumeuleu_translate_hpp

#define XEUMEULEU_TRANSCODER_ENCODING "utf-8"
#define XEUMEULEU_TRANSCODER_BUFFER_SIZE 128

#include <xeumeuleu/bridges/xerces/detail/xerces.hpp>
#include <vector>
#include <string>

namespace xml
{
// =============================================================================
/** @class  translate
    @brief  String translation helpers
*/
// Created: MAT 2006-01-04
// =============================================================================
class translate
{
public:
    //! @name Constructors/Destructor
    //@{
    explicit translate( const std::string& str )
        : transcoder_( create() )
        , s_         ( transcode( str ) )
        , ch_        ( &s_[0] )
    {}
    explicit translate( const XMLCh* const ch )
        : transcoder_( create() )
        , ch_        ( ch )
    {}
    translate( const translate& rhs )
        : transcoder_( create() )
        , s_         ( rhs.s_ )
        , ch_        ( s_.empty() ? rhs.ch_ : &s_[0] )
    {}
    //@}

    //! @name Operators
    //@{
    operator const XMLCh*() const
    {
        return ch_;
    }
    operator std::string() const
    {
        std::string result;
        const XMLSize_t size = XERCES_CPP_NAMESPACE::XMLString::stringLen( ch_ );
        XMLByte s[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        XMLSize_t done = 0;
        while( done < size )
        {
            Count_t read = 0;
            const Count_t written = transcoder_->transcodeTo(
                ch_ + done, size - done,
                s, XEUMEULEU_TRANSCODER_BUFFER_SIZE,
                read, XERCES_CPP_NAMESPACE::XMLTranscoder::UnRep_RepChar );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            result.append( reinterpret_cast< const char* >( s ), written );
        }
        return result;
    }

    bool operator==( const XMLCh* const ch ) const
    {
        return XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator==( const std::string& str ) const
    {
        return translate( str ) == ch_;
    }
    bool operator!=( const XMLCh* const ch ) const
    {
        return ! XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator!=( const std::string& str ) const
    {
        return translate( str ) != ch_;
    }
    //@}

private:
    //! @name Helpers
    //@{
    XERCES_CPP_NAMESPACE::XMLTranscoder* create() const
    {
        XERCES_CPP_NAMESPACE::XMLTransService::Codes result;
        XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder(
            XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
                XEUMEULEU_TRANSCODER_ENCODING, result, 16 * 1024 ) );
        if( result != XERCES_CPP_NAMESPACE::XMLTransService::Ok )
            throw xml::exception( std::string( "unable to create transcoder for " ) + XEUMEULEU_TRANSCODER_ENCODING );
        return transcoder.release();
    }
    std::vector< XMLCh > transcode( const std::string& str ) const
    {
        std::vector< XMLCh > result;
        const XMLByte* in = reinterpret_cast< const XMLByte* >( str.c_str() );
        const XMLSize_t size = str.length();
        XMLCh s[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        unsigned char sizes[ XEUMEULEU_TRANSCODER_BUFFER_SIZE ];
        XMLSize_t done = 0;
        while( done < size )
        {
            Count_t read = 0;
            const XMLSize_t written = transcoder_->transcodeFrom(
                in + done, size - done,
                s, XEUMEULEU_TRANSCODER_BUFFER_SIZE,
                read, sizes );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            result.insert( result.end(), s, s + written );
        }
        result.resize( result.size() + 4 );
        return result;
    }
    //@}

private:
    //! @name Copy/Assignment
    //@{
    translate& operator=( const translate& ); //!< Assignment operator
    //@}

private:
    //! @name Member data
    //@{
    XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder_;
    const std::vector< XMLCh > s_;
    const XMLCh* const ch_;
    //@}
};

inline bool operator==( const XMLCh* const ch, const translate& tr )
{
    return tr == ch;
}
inline bool operator==( const std::string& str, const translate& tr )
{
    return tr == str;
}

inline bool operator!=( const XMLCh* const ch, const translate& tr )
{
    return tr != ch;
}
inline bool operator!=( const std::string& str, const translate& tr )
{
    return tr != str;
}

inline std::string operator+( const translate& tr, const std::string& str )
{
    return std::string( tr ) + str;
}
inline std::string operator+( const std::string& str, const translate& tr )
{
    return str + std::string( tr );
}

}

#endif // xeumeuleu_translate_hpp
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: PrintHeader.cxx,v $
  Language:  C++
  Date:      $Date: 2009/01/05 20:09:47 $
  Version:   $Revision: 1.4 $

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"
#include "itkCastImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"

template <unsigned int ImageDimension>
int PrintHeader(int argc, char *argv[])
{

  typedef  float  outPixelType;
  typedef  float floatPixelType;
  typedef  float inPixelType;
  typedef itk::Image<inPixelType,ImageDimension> ImageType;
  typedef itk::Image<floatPixelType,ImageDimension> IntermediateType;
  typedef itk::Image<outPixelType,ImageDimension> OutImageType;
  typedef itk::ImageFileReader<ImageType> readertype;
  typedef itk::ImageFileWriter<OutImageType> writertype;

  typename readertype::Pointer reader = readertype::New();
  reader->SetFileName(argv[1]);
  reader->Update();
  std::cout << " Spacing " << reader->GetOutput()->GetSpacing() << std::endl;
  std::cout << " Origin " << reader->GetOutput()->GetOrigin() << std::endl;
  std::cout << " Direction " << std::endl << reader->GetOutput()->GetDirection() << std::endl;
  std::cout << " Size : " << reader->GetOutput()->GetLargestPossibleRegion().GetSize() << std::endl;
//  std::cout << " Orientation " << reader->GetOutput()->GetOrientation() << std::endl;

  return 1;

}

int main(int argc, char *argv[])
{

  if ( argc < 2 )
    { std::cout << "Useage ex:  " << argv[0] << " image.ext " << std::endl;
    return 1;
  }

   // Get the image dimension
  std::string fn = std::string(argv[1]);
   itk::ImageIOBase::Pointer imageIO =
      itk::ImageIOFactory::CreateImageIO(
         fn.c_str(), itk::ImageIOFactory::ReadMode);
   imageIO->SetFileName(fn.c_str());
   imageIO->ReadImageInformation();

   switch ( imageIO->GetNumberOfDimensions() )
   {
   case 2:
     PrintHeader<2>(argc,argv);
      break;
   case 3:
     PrintHeader<3>(argc,argv);
      break;
   default:
      std::cerr << "Unsupported dimension" << std::endl;
      exit( EXIT_FAILURE );
   }

  return 0;
}

<commit_msg> minor edit to PrintHeader Output <commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: PrintHeader.cxx,v $
  Language:  C++
  Date:      $Date: 2009/01/05 20:09:47 $
  Version:   $Revision: 1.4 $

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"
#include "itkCastImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"

template <unsigned int ImageDimension>
int PrintHeader(int argc, char *argv[])
{

  typedef  float  outPixelType;
  typedef  float floatPixelType;
  typedef  float inPixelType;
  typedef itk::Image<inPixelType,ImageDimension> ImageType;
  typedef itk::Image<floatPixelType,ImageDimension> IntermediateType;
  typedef itk::Image<outPixelType,ImageDimension> OutImageType;
  typedef itk::ImageFileReader<ImageType> readertype;
  typedef itk::ImageFileWriter<OutImageType> writertype;

  typename readertype::Pointer reader = readertype::New();
  reader->SetFileName(argv[1]);
  reader->Update();
  std::cout << " Spacing " << reader->GetOutput()->GetSpacing() << std::endl;
  std::cout << " Origin " << reader->GetOutput()->GetOrigin() << std::endl;
  std::cout << " Direction " << std::endl << reader->GetOutput()->GetDirection() << std::endl;
  if ( ImageDimension == 1 )
  std::cout << " Size : " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] << " " <<  << std::endl;
  else if ( ImageDimension == 2 )
    std::cout << " Size : " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] << " " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] << " " << std::endl;
   else if ( ImageDimension == 2 )
    std::cout << " Size : " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] << " " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] << " " <<  " " << reader->GetOutput()->GetLargestPossibleRegion().GetSize()[2] << std::endl;
   else    std::cout << " Size : " << reader->GetOutput()->GetLargestPossibleRegion().GetSize() << std::endl;
//  std::cout << " Orientation " << reader->GetOutput()->GetOrientation() << std::endl;

  return 1;

}

int main(int argc, char *argv[])
{

  if ( argc < 2 )
    { std::cout << "Useage ex:  " << argv[0] << " image.ext " << std::endl;
    return 1;
  }

   // Get the image dimension
  std::string fn = std::string(argv[1]);
   itk::ImageIOBase::Pointer imageIO =
      itk::ImageIOFactory::CreateImageIO(
         fn.c_str(), itk::ImageIOFactory::ReadMode);
   imageIO->SetFileName(fn.c_str());
   imageIO->ReadImageInformation();

   switch ( imageIO->GetNumberOfDimensions() )
   {
   case 2:
     PrintHeader<2>(argc,argv);
      break;
   case 3:
     PrintHeader<3>(argc,argv);
      break;
   default:
      std::cerr << "Unsupported dimension" << std::endl;
      exit( EXIT_FAILURE );
   }

  return 0;
}

<|endoftext|>


<commit_before>// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-mingw32 -emit-llvm %s -o - | FileCheck %s

__interface I {
  int test() {
    return 1;
  }
};

struct S : I {
  virtual int test() override {
    return I::test();
  }
};

int fn() {
  S s;
  return s.test();
}

// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)]

// CHECK-LABEL: define i32 @_Z2fnv()
// CHECK:   call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s)
// CHECK:   %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %s)

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this)
// CHECK:   call x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})

// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this)
// CHECK:   %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}})

// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this)
// CHECK:   ret i32 1

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
// CHECK:   call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
// CHECK:   store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this)
// CHECK:   store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}

// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSERKS_(%__interface.I* %this, %__interface.I*)
// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSEOS_(%__interface.I* %this, %__interface.I*)
<commit_msg>MS ABI: Remove a useless FileCheck line<commit_after>// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-mingw32 -emit-llvm %s -o - | FileCheck %s

__interface I {
  int test() {
    return 1;
  }
};

struct S : I {
  virtual int test() override {
    return I::test();
  }
};

int fn() {
  S s;
  return s.test();
}

// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)]

// CHECK-LABEL: define i32 @_Z2fnv()
// CHECK:   call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s)
// CHECK:   %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %s)

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this)
// CHECK:   call x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})

// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this)
// CHECK:   %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}})

// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this)
// CHECK:   ret i32 1

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
// CHECK:   call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
// CHECK:   store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this)
// CHECK:   store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}
<|endoftext|>


<commit_before>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<int> in;
  set<int> out;
  set<int> all;
  RSplit() = default;
  RSplit(const set<int>& i, const set<int>& a)
    :in(i),all(a)
  {
    std::set_difference(all.begin(),all.end(),in.begin(),in.end(),std::inserter(out,out.end()));
    assert(in.size() + out.size() == all.size());
  }
};

void merge(int c1, int c2, map<int,int>& component, map<int,list<int>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(int i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);
}

unique_ptr<Tree_t> BUILD(const std::set<int>& tips, const vector<RSplit>& splits)
{
  map<int,int> component;    // tip -> component
  map<int,list<int>> elements; // component -> elements
  for(int i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  for(const auto& split: splits)
  {
    int c1 = -1;
    for(int i: split.in)
    {
      int c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  int first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    std::cout<<"Failure: 1 component!\n";
  std::cout<<"Components:\n";
  for(const auto& l:elements)
  {
    if (l.second.empty()) continue;

    std::cout<<"   "<<l.second<<"\n";
  }
  return {};
}

unique_ptr<Tree_t> BUILD(const std::set<int>& tips, const vector<RSplit>& splits, int n)
{

  return {};
}

map<long,int> get_name_mapping(const vector<long>& ids)
{
  std::map<long,int> names;
  for(int i=0;i<ids.size();i++)
    names[ids[i]] = i;
  return names;
}

set<int> remap_names(const set<long>& ids, const map<long,int>& name)
{
  set<int> indices;
  for(auto id: ids)
  {
    auto i = name.find(id);
    if (i == name.end())
      throw OTCError()<<"Can't find ottid "<<id<<" in taxonomy";
    indices.insert(i->second);
  }
  return indices;
}

vector<long> get_vector(const set<long>& ids)
{
  vector<long> v;
  for(long id: ids)
    v.push_back(id);
  return v;
}

unique_ptr<Tree_t> merge(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto leafset = taxonomy->getRoot()->getData().desIds;
  std::cout<<leafset<<std::endl;
  // i -> ids[i]
  vector<long> leaves = get_vector(leafset);
  // ids[i] -> i
  auto names = get_name_mapping(leaves);
  auto rename = [&names](const set<long>& ids) {return remap_names(ids,names);};
  auto all_leaves = rename(leafset);

  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    std::cout<<"Tree!\n";
    auto root = tree->getRoot();
    const auto leafTaxa = rename(root->getData().desIds);
    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = rename(nd->getData().desIds);
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      {
      	splits.push_back(split);
	std::cout<<split.in<<" | "<<split.out<<"\n";
      }
    }
    BUILD(all_leaves, splits);
  }

  for(int n=2;n<=splits.size();)
  {
    unique_ptr<Tree_t> result = BUILD(all_leaves, splits, n);
    if (not result)
      splits.erase(splits.begin()+(n-1));
    else
      n++;
  }

  return BUILD(all_leaves, splits, splits.size());
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-subproblem-stats",
                "takes at series of tree files. Each is treated as a subproblem.\n" \
                "For each subproblem there is tab-separated report for:\n" \
                "    Subproblem name\n" \
                "    InSp = # of informative (nontrivial) splits\n" \
                "    LSS = size of the leaf label set\n" \
                "    ILSS = size of the set of labels included in at least one \"ingroup\"\n" \
                "    NT = The number of trees.\n" \
                "    TreeSummaryName = tree index or summary name\n" \
                "where the summary name can be Phylo-only or Total. \n" \
                "  \"Total\" summarizes info all trees in the file (including the taxonomy).\n" \
                "  \"Phylo-only\" former summarizes all of the phylogenetic inputs",
                "taxonomy.tre supertree/step_7_scratch/export-sub-temp/ott1000236.tre supertree/step_7_scratch/export-sub-temp/ott1000250.tre");

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    // Want splits for each tip.
    // Not sure these trees are aligned to the taxonomy
    // They should have only terminals in desIds.
    treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1);

    merge(trees);
}
<commit_msg>Add some more bits.<commit_after>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<int> in;
  set<int> out;
  set<int> all;
  RSplit() = default;
  RSplit(const set<int>& i, const set<int>& a)
    :in(i),all(a)
  {
    std::set_difference(all.begin(),all.end(),in.begin(),in.end(),std::inserter(out,out.end()));
    assert(in.size() + out.size() == all.size());
  }
};

void merge(int c1, int c2, map<int,int>& component, map<int,list<int>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(int i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);
}

unique_ptr<Tree_t> BUILD(const std::set<int>& tips, const vector<RSplit>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (tips.size() == 1)
  {
    auto Node1 = tree->createChild(tree->getRoot());
    Node1->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  map<int,int> component;    // tip -> component
  map<int,list<int>> elements; // component -> elements
  for(int i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  for(const auto& split: splits)
  {
    int c1 = -1;
    for(int i: split.in)
    {
      int c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  int first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
  {
    std::cout<<"Failure: 1 component!\n";
    return {};
  }

  std::cout<<"Components:\n";
  map<int,set<int>> subtips;
  for(int c: tips)
  {
    if (c != component[c]) continue;

    set<int>& s = subtips[c];
    for(int l: elements[c])
      s.insert(l);
    std::cout<<"   "<<s<<"\n";
  }

  map<int,vector<RSplit>> subsplits;
  for(const auto& split: splits)
  {
    int first = *split.in.begin();
    int c = component[first];

  }

  return tree;
}

unique_ptr<Tree_t> BUILD(const std::set<int>& tips, const vector<RSplit>& splits, int n)
{

  return {};
}

map<long,int> get_name_mapping(const vector<long>& ids)
{
  std::map<long,int> names;
  for(int i=0;i<ids.size();i++)
    names[ids[i]] = i;
  return names;
}

set<int> remap_names(const set<long>& ids, const map<long,int>& name)
{
  set<int> indices;
  for(auto id: ids)
  {
    auto i = name.find(id);
    if (i == name.end())
      throw OTCError()<<"Can't find ottid "<<id<<" in taxonomy";
    indices.insert(i->second);
  }
  return indices;
}

vector<long> get_vector(const set<long>& ids)
{
  vector<long> v;
  for(long id: ids)
    v.push_back(id);
  return v;
}

unique_ptr<Tree_t> merge(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto leafset = taxonomy->getRoot()->getData().desIds;
  std::cout<<leafset<<std::endl;
  // i -> ids[i]
  vector<long> leaves = get_vector(leafset);
  // ids[i] -> i
  auto names = get_name_mapping(leaves);
  auto rename = [&names](const set<long>& ids) {return remap_names(ids,names);};
  auto all_leaves = rename(leafset);

  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    std::cout<<"Tree!\n";
    auto root = tree->getRoot();
    const auto leafTaxa = rename(root->getData().desIds);
    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = rename(nd->getData().desIds);
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      {
      	splits.push_back(split);
	std::cout<<split.in<<" | "<<split.out<<"\n";
      }
    }
    BUILD(all_leaves, splits);
  }

  for(int n=2;n<=splits.size();)
  {
    unique_ptr<Tree_t> result = BUILD(all_leaves, splits, n);
    if (not result)
      splits.erase(splits.begin()+(n-1));
    else
      n++;
  }

  return BUILD(all_leaves, splits, splits.size());
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-subproblem-stats",
                "takes at series of tree files. Each is treated as a subproblem.\n" \
                "For each subproblem there is tab-separated report for:\n" \
                "    Subproblem name\n" \
                "    InSp = # of informative (nontrivial) splits\n" \
                "    LSS = size of the leaf label set\n" \
                "    ILSS = size of the set of labels included in at least one \"ingroup\"\n" \
                "    NT = The number of trees.\n" \
                "    TreeSummaryName = tree index or summary name\n" \
                "where the summary name can be Phylo-only or Total. \n" \
                "  \"Total\" summarizes info all trees in the file (including the taxonomy).\n" \
                "  \"Phylo-only\" former summarizes all of the phylogenetic inputs",
                "taxonomy.tre supertree/step_7_scratch/export-sub-temp/ott1000236.tre supertree/step_7_scratch/export-sub-temp/ott1000250.tre");

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    // Want splits for each tip.
    // Not sure these trees are aligned to the taxonomy
    // They should have only terminals in desIds.
    treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1);

    merge(trees);
}
<|endoftext|>