#include "test_data.hpp"
#include <boost/test/unit_test.hpp>
#include "libs/ml_models/random_trees.h"
#include <iostream>

BOOST_AUTO_TEST_CASE(empty_data_rtree)
{
    mlmodels::random_trees model;
    auto m = model.train(mlmodels::training_data{},
            mlmodels::class_data{},
            mlmodels::random_trees::args{}
        );
    BOOST_TEST((m.get() == nullptr), "the model that we should get back from empty data set should be empty as well");
    mlmodels::testing_result out;
    auto r = model.predict(m, mlmodels::testing_data{}, out);
    BOOST_TEST(r == false, "should failed because training did not run");
    BOOST_TEST(out.empty(), "there should not be any data from the test");
}

BOOST_AUTO_TEST_CASE(test_model_create_rtree)
{
    const auto& samples = ut_data::unittest_data();
    const auto& classes = ut_data::classes4ut();
    BOOST_TEST_REQUIRE(mlmodels::rows(samples) == classes.size());

    mlmodels::random_trees b;
    auto m = b.train(samples,
                classes,
                mlmodels::random_trees::args{}
        );
    BOOST_TEST_REQUIRE((m.get() != nullptr), "we are expecting that this train would succeed");
    const auto& test_samples = ut_data::samples4test();
    BOOST_TEST_REQUIRE(mlmodels::rows(test_samples) < mlmodels::rows(samples));
    BOOST_TEST_REQUIRE(mlmodels::columns(test_samples) == mlmodels::columns(samples));
    auto p = b.test(m, test_samples, ut_data::NUMBER_OF_CLASSES);
    BOOST_TEST_REQUIRE(!p.empty(), "we are expecting to get entries from the test");
    BOOST_TEST_REQUIRE(p.size() == mlmodels::rows(test_samples));
    //mlmodels::save_model(m);
#ifdef PRINT_MODEL_RESULTS
    std::cout<<"model prediction for random_trees\n";
    for (auto f : p) {
        std::cout<<"["<<f<<"]";
    }
    std::cout<<std::endl;
#endif
}


/* Copyright © 2017 Apple Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-3-clause license that can
 * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
 */
#ifndef TURI_TEXT_SCVB_H_
#define TURI_TEXT_SCVB_H_

// SFrame
#include <sframe/sarray.hpp>
#include <sframe/sframe.hpp>

// Other
#include <fileio/temp_files.hpp>
#include <thread>
#include <iostream>

// Types
#include <unity/lib/variant.hpp>
#include <unity/lib/unity_base_types.hpp>
#include <flexible_type/flexible_type.hpp>
#include <util/hash_value.hpp>
#include <unity/lib/flex_dict_view.hpp>

// External
#include <Eigen/Core>
#include <random/random.hpp>

namespace turi {

namespace text {

class scvb0_solver {

 public:

  scvb0_solver(topic_model* _model) {

    model = _model;
    s = 10;
    tau = 1000;
    kappa = .9;

  }

  /**
   * Train the model using the SCVB0 algorithm.
   *
   * See Foulds, Boyles, DuBois, Smyth, Welling.
   * Stochastic Collapsed Variational Bayesian Inference
   * for Latent Dirichlet Allocation. KDD 2013.
   * See http://arxiv.org/pdf/1305.2452.pdf for a pdf.
   *
   * The key aspect of this algorithm is to keep a set of statistics that
   * describe the number of times each word in the vocabulary has been assigned
   * to each topic. We then iterate through minibatches of documents and
   * perform updates akin to online EM: we use our current statistics (N_Z and N_phi)
   * to make estimated "local" versions using the minibatch.
   *
   */
  void train(std::shared_ptr<sarray<flexible_type>> data, bool verbose);

 private:
  topic_model* model;

  // Hyperparameters for learning rate
  size_t s;
  size_t tau;
  double kappa;

  // Variables needed for SCVB0
  Eigen::MatrixXd N_Z;        /* < Estimate of N_Z for each topic. */
  Eigen::MatrixXd N_theta_j;  /* < Estimate of N_theta for document j. */
  Eigen::MatrixXd N_phi;      /* < Estimate of N_phi. */
  Eigen::MatrixXd N_phi_hat;  /* < Estimate of N_phi based on a minibatch. */
  Eigen::MatrixXd N_Z_hat;    /* < Estimate of N_Z based on a minibatch. */

 private:

  /**
   * Initialize global estimate of N_theta_j.
   */
  void initialize_N_theta_j(size_t C_j) {
     N_theta_j = Eigen::MatrixXd::Zero(model->num_topics, 1);
     for (size_t i = 0; i < C_j; ++i) {
       size_t ix = random::fast_uniform<size_t>(0, model->num_topics-1);
       N_theta_j(ix) += 1;
     }
  }

  /**
   * Compute the topic probabilities for a single token.
   *
   * \params w_ij The integer id for the word that is the i'th token
   *              of document j.
   *
   * \returns An Eigen vector of length num_topics containing the
   * estimated probability the word belongs to each of the topics.
   */
  Eigen::MatrixXd compute_gamma(size_t w_ij) {
    // DASSERT(j >= 0 && j < documents.size());
    // DASSERT(i >= 0 && i < vocab_size);
    Eigen::MatrixXd gamma_ij(model->num_topics, 1);
    for (size_t k = 0; k < model->num_topics; ++k) {
      gamma_ij(k, 0) = (N_phi(w_ij, k) + model->beta) *
        (N_theta_j(k) + model->alpha) /
        (N_Z(k) + model->beta * model->vocab_size);
    }
    gamma_ij.normalize();
    return gamma_ij;
  }

  /**
   * Compute a local estimate of topic proportions for this document.
   *
   */
  void update_N_theta_j(const Eigen::MatrixXd& gamma_ij,
                        size_t count_ij,
                        size_t C_j,
                        double rho) {
    double alpha = std::pow(1 - rho, count_ij);
    N_theta_j = alpha * N_theta_j + C_j * gamma_ij * (1 - alpha);
  }

  /**
   * Update the local estimate of N_Z using the current token probabilities.
   */
  void update_N_Z_hat(const Eigen::MatrixXd& gamma_ij,
                      size_t M, size_t C) {
    N_Z_hat += gamma_ij * C / M;
  }

  /**
   * Update the global estimate of N_Z using the current local estimates.
   */
  void update_N_Z(double rho) {
    N_Z = (1 - rho) * N_Z + rho * N_Z_hat;
  }

  /**
   * Update global estimate of N_phi using the current local estimates.
   */
  void update_N_phi(double rho) {
    N_phi = (1 - rho) * N_phi + rho * N_phi_hat;
  }

  /**
   * Update local estimate of N_phi with the current token probabilities.
   */
  void update_N_phi_hat(const Eigen::MatrixXd& gamma_ij,
                        size_t word_ij,
                        size_t M, size_t C) {
    for (size_t k = 0; k < model->num_topics; ++k) {
      N_phi_hat(word_ij, k) += gamma_ij(k) * C / M;
    }
  }

  /**
   * Compute the learning rate for a given iteration.
   * The default values have been reported to experimentally provide
   * reasonable learning rates for real data sets.
   *
   * \returns s/(tau + t)^kappa.
   */
  double compute_rho(size_t t, size_t s = 10, size_t tau=1000, double kappa = .9) {
    return (double) s / std::pow(tau + t, kappa);
  }

};
}
}
#endif


//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_CONSTANT_NAN_HPP_INCLUDED
#define BOOST_SIMD_CONSTANT_NAN_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{
  /*!
    @ingroup group-constant

    Generate the Not a Number (Nan) constant.

    @par Semantic

    For any type @c T,

    @code
    T x = Nan<T>();
    @endcode

    return the Nan representation for this type, i.e QuietNan for IEEE reals and
    0 for integers.

    @return The Nan constant for the proper type
  **/
  template<typename T> T Nan();

  namespace functional
  {
    /*!
      @ingroup group-callable-constant
      Generate the Not a Number (Nan) constant.

      @par Semantic

      For any type @c T,

      @code
      T x = nan(as(T{}));
      @endcode

      return the Nan representation for this type, i.e QuietNan for IEEE reals and
      0 for integers.

      @return The Nan constant for the proper type
    **/
    Value Nan();
  }
} }
#endif

#include <boost/simd/constant/definition/nan.hpp>
#include <boost/simd/arch/common/scalar/constant/constant_value.hpp>
#include <boost/simd/arch/common/simd/constant/constant_value.hpp>

#endif


/* CirKit: A circuit toolkit
 * Copyright (C) 2009-2015  University of Bremen
 * Copyright (C) 2015-2017  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "npn_canonization.hpp"

#include <iostream>
#include <strings.h>

#include <boost/graph/adjacency_list.hpp>
#include <boost/math/special_functions/factorials.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm_ext/iota.hpp>

#include <core/utils/range_utils.hpp>
#include <core/utils/timer.hpp>
#include <classical/abc/abc_api.hpp>

#include <misc/util/utilTruth.h>
#include <bool/lucky/lucky.h>

namespace cirkit
{

/******************************************************************************
 * Types                                                                      *
 ******************************************************************************/

/******************************************************************************
 * Private functions                                                          *
 ******************************************************************************/

std::vector<unsigned> compute_swaps( unsigned n )
{
  const unsigned N = static_cast<unsigned>( boost::math::factorial<double>( n ) );
  std::vector<unsigned> swap_array( N - 1u );
  auto d = N / 2u;
  swap_array[d - 1u] = 0u;
  auto m = 2u;
  unsigned j, k;

  while ( m != n )
  {
    ++m;
    d /= m;
    k = 0;

    do
    {
      k += d;
      j = m - 1u;
      while ( j > 0u )
      {
        swap_array[k - 1u] = --j;
        k += d;
      }
      swap_array[k - 1u]++;
      k += d;
      while ( j < m - 1u )
      {
        swap_array[k - 1u] = j++;
        k += d;
      }
    } while ( k < N );
  }

  return swap_array;
}

std::vector<unsigned> compute_flips( unsigned n )
{
  const auto total_flips = ( 1u << n ) - 1;
  std::vector<unsigned> flip_array( total_flips );

  auto graynumber = 0u;
  auto temp = 0u;
  for ( auto i = 1u; i <= total_flips; ++i )
  {
    graynumber = i ^ (i >> 1);
    flip_array[total_flips - i] = ffs( temp ^ graynumber ) - 1u;
    temp = graynumber;
  }

  return flip_array;
}

inline void bitset_swap( boost::dynamic_bitset<>& bs, unsigned i, unsigned j )
{
  auto t = bs[i];
  bs[i] = bs[j];
  bs[j] = t;
}

void npn_canonization_sifting_loop( tt& npn, unsigned n, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm )
{
  auto improvement = true;
  auto forward = true;

  //auto round = 0u;

  while ( improvement )
  {
    //std::cout << "[i] round " << ++round << std::endl;

    improvement = false;

    for ( int i = forward ? 0 : n - 2; forward ? i < static_cast<int>( n - 1 ) : i >= 0; forward ? ++i : --i )
    {
      auto local_improvement = false;
      for ( auto k = 1u; k < 8u; ++k )
      {
        if ( k % 4u == 0u )
        {
          const auto next_t = tt_permute( npn, i, i + 1 );
          if ( next_t < npn )
          {
            npn = next_t;
            std::swap( perm[i], perm[i + 1] );
            local_improvement = true;
          }
        }
        else if ( k % 2u == 0u )
        {
          const auto next_t = tt_flip( npn, i + 1 );
          if ( next_t < npn )
          {
            npn = next_t;
            phase.flip( i + 1 );
            local_improvement = true;
          }
        }
        else
        {
          const auto next_t = tt_flip( npn, i );
          if ( next_t < npn )
          {
            npn = next_t;
            phase.flip( i );
            local_improvement = true;
          }
        }
      }

      if ( local_improvement )
      {
        improvement = true;
      }
      else
      {
        std::swap( perm[i], perm[i + 1] );
      }
    }

    forward = !forward;
  }
}

/******************************************************************************
 * Public functions                                                           *
 ******************************************************************************/

tt exact_npn_canonization( const tt& t, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm, const properties::ptr& settings, const properties::ptr& statistics )
{
  properties_timer tim( statistics );

  /* initialize */
  auto n = tt_num_vars( t );
  phase.resize( n + 1u );
  phase.reset();
  perm.resize( n );
  boost::iota( perm, 0u );

  assert( n <= 6u );

  const auto& swap_array = tt_store::i().swaps( n );
  const auto& flip_array = tt_store::i().flips( n );
  const auto total_swaps = swap_array.size();
  const auto total_flips = flip_array.size();

  auto t1 = t;
  auto t2 = ~t; /* inversion */
  auto min = std::min( t1, t2 );

  auto invo = ( min == t2 );

  if ( false /* verbose */ )
  {
    std::cout << "[i] swaps: " << any_join( swap_array, " " ) << std::endl
              << "[i] flips: " << any_join( flip_array, " " ) << std::endl;
  }

  int best_flip = total_flips;
  int best_swap = total_swaps;

  for ( int i = total_swaps - 1; i >= 0; --i )
  {
    const auto pos = swap_array[i];
    t1 = tt_permute( t1, pos, pos + 1 );
    t2 = tt_permute( t2, pos, pos + 1 );
    tt_shrink( t1, n ); tt_shrink( t2, n );
    if ( t1 < min || t2 < min )
    {
      best_swap = i;
      min = std::min( std::min( t1, t2 ), min );
      invo = ( min == t2 );
    }
  }

  for ( int j = total_flips - 1; j >= 0; --j )
  {
    t1 = tt_flip( tt_permute( t1, 0u, 1u ), flip_array[j] );
    t2 = tt_flip( tt_permute( t2, 0u, 1u ), flip_array[j] );
    tt_shrink( t1, n ); tt_shrink( t2, n );
    if ( t1 < min || t2 < min )
    {
      best_swap = total_swaps;
      best_flip = j;
      min = std::min( std::min( t1, t2 ), min );
      invo = ( min == t2 );
    }

    for ( int i = total_swaps - 1; i >= 0; --i )
    {
      const auto pos = swap_array[i];
      t1 = tt_permute( t1, pos, pos + 1 );
      t2 = tt_permute( t2, pos, pos + 1 );
      tt_shrink( t1, n ); tt_shrink( t2, n );
      if ( t1 < min || t2 < min )
      {
        best_swap = i;
        best_flip = j;
        min = std::min( std::min( t1, t2 ), min );
        invo = ( min == t2 );
      }
    }
  }

  for ( int i = total_swaps - 1; i >= best_swap; --i )
  {
    const auto pos = swap_array[i];
    std::swap( perm[pos], perm[pos + 1] );
  }

  for ( int j = total_flips - 1; j >= best_flip; --j )
  {
    phase.flip( flip_array[j] );
  }

  /* output inverted? */
  if ( invo )
  {
    phase.flip( n );
  }

  return min;
}

tt npn_canonization( const tt& t, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm, const properties::ptr& settings, const properties::ptr& statistics )
{
  properties_timer tim( statistics );

  typedef tt::size_type size_type;

  /* initialize */
  auto n = tt_num_vars( t );
  phase.resize( n + 1u );
  phase.reset();
  perm.resize( n );
  boost::iota( perm, 0u );

  tt npn = t;

  auto old_count = npn.size() + 1u;

  while ( old_count != npn.count() )
  {
    old_count = npn.count();

    /* output negation */
    if ( npn.count() > ( npn.size() >> (size_type)1 ) )
    {
      phase.flip( n );
      npn.flip();
    }

    /* input negation */
    for ( unsigned i = 0u; i < n; ++i )
    {
      if ( tt_cof1( npn, i ).count() > tt_cof0( npn, i ).count() )
      {
        phase.flip( i );
        npn = tt_flip( npn, i );
      }
    }

    /* permute inputs */
    for ( unsigned d = 1u; d < n - 1; ++d )
    {
      for ( unsigned i = 0u; i < n - d; ++i )
      {
        unsigned j = i + d;

        if ( tt_cof1( npn, i ).count() > tt_cof1( npn, j ).count() )
        {
          npn = tt_permute( npn, i, j );
          std::swap( perm[i], perm[j] );
        }
      }
    }
  }

  if ( tt_num_vars( npn ) > n )
  {
    tt_shrink( npn, n );
  }

  return npn;
}

tt npn_canonization_flip_swap( const tt& t, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm, const properties::ptr& settings, const properties::ptr& statistics )
{
  properties_timer tim( statistics );

  /* initialize */
  auto n = tt_num_vars( t );
  phase.resize( n + 1u );
  phase.reset();
  perm.resize( n );
  boost::iota( perm, 0u );

  tt npn = t;

  auto improvement = true;

  //auto round = 0u;

  while ( improvement )
  {
    //std::cout << "[i] round " << ++round << std::endl;

    improvement = false;

    /* input inversion */
    for ( auto i = 0u; i < n; ++i )
    {
      const auto flipped = tt_flip( npn, i );
      if ( flipped < npn )
      {
        //std::cout << "[i]   flip input " << i << std::endl;
        npn = flipped;
        phase.flip( i );
        improvement = true;
      }
    }

    /* output inversion */
    const auto flipped = ~npn;
    if ( flipped < npn )
    {
      //std::cout << "[i]   flip output" << std::endl;
      npn = flipped;
      phase.flip( n );
      improvement = true;
    }

    /* permute inputs */
    for ( auto d = 1u; d < n - 1; ++d )
    {
      for ( auto i = 0u; i < n - d; ++i )
      {
        auto j = i + d;

        const auto permuted = tt_permute( npn, i, j );
        if ( permuted < npn )
        {
          //std::cout << "[i]   swap inputs " << i << " and " << j << std::endl;
          npn = permuted;
          std::swap( perm[i], perm[j] );
          bitset_swap( phase, i, j );
          improvement = true;
        }
      }
    }
  }

  if ( tt_num_vars( npn ) > n )
  {
    tt_shrink( npn, n );
  }

  return npn;
}

tt npn_canonization_sifting( const tt& t, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm, const properties::ptr& settings, const properties::ptr& statistics )
{
  properties_timer tim( statistics );

  /* initialize */
  auto n = tt_num_vars( t );
  phase.resize( n + 1u );
  phase.reset();
  perm.resize( n );
  boost::iota( perm, 0u );

  tt npn = t;

  if ( n < 2u )
  {
    return npn;
  }

  npn_canonization_sifting_loop( npn, n, phase, perm );

  const auto best_perm = perm;
  const auto best_phase = phase;
  const auto best_npn = npn;

  npn = ~t;
  phase.reset();
  phase.flip( n );
  boost::iota( perm, 0u );

  npn_canonization_sifting_loop( npn, n, phase, perm );

  if ( best_npn < npn )
  {
    perm = best_perm;
    phase = best_phase;
    npn = best_npn;
  }

  if ( tt_num_vars( npn ) > n )
  {
    tt_shrink( npn, n );
  }

  return npn;
}

tt tt_from_npn( const tt& npn, const boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm )
{
  tt t = npn;

  /* permute inputs */
  for ( unsigned i = 0; i < perm.size(); ++i )
  {
    if ( perm[i] == i ) continue;

    unsigned pos = boost::find( perm, i ) - perm.begin();
    t = tt_permute( t, i, pos );
    std::swap( perm[i], perm[pos] );
  }

  /* invert inputs */
  for ( unsigned i = 0; i < perm.size(); ++i )
  {
    if ( phase.test( i ) )
    {
      t = tt_flip( t, i );
    }
  }

  /* invert output */
  if ( phase.test( perm.size() ) )
  {
    t.flip();
  }

  if ( tt_num_vars( t ) > perm.size() )
  {
    tt_shrink( t, perm.size() );
  }

  return t;
}

tt npn_canonization_lucky( const tt& t, boost::dynamic_bitset<>& phase, std::vector<unsigned>& perm )
{
  std::vector<unsigned long> truth( t.num_blocks() );
  boost::to_block_range( t, &truth[0] );

  const auto num_vars = tt_num_vars( t );

  char pCanonPerm[16];
  abc::resetPCanonPermArray( pCanonPerm, num_vars );
  auto uCanonPhase = abc::luckyCanonicizer_final_fast( &truth[0], num_vars, pCanonPerm );

  boost::dynamic_bitset<> phase_direct( num_vars + 1, uCanonPhase );
  phase = phase_direct;

  perm.resize( num_vars );
  for ( auto i = 0u; i < num_vars; ++i )
  {
    perm[i] = pCanonPerm[i] - 'a';

    if ( perm[i] >= num_vars )
    {
      std::cout << "[e] problem with canonization" << std::endl;
      std::cout << "[e] pCanonPerm:";
      for ( auto i = 0u; i < num_vars; ++i )
      {
        std::cout << " " << pCanonPerm[i];
      }
      std::cout << std::endl;
      std::cout << "[e] truth table: " << t << std::endl;
      std::cout << "[e] tt num vars: " << tt_num_vars( t ) << std::endl;
      assert( false );
    }
    phase[perm[i]] = phase_direct[i];
  }

  return tt( truth.begin(), truth.end() );
}

}

// Local Variables:
// c-basic-offset: 2
// eval: (c-set-offset 'substatement-open 0)
// eval: (c-set-offset 'innamespace 0)
// End:


#ifndef SKYLARK_RFUT_ELEMENTAL_HPP
#define SKYLARK_RFUT_ELEMENTAL_HPP

#include <boost/mpi.hpp>
#include "../utility/randgen.hpp"

namespace skylark { namespace sketch {

/**
 * Specialization for [*, SOMETHING]
 */
template < typename ValueType,
           typename FUT,
           elem::Distribution RowDist,
           typename ValueDistributionType>
struct RFUT_t<
    elem::DistMatrix<ValueType, elem::STAR, RowDist>,
    FUT,
    ValueDistributionType> :
        public RFUT_data_t<ValueDistributionType> {
    // Typedef value, matrix, distribution and transform data types
    // so that we can use them regularly and consistently.
    typedef ValueType value_type;
    typedef elem::Matrix<ValueType> local_type;
    typedef elem::DistMatrix<ValueType, elem::STAR, RowDist> matrix_type;
    typedef elem::DistMatrix<ValueType,
                             elem::STAR, RowDist> output_matrix_type;
    typedef ValueDistributionType value_distribution_type;
    typedef RFUT_data_t<ValueDistributionType> data_type;

    /**
     * Regular constructor
     */
    RFUT_t(int N, base::context_t& context)
        : data_type (N, context) {

    }

    /**
     * Copy constructor
     */
    RFUT_t (RFUT_t<matrix_type,
                   FUT,
                   value_distribution_type>& other) :
        data_type(other) {}

    /**
     * Constructor from data
     */
    RFUT_t(const data_type& other_data) :
        data_type(other_data) {}

    /**
     * Apply the transform that is described in by the mixed_A.
     * mixed_A can be the same as A.
     */
    template <typename Dimension>
    void apply (const matrix_type& A,
        output_matrix_type& mixed_A,
        Dimension dimension) const {
        switch (RowDist) {
        case elem::VC:
        case elem::VR:
            try {
                apply_impl_vdist(A, mixed_A, dimension);
            } catch (std::logic_error e) {
                SKYLARK_THROW_EXCEPTION (
                    base::elemental_exception()
                        << base::error_msg(e.what()) );
            } catch(boost::mpi::exception e) {
                SKYLARK_THROW_EXCEPTION (
                     base::mpi_exception()
                         << base::error_msg(e.what()) );
                }
            break;

        default:
            SKYLARK_THROW_EXCEPTION (
                base::unsupported_matrix_distribution() );
        }
    }

private:
    /**
     * Apply the transform to compute mixed_A.
     * Implementation for the application on the columns.
     */
    void apply_impl_vdist (const matrix_type& A,
                           output_matrix_type& mixed_A,
                           skylark::sketch::columnwise_tag) const {
        // TODO verify that A has the correct size

        // TODO no need to create FUT everytime...
        FUT T(data_type::_N);

        // Scale
        const local_type& local_A = A.LockedMatrix();
        local_type& local_TA = mixed_A.Matrix();
        value_type scale = T.scale();
        for (int j = 0; j < local_A.Width(); j++)
            for (int i = 0; i < data_type::_N; i++)
                local_TA.Set(i, j,
                    scale * data_type::D[i] * local_A.Get(i, j));

        // Apply underlying transform
        T.apply(local_TA, skylark::sketch::columnwise_tag());
    }

};

/**
 * Specialization for [SOMETHING, *]
 */
template < typename ValueType,
           typename FUT,
           elem::Distribution RowDist,
           typename ValueDistributionType>
struct RFUT_t<
    elem::DistMatrix<ValueType, RowDist, elem::STAR>,
    FUT,
    ValueDistributionType> :
        public RFUT_data_t<ValueDistributionType> {
    // Typedef value, matrix, distribution and transform data types
    // so that we can use them regularly and consistently.
    typedef ValueType value_type;
    typedef elem::Matrix<ValueType> local_type;
    typedef elem::DistMatrix<ValueType, RowDist, elem::STAR> matrix_type;
    typedef elem::DistMatrix<ValueType, RowDist, elem::STAR> output_matrix_type;
    typedef elem::DistMatrix<ValueType, elem::STAR, RowDist> intermediate_type;
    /**< Intermediate type for columnwise applications */
    typedef ValueDistributionType value_distribution_type;
    typedef RFUT_data_t<ValueDistributionType> data_type;

    /**
     * Regular constructor
     */
    RFUT_t(int N, base::context_t& context)
        : data_type (N, context) {

    }

    /**
     * Copy constructor
     */
    RFUT_t (RFUT_t<matrix_type,
                   FUT,
                   value_distribution_type>& other) :
        data_type(other) {}

    /**
     * Constructor from data
     */
    RFUT_t(const data_type& other_data) :
           data_type(other_data) {}

    /**
     * Apply the transform that is described in by the mixed_A.
     */
    template <typename Dimension>
    void apply(const matrix_type& A,
               output_matrix_type& mixed_A,
               Dimension dimension) const {

        switch (RowDist) {
            case elem::VC:
            case elem::VR:
                try {
                    apply_impl_vdist(A, mixed_A, dimension);
                } catch (std::logic_error e) {
                    SKYLARK_THROW_EXCEPTION (
                        base::elemental_exception()
                            << base::error_msg(e.what()) );
                } catch(boost::mpi::exception e) {
                    SKYLARK_THROW_EXCEPTION (
                        base::mpi_exception()
                            << base::error_msg(e.what()) );
                }

                break;

            default:
                SKYLARK_THROW_EXCEPTION (
                    base::unsupported_matrix_distribution() );

        }
    }

    template <typename Dimension>
    void apply_inverse(const matrix_type& A,
                       output_matrix_type& mixed_A,
                       Dimension dimension) const {

        switch (RowDist) {
            case elem::VC:
            case elem::VR:
                try {
                    apply_inverse_impl_vdist(A, mixed_A, dimension);
                } catch (std::logic_error e) {
                    SKYLARK_THROW_EXCEPTION (
                        base::elemental_exception()
                            << base::error_msg(e.what()) );
                } catch(boost::mpi::exception e) {
                    SKYLARK_THROW_EXCEPTION (
                        base::mpi_exception()
                            << base::error_msg(e.what()) );
                }

                break;

        default:
            SKYLARK_THROW_EXCEPTION (
                base::unsupported_matrix_distribution() );

        }
    }

private:
    /**
     * Apply the transform to compute mixed_A.
     * Implementation for the application on the rows.
     */
    void apply_impl_vdist (const matrix_type& A,
                           output_matrix_type& mixed_A,
                           skylark::sketch::rowwise_tag) const {
        // TODO verify that A has the correct size

        FUT T(data_type::_N);

        // Scale
        const local_type& local_A = A.LockedMatrix();
        local_type& local_TA = mixed_A.Matrix();
        value_type scale = T.scale(local_A);
        for (int j = 0; j < data_type::_N; j++)
            for (int i = 0; i < local_A.Height(); i++)
                local_TA.Set(i, j,
                    scale * data_type::D[j] * local_A.Get(i, j));

        // Apply underlying transform
        T.apply(local_TA, skylark::sketch::rowwise_tag());
    }

    /**
     * Apply the transform to compute mixed_A.
     * Implementation for the application on the columns.
     */
    void apply_impl_vdist (const matrix_type& A,
                           output_matrix_type& mixed_A,
                           skylark::sketch::columnwise_tag) const {
        // TODO verify that A has the correct size
        // TODO A and mixed_A have to match

        FUT T(data_type::_N);

        // Rearrange matrix
        intermediate_type inter_A(A.Grid());
        inter_A = A;

        // Scale
        local_type& local_A = inter_A.Matrix();
        value_type scale = T.scale(local_A);
        for (int j = 0; j < local_A.Width(); j++)
            for (int i = 0; i < data_type::_N; i++)
                local_A.Set(i, j,
                    scale * data_type::D[i] * local_A.Get(i, j));

        // Apply underlying transform
        T.apply(local_A, skylark::sketch::columnwise_tag());

        // Rearrange back
        mixed_A = inter_A;
    }

    /**
     * Apply the transform to compute mixed_A.
     * Implementation for the application on the columns.
     */
    void apply_inverse_impl_vdist  (const matrix_type& A,
                                    output_matrix_type& mixed_A,
                                    skylark::sketch::columnwise_tag) const {

        FUT T(data_type::_N);

        // TODO verify that A has the correct size
        // TODO A and mixed_A have to match

        // Rearrange matrix
        intermediate_type inter_A(A.Grid());
        inter_A = A;

        // Apply underlying transform
        local_type& local_A = inter_A.Matrix();
        T.apply_inverse(local_A, skylark::sketch::columnwise_tag());

        // Scale
        value_type scale = T.scale(local_A);
        for (int j = 0; j < local_A.Width(); j++)
            for (int i = 0; i < data_type::_N; i++)
                local_A.Set(i, j,
                    scale * data_type::D[i] * local_A.Get(i, j));

        // Rearrange back
        mixed_A = inter_A;
    }

};

} } /** namespace skylark::sketch */

#endif // SKYLARK_RFUT_HPP


#include <iostream>
#include <armadillo>
#include "InputGenerator.h"
#include <cmath>

int main(int argc, char **argv)
{
    int n_times = 252;
    double dt = 1. / (250 - 1);

    double beta = 1;
    double t_max = 1;
    int real_grid_size = 250;
    int imag_grid_size = 250;

    assert((n_times - 1) * dt >= t_max);

    int n_flavor = 2;

    std::string name = "input/test";

    int n_bath = 1;

    double U = 3;
    double eps_0 = 1;
    double eps = -1;
    double eps_bath = 0;
    double V = 1; //std::sqrt(2 * 1 / (PI * n_bath) * 1);

    auto time_dependent_eps_bath = std::vector<double>(n_times, eps_bath);
    auto time_dependent_V = std::vector<cx_double>(n_times, cx_double(V, 0));
    auto time_dependent_eps = std::vector<double>(n_times, eps);
    time_dependent_eps[0] = eps_0;
    auto time_dependent_U = std::vector<double>(n_times, U);

    vec_re_3_t bath_energies;
    vec_3_t hybridizations;
    for(int n = 0; n < n_bath; ++n){
        bath_energies.emplace_back(vec_re_2_t(n_flavor, time_dependent_eps_bath));
        hybridizations.emplace_back(vec_2_t(n_flavor, time_dependent_V));
    }
    vec_re_2_t local_energies(n_flavor, time_dependent_eps);
    vec_re_1_t Hubbard_U(time_dependent_U);

    assert(bath_energies.size() == n_bath);
    assert(hybridizations.size() == n_bath);
    assert(bath_energies[0].size() == n_flavor);
    assert(hybridizations[0].size() == n_flavor);
    assert(local_energies.size() == n_flavor);
    assert(bath_energies[0][0].size() == n_times);
    assert(hybridizations[0][0].size() == n_times);
    assert(local_energies[0].size() == n_times);
    assert(Hubbard_U.size() == n_times);

    UserInput user_input = {
        bath_energies,       // vector in k-space of vectors in flavor space of vectors representing time dependence of bath energies
        hybridizations,      // vector in k-space of vectors in flavor space of vectors representing time dependence of hybridizations
        local_energies,      // vector in flavor space of vectors representing time dependence of local energies
        Hubbard_U,           // vector representing time dependence of Hubbard U
        dt,                  // time resolution of USER input data, data[i] = data(t=i*dt), applies to ALL vectors above
        n_times,             // number of time points in USER input data, applies to ALL vectors above
        beta,                // temperature^{-1}
        t_max,               // maximal time on the real axis
        real_grid_size,      // desired number of real time points in the GENERATED input (i.e. output of this code)
        imag_grid_size,      // desired number of imaginary time points in the GENERATED input (i.e. output of this code)
        name                 // user-defined name of the parameter set, will be used for naming the output
    };

    InputGenerator input_generator = {user_input};

    input_generator.generate_all_for_determinant();
    input_generator.generate_all_for_one_spin();
    input_generator.generate_benchmark_data();
}


#ifndef CONNECT_FOUR_GRAPH_HPP
#define CONNECT_FOUR_GRAPH_HPP

#include <boost/format.hpp>

struct Node;

// This is for sugar
// TODO, we using invariants (expliting symetric, inverse mappings,
// can add flags for inverses etc here, reduce node set by ~4

struct Edge{
        explicit Edge(char idx, Node* node)
                :idx_{idx}, node_{node}
        {}
        auto Idx()const { return idx_; }
        auto GetNode()const{ return node_; }
private:
        char idx_;
        Node* node_;
};

struct Node{
        explicit Node(GameContext ctx):ctx_{std::move(ctx)}{}
        auto const& Ctx()const{ return ctx_; }
        void AddEdge(char x, Node* n){
                edges_.emplace_back(x,n);
        }
        auto begin()const{ return edges_.begin(); }
        auto end()const{ return edges_.end(); }
        bool IsTerminal()const{ return edges_.size()==0; }
private:

        GameContext ctx_;
        std::vector< Edge > edges_;
};

struct GameTree{
        explicit GameTree(Node* start):start_{start}{}
        Node* GetStart(){ return start_; }
private:
        Node* start_;
};

/*
        Idea here is that I can create a subgraph for each
        board popcount
 */

GameTree GenerateGameTree(Board const& board = Board{}){
        ConnectFourLogic logic;
        std::map<decltype(std::declval<GameContext>().Hash()), Node*> nodes;

        auto start = new Node{GameContext{board}};
        std::vector<Node*> stack{start};

        nodes[start->Ctx().Hash()] = start;

        for(;stack.size();){
                auto ptr = stack.back();
                stack.pop_back();
                auto const& ctx{ptr->Ctx()};

                if( ptr->Ctx().GetCtrl() == Ctrl_Finish ){
                        //std::cout << "Finished\n";
                        //ptr->Ctx().Display();
                        continue;
                }

                if( PopCount( ptr->Ctx().GetBoard() ) == 20 )
                        continue;

                //ptr->Ctx().Display();

                // try to place a tile
                for( unsigned x=0;x!=ctx.BoardWidth();++x){
                        //if( ! CanPlace( ctx.GetBoard(), x) ){
                                //continue;
                        //}
                        //ctx.Display();
                        GameContext nextCtx{ctx};
                        nextCtx.Place(logic, x);

                        auto h = nextCtx.Hash();
                        auto iter = nodes.find(h);
                        if( iter == nodes.end()){
                                auto tmp = new Node{std::move(nextCtx)};
                                nodes.emplace(h, tmp);
                                stack.push_back(tmp);
                                iter = nodes.find(h);
                                //tmp->Ctx().Display();
                        }

                        ptr->AddEdge( x, iter->second);
                }
                if( nodes.size() % 10000 == 0 )
                        PRINT( nodes.size() );
        }

        PRINT( nodes.size() );
        PRINT( stack.size() );

        return GameTree{start};
}

enum Marking{
        Marked_Zero = 0,
        Marked_Win  = 1,
        Marked_Lose = 2,
        Marked_Draw = 4,
};

struct NodeMarker{

        void Run(GameTree& root){
                ConnectFourLogic logic;
                std::vector< Node const* > ticker = { root.GetStart() };
                for( ; ticker.size(); ){
                        auto ptr = ticker.back();
                        ticker.pop_back();

                        if( ptr->IsTerminal()){
                                switch( ptr->Ctx().Evaluate(logic) ){
                                case Eval_NotFinished:
                                        //ptr->Ctx().Display();
                                        throw std::domain_error("bad game tree");
                                case Eval_Hero:
                                        marks_.emplace(ptr, Marked_Win);
                                        break;
                                case Eval_Villian:
                                        marks_.emplace(ptr, Marked_Lose);
                                        break;
                                case Eval_Draw:
                                        marks_.emplace(ptr, Marked_Draw);
                                        break;
                                }
                                continue;
                        }

                        // Go thought all edges, if there are any unmarked,
                        // enqueue marking, and enqueue node for later processing
                        bool process = true;
                        for( auto const& edge : *ptr ){
                                if( marks_.count(edge.GetNode()) == 0 ){
                                        if( process == true ){
                                                // reque myself
                                                ticker.emplace_back( ptr );
                                                process = false;
                                        }
                                        ticker.emplace_back( edge.GetNode() );
                                }
                        }
                        if( ! process ){
                                continue;
                        }
                        if( ptr->Ctx().ActivePlayer() == Player_Villian ){
                                int mark = 0;
                                for( auto const& edge : *ptr ){
                                        mark |= marks_[edge.GetNode()];
                                }
                                marks_[ptr] = mark;
                                continue;
                        }

                        std::vector<int> aux;
                        for( auto const& edge : *ptr ){
                                aux.emplace_back( marks_[edge.GetNode()] );
                        }
                        std::sort( aux.begin(), aux.end(), [&](auto left, auto right){
                                static std::map<int, int> order = [](){
                                        int precedence[] = {
                                                Marked_Win,
                                                Marked_Win  | Marked_Draw,
                                                Marked_Draw,
                                                Marked_Win  | Marked_Draw | Marked_Lose,
                                                Marked_Win  | Marked_Lose,
                                                Marked_Draw | Marked_Lose,
                                                Marked_Lose,
                                        };
                                        std::map<int, int> ret;
                                        int index = 0;
                                        for( auto mark : precedence ){
                                                ret.emplace(mark, index++);
                                        }
                                        return std::move(ret);
                                }();
                                return order[left] < order[right];
                        });
                        marks_[ptr] = aux.front();

                }

                PRINT(marks_.size());
        }
        auto Lookup(Node const* ptr)const{
                return marks_.find(ptr)->second;
        }
private:
        std::map<Node const*, int > marks_;
};

struct Profiler{
        void Run(GameTree& root){
                std::map<Node const*, int > marked;
                std::vector< Node const* > ticker = { root.GetStart() };
                std::map<std::string, unsigned> profile_;
                for( ; ticker.size(); ){
                        auto ptr = ticker.back();
                        ticker.pop_back();
                        for( auto const& edge : *ptr ){
                                if( marked.count(edge.GetNode()) == 0 ){
                                        ticker.emplace_back( edge.GetNode() );
                                }
                        }

                        if( marked.count(ptr) != 0 )
                                continue;
                        marked.emplace(ptr, 1);

                        std::map<Tile, int> hist;
                        hist[Tile_Empty];
                        hist[Tile_Hero];
                        hist[Tile_Villian];
                        auto const& board = ptr->Ctx().GetBoard();
                        for(size_t x=0;x!=ptr->Ctx().BoardWidth();++x){

                                for(size_t y=0;y!=ptr->Ctx().BoardHeight();++y){
                                        ++hist[board.Get(x,y)];
                                }
                        }
                        std::stringstream sstr;
                        sstr << "{";
                        bool first = true;
                        for(auto const& p : hist ){
                                sstr << ( first ? (first=false, "") : ", ");
                                sstr << TileToMetaString(p.first) << ":" << p.second;
                        }
                        sstr << "}";
                        ++profile_[sstr.str()];
                        if( marked.size() % 10000 == 0 )
                                PRINT(marked.size());
                }
                for( auto const& p : profile_ ){
                        std::cout << boost::format("%-8s => %s")
                                % p.second % p.first << "\n";
                }
        }
};
#endif // CONNECT_FOUR_GRAPH_HPP


#include <CGAL/basic.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Lazy_exact_nt.h>
#ifdef CGAL_USE_GMP
#include <CGAL/Gmpq.h>
#include <CGAL/Gmpz.h>
#include <CGAL/Gmpzf.h>
#include <CGAL/Gmpfr.h>
#endif
#ifdef CGAL_USE_MPFI
#include <CGAL/Gmpfi.h>
#endif
#ifdef CGAL_USE_CORE
#include <CGAL/CORE_BigInt.h>
#include <CGAL/CORE_BigRat.h>
#include <CGAL/CORE_BigFloat.h>
#include <CGAL/CORE_Expr.h>
#endif
#include <CGAL/MP_Float.h>
#include <CGAL/Quotient.h>
#include <CGAL/Sqrt_extension.h>
#include <CGAL/Testsuite/use.h>

#ifdef CGAL_EIGEN3_ENABLED
#include <Eigen/Dense>

// Just check that it all compiles.
template <class NT, int s>
void check_(){
  Eigen::Matrix<NT,s,s> m(3,3);
  m << 1, 2, 3, 4, 5, 6, 7, 8, 10;
  NT d=(m+m).determinant();
  Eigen::Matrix<NT,s,1> v(3);
  v << 1, 2, 3;
  NT t=v.dot(v);
  v+=d*m*(t*v);
  int si=v.size();
  CGAL_USE(si);
}
template <class NT>
void check(){
  check_<NT,3>();
  check_<NT,Eigen::Dynamic>();
}

int main(){
  {
    typedef CGAL::Interval_nt<true> I1;
    I1::Protector p1;
    check<I1>();
  }
  {
    typedef CGAL::Interval_nt<false> I2;
    I2::Protector p2;
    check<I2>();
  }
  //check<CGAL::MP_Float>();
  //check<CGAL::Quotient<CGAL::MP_Float> >();
  //check<CGAL::Lazy_exact_nt<CGAL::Quotient<CGAL::MP_Float> > >();
  check<CGAL::Sqrt_extension<double,double> >();
#ifdef CGAL_USE_GMP
  check<CGAL::Gmpz>();
  check<CGAL::Gmpq>();
  check<CGAL::Gmpfr>();
  check<CGAL::Quotient<CGAL::Gmpz> >();
  check<CGAL::Lazy_exact_nt<CGAL::Gmpq> >();
#endif
#ifdef CGAL_USE_MPFI
  check<CGAL::Gmpfi>();
#endif
#ifdef CGAL_USE_CORE
  check<CORE::BigInt>();
  check<CORE::BigRat>();
  check<CORE::BigFloat>();
  check<CORE::Expr>();
#endif
}

#else
#include <iostream>
int main(){
  std::cerr << "Eigen is not configured!\n";
}
#endif


#include <boost/multiprecision/random.hpp>


#include <iostream>                    // std::flush
#include <fstream>                     // std::ofstream
#include <string>                      // std::string
#include <tuple>                       // std::tuple
#include <vector>                      // std::vector
#include <cmath>                       // std::isinf
// For External Library
#include <torch/torch.h>               // torch
#include <boost/program_options.hpp>   // boost::program_options
// For Original Header
#include "loss.hpp"                    // Loss
#include "networks.hpp"                // Encoder, Decoder, EstimationNetwork, RelativeEuclideanDistance, CosineSimilarity
#include "dataloader.hpp"              // DataLoader::ImageFolderWithPaths
#include "visualizer.hpp"              // visualizer::graph

// Define Namespace
namespace po = boost::program_options;

// -------------------
// Validation Function
// -------------------
void valid(po::variables_map &vm, DataLoader::ImageFolderWithPaths &valid_dataloader, torch::Device &device, Loss &criterion, Encoder &enc, Decoder &dec, EstimationNetwork &est, torch::Tensor mu, torch::Tensor sigma, torch::Tensor phi, const size_t epoch, visualizer::graph &writer, visualizer::graph &writer_rec){

    // (0) Initialization and Declaration
    size_t iteration;
    float ave_rec, total_rec;
    float ave_anomaly_score, total_anomaly_score, score;
    std::ofstream ofs;
    std::tuple<torch::Tensor, std::vector<std::string>> mini_batch;
    torch::Tensor image, output;
    torch::Tensor z, z_c, z_r, z_r1, z_r2;
    torch::Tensor rec, anomaly_score;

    // (1) Tensor Forward per Mini Batch
    enc->eval();
    dec->eval();
    est->eval();
    iteration = 0;
    total_rec = 0.0; total_anomaly_score = 0.0;
    while (valid_dataloader(mini_batch)){

        image = std::get<0>(mini_batch).to(device);

        // (1.1) Encoder-Decoder Forward
        z_c = enc->forward(image);   // {C,H,W} ===> {ZC,1,1}
        output = dec->forward(z_c);  // {ZC,1,1} ===> {C,H,W}

        // (1.2) Setting Latent Space
        z_c = z_c.view({z_c.size(0), z_c.size(1)});  // {ZC,1,1} ===> {ZC}
        if (vm["RED"].as<bool>()){
            z_r1 = RelativeEuclideanDistance(image, output);
        }
        else{
            z_r1 = AbsoluteEuclideanDistance(image, output);
        }
        z_r2 = CosineSimilarity(image, output);
        z_r = torch::cat({z_r1, z_r2}, /*dim=*/1);  // {1} + {1} ===> {ZR} = {2}
        z = torch::cat({z_c, z_r}, /*dim=*/1);  // {ZC} + {ZR} ===> {Z} = {ZC+ZR}

        // (1.3) Calculation of Loss
        rec = criterion(output, image);
        anomaly_score = est->anomaly_score(z, mu, sigma, phi);

        // (1.4) Update Loss
        total_rec += rec.item<float>();
        score = anomaly_score.item<float>();
        score = (std::isinf(score) ? (float)(long)score : score);
        total_anomaly_score += score;

        iteration++;
    }

    // (2) Calculate Average Loss
    ave_rec = total_rec / (float)iteration;
    ave_anomaly_score = total_anomaly_score / (float)iteration;

    // (3.1) Record Loss (Log)
    ofs.open("checkpoints/" + vm["dataset"].as<std::string>() + "/log/valid.txt", std::ios::app);
    ofs << "epoch:" << epoch << '/' << vm["epochs"].as<size_t>() << ' ' << std::flush;
    ofs << "rec:" << ave_rec << ' ' << std::flush;
    ofs << "anomaly_score:" << ave_anomaly_score << std::endl;
    ofs.close();

    // (3.2) Record Loss (Graph)
    writer.plot(/*base=*/epoch, /*value=*/{ave_rec + ave_anomaly_score, ave_rec, ave_anomaly_score});
    writer_rec.plot(/*base=*/epoch, /*value=*/{ave_rec});

    // End Processing
    return;

}


#include <boost/thread/lock_guard.hpp>
#include "time_postprocessor.h"
#include "api_config.h"

#include <cmath>

// === implementation of the time_postprocessor class ===

using namespace lsl;

/// Construct a new time post-processor.
time_postprocessor::time_postprocessor(const postproc_callback_t &query_correction, const postproc_callback_t &query_srate, const reset_callback_t &query_reset):
	samples_seen_(0.0), query_srate_(query_srate), options_(proc_none), halftime_(api_config::get_instance()->smoothing_halftime()),
    query_correction_(query_correction), query_reset_(query_reset), next_query_time_(0.0), last_offset_(0.0),
	smoothing_initialized_(false), last_value_(-std::numeric_limits<double>::infinity())
{
}

/// Post-process the given time-stamp and return the new time-stamp.

double time_postprocessor::process_timestamp(double value) {
	if (options_ & proc_threadsafe) {
		lslboost::lock_guard<lslboost::mutex> lock(processing_mut_);
		return process_internal(value);
	} else
		return process_internal(value);
}

double time_postprocessor::process_internal(double value) {
	// --- clock synchronization ---
	if (options_ & proc_clocksync) {
		// update last correction value if needed (we do this every 50 samples and at most twice per second)
		if ((fmod(samples_seen_,50.0) == 0.0) && lsl_clock() > next_query_time_) {
			last_offset_ = query_correction_();
			if (query_reset_()) {
				// reset state to unitialized
				last_offset_ = query_correction_();
				last_value_ = -std::numeric_limits<double>::infinity();
				samples_seen_ = 0;
				smoothing_initialized_ = false;
			}
			next_query_time_ = lsl_clock()+0.5;
		}
		// perform clock synchronization; this is done by adding the last-measured clock offset value
		// (typically this is used to map the value from the sender's clock to our local clock)
		value += last_offset_;
	}

	// --- jitter removal ---
	if (options_ & proc_dejitter) {
		// initialize the smoothing state if not yet done so
		if (!smoothing_initialized_) {
			double srate = query_srate_();
			smoothing_applicable_ = (srate > 0.0);
			if (smoothing_applicable_) {
				// linear regression model coefficients (intercept, slope)
				w0_ = 0.0;
				w1_ = 1.0/srate;
				// forget factor lambda in RLS calculation & its inverse
				lam_ = pow(2.0, -1.0/(srate*halftime_));
				il_ = 1.0/lam_;
				// inverse autocovariance matrix of predictors u
				P00_ = P11_ = 1e10; P01_ = P10_ = 0.0;
				// numeric baseline
				baseline_value_ = value;
			}
			smoothing_initialized_ = true;
		}
		if (smoothing_applicable_) {
			value -= baseline_value_;

			// RLS update
			double u1 = samples_seen_;				// u = np.matrix([[1.0], [samples_seen]])
			double pi0 = P00_ + u1*P10_;			// pi = u.T * P
			double pi1 = P01_ + u1*P11_;			// ... (ct'd)
			double al = value - w0_ - w1_ * u1;		// al = value - w.T * u (prediction error)
			double gam = lam_ + pi0 + pi1 * u1;		// gam = lam + pi * u
			P00_ = il_ * (P00_ - ((pi0*pi0)/gam));  // Pp = k * pi; P = il * (P - Pp)
			P01_ = il_ * (P01_ - ((pi0*pi1)/gam));	// ...
			P10_ = il_ * (P10_ - ((pi1*pi0)/gam));	// ...
			P11_ = il_ * (P11_ - ((pi1*pi1)/gam));	// ...
			w0_ += al * (P00_ + P10_ * u1);         // w = w + k*al
			w1_ += al * (P01_ + P11_ * u1);			// ...
			value = w0_ + w1_*u1;					// value = float(w.T * u)

			value += baseline_value_;
		}
	}

	// --- force monotonic timestamps ---
	if (options_ & proc_monotonize) {
		if (value < last_value_)
			value = last_value_;
	}

	samples_seen_ += 1.0;
	last_value_ = value;
	return value;
}


/*=============================================================================
    Copyright (c) 2002-2010 Hartmut Kaiser
    Copyright (c) 2002-2010 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
///////////////////////////////////////////////////////////////////////////////
//
//  This sample demonstrates a generator for a comma separated list of numbers.
//  No actions. It is based on the example qi/num_lists.cpp for reading in
//  some numbers to generate.
//
///////////////////////////////////////////////////////////////////////////////

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace client
{
    ///////////////////////////////////////////////////////////////////////////
    //  Our number list parser, please see the example qi/numlist1.cpp for
    //  more information
    ///////////////////////////////////////////////////////////////////////////
    template <typename Iterator>
    bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
    {
        using boost::spirit::qi::double_;
        using boost::spirit::qi::phrase_parse;
        using boost::spirit::ascii::space;

        bool r = phrase_parse(first, last, double_ % ',', space, v);
        if (first != last)
            return false;
        return r;
    }

    //[tutorial_karma_numlist3_complex
    // a simple complex number representation z = a + bi
    struct complex
    {
        complex (double a, double b = 0.0) : a(a), b(b) {}

        double a;
        double b;
    };

    // the streaming operator for the type complex
    std::ostream&
    operator<< (std::ostream& os, complex const& z)
    {
        os << "{" << z.a << "," << z.b << "}";
        return os;
    }
    //]

    ///////////////////////////////////////////////////////////////////////////
    //  Our number list generator
    ///////////////////////////////////////////////////////////////////////////
    //[tutorial_karma_numlist3
    template <typename OutputIterator, typename Container>
    bool generate_numbers(OutputIterator& sink, Container const& v)
    {
        using boost::spirit::karma::stream;
        using boost::spirit::karma::generate;
        using boost::spirit::karma::eol;

        bool r = generate(
            sink,                           // destination: output iterator
            stream % eol,                   // the generator
            v                               // the data to output
        );
        return r;
    }
    //]
}

////////////////////////////////////////////////////////////////////////////
//  Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
    std::cout << "/////////////////////////////////////////////////////////\n\n";
    std::cout << "\tA comma separated list generator for Spirit...\n\n";
    std::cout << "/////////////////////////////////////////////////////////\n\n";

    std::cout << "Give me a comma separated list of numbers.\n";
    std::cout << "Type [q or Q] to quit\n\n";

    std::string str;
    while (getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        std::vector<double> v;      // here we put the data gotten from input
        if (client::parse_numbers(str.begin(), str.end(), v))
        {
            // ok, we got some numbers, fill a vector of client::complex
            // instances and print them back out
            std::vector<client::complex> vc;
            std::vector<double>::const_iterator end = v.end();
            for (std::vector<double>::const_iterator it = v.begin();
                 it != end; ++it)
            {
                double real(*it);
                if (++it != end)
                    vc.push_back(client::complex(real, *it));
                else {
                    vc.push_back(client::complex(real));
                    break;
                }
            }

            std::cout << "-------------------------\n";

            std::string generated;
            std::back_insert_iterator<std::string> sink(generated);
            if (!client::generate_numbers(sink, vc))
            {
                std::cout << "-------------------------\n";
                std::cout << "Generating failed\n";
                std::cout << "-------------------------\n";
            }
            else
            {
                std::cout << "-------------------------\n";
                std::cout << "Generated:\n" << generated << "\n";
                std::cout << "-------------------------\n";
            }
        }
        else
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}


#include <iostream>
#include <boost/numeric/ublas/matrix.hpp>

typedef boost::numeric::ublas::matrix<float> Matrix44;

const Matrix44 &getWorldMatrix()
{
	Matrix44 matrix = boost::numeric::ublas::identity_matrix<float> (4);
	return matrix;
}

int main()
{
	const Matrix44 &matrix = getWorldMatrix();

	std::cout << matrix(0, 0) << std::endl;

	return 0;
}


#include <basix/e-lagrange.h>
#include <boost/program_options.hpp>
#include <cmath>
#include <dolfinx.h>
#include <dolfinx/io/XDMFFile.h>
#include <iostream>

#include <cuda_profiler_api.h>

// Helper functions
#include <cuda/allocator.hpp>
#include <cuda/array.hpp>
#include <cuda/la.hpp>
#include <cuda/scatter.hpp>
#include <cuda/utils.hpp>

using namespace dolfinx;
namespace po = boost::program_options;

void assert_cublas(cudaError_t e) {
  if (e != cudaSuccess)
    throw std::runtime_error(" Unable to allocate memoy - cublas error");
}

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

  po::options_description desc("Allowed options");
  desc.add_options()("help,h", "print usage message")(
      "size", po::value<std::size_t>()->default_value(32))(
      "degree", po::value<int>()->default_value(1));

  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(),
            vm);
  po::notify(vm);

  if (vm.count("help")) {
    std::cout << desc << "\n";
    return 0;
  }

  const std::size_t Nx = vm["size"].as<std::size_t>();
  const int degree = vm["degree"].as<int>();

  common::subsystem::init_logging(argc, argv);
  common::subsystem::init_mpi(argc, argv);
  {
    // MPI
    MPI_Comm mpi_comm{MPI_COMM_WORLD};
    int rank = utils::set_device(mpi_comm);

    // Read mesh and mesh tags
    std::array<std::array<double, 3>, 2> p = {{{0.0, 0.0, 0.0}, {1.0, 1.0, 1.0}}};
    std::array<std::size_t, 3> n = {Nx, Nx, Nx};
    auto mesh = std::make_shared<mesh::Mesh>(mesh::create_box(
        mpi_comm, p, n, mesh::CellType::hexahedron, mesh::GhostMode::none));

    // Create a Basix continuous Lagrange element of given degree
    basix::FiniteElement e = basix::element::create_lagrange(
        mesh::cell_type_to_basix_type(mesh::CellType::hexahedron), degree,
        basix::element::lagrange_variant::equispaced, true);

    // Create a scalar function space
    auto V = std::make_shared<fem::FunctionSpace>(fem::create_functionspace(mesh, e, 1));
    auto idxmap = V->dofmap()->index_map;

    // Assemble RHS vector
    CUDA::allocator<double> allocator{};
    la::Vector<double, decltype(allocator)> x(idxmap, 1, allocator);
    std::iota(x.mutable_array().begin(), x.mutable_array().end(), 0);

    int ncells = mesh->topology().index_map(3)->size_local();
    int ndofs = e.dim();

    std::int32_t Ne = ncells * ndofs;

    cuda::array<double> xe(Ne);
    cuda::array<std::int32_t> dofmap(Ne);
    const std::vector<std::int32_t>& dof_array = V->dofmap()->list().array();
    dofmap.set(dof_array);

    // prefetch data to gpu
    linalg::prefetch(rank, x);
    gather(Ne, dofmap.data(), x.array().data(), xe.data(), 512);

    auto h_xe = xe.copy_to_host();

    for (int i = 0; i < Ne; i++) {
      assert(h_xe[i] == double(dof_array[i]));
    }
  }

  common::subsystem::finalize_mpi();
  return 0;
}


/*
@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#include <boost/hana/assert.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/range.hpp>
using namespace boost::hana;

int main() {
    //////////////////////////////////////////////////////////////////////////
    // range_c
    //////////////////////////////////////////////////////////////////////////
    {
        using T = int;
        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 0, 0>,
            range(integral_constant<T, 0>, integral_constant<T, 0>)
        ));
        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 0, 1>,
            range(integral_constant<T, 0>, integral_constant<T, 1>)
        ));
        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 0, 2>,
            range(integral_constant<T, 0>, integral_constant<T, 2>)
        ));

        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 1, 1>,
            range(integral_constant<T, 1>, integral_constant<T, 1>)
        ));
        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 1, 2>,
            range(integral_constant<T, 1>, integral_constant<T, 2>)
        ));
        BOOST_HANA_CONSTANT_CHECK(equal(
            range_c<T, 1, 3>,
            range(integral_constant<T, 1>, integral_constant<T, 3>)
        ));
    }
}


///////////////////////////////////////////////////////////////////////////////
// peaks_over_threshold.hpp
//
//  Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006
#define BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006

#include <vector>
#include <limits>
#include <numeric>
#include <functional>
#include <boost/config/no_tr1/cmath.hpp> // pow
#include <sstream> // stringstream
#include <stdexcept> // runtime_error
#include <boost/throw_exception.hpp>
#include <boost/range.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/parameter/keyword.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/extractor.hpp>
#include <boost/accumulators/numeric/functional.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>
#include <boost/accumulators/framework/depends_on.hpp>
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
#include <boost/accumulators/statistics/count.hpp>
#include <boost/accumulators/statistics/tail.hpp>

#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
#endif

namespace boost { namespace accumulators
{

///////////////////////////////////////////////////////////////////////////////
// threshold_probability and threshold named parameters
//
BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_value, threshold_value)
BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_probability, threshold_probability)

BOOST_ACCUMULATORS_IGNORE_GLOBAL(pot_threshold_value)
BOOST_ACCUMULATORS_IGNORE_GLOBAL(pot_threshold_probability)

namespace impl
{
    ///////////////////////////////////////////////////////////////////////////////
    // peaks_over_threshold_impl
    //  works with an explicit threshold value and does not depend on order statistics
    /**
        @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation

        According to the theorem of Pickands-Balkema-de Haan, the distribution function \f$F_u(x)\f$ of
        the excesses \f$x\f$ over some sufficiently high threshold \f$u\f$ of a distribution function \f$F(x)\f$
        may be approximated by a generalized Pareto distribution
        \f[
            G_{\xi,\beta}(x) =
            \left\{
            \begin{array}{ll}
                \beta^{-1}\left(1+\frac{\xi x}{\beta}\right)^{-1/\xi-1} & \textrm{if }\xi\neq0\\
                \beta^{-1}\exp\left(-\frac{x}{\beta}\right) & \textrm{if }\xi=0,
            \end{array}
            \right.
        \f]
        with suitable parameters \f$\xi\f$ and \f$\beta\f$ that can be estimated, e.g., with the method of moments, cf.
        Hosking and Wallis (1987),
        \f[
            \begin{array}{lll}
            \hat{\xi} & = & \frac{1}{2}\left[1-\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}\right]\\
            \hat{\beta} & = & \frac{\hat{\mu}-u}{2}\left[\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}+1\right],
            \end{array}
        \f]
        \f$\hat{\mu}\f$ and \f$\hat{\sigma}^2\f$ being the empirical mean and variance of the samples over
        the threshold \f$u\f$. Equivalently, the distribution function
        \f$F_u(x-u)\f$ of the exceedances \f$x-u\f$ can be approximated by
        \f$G_{\xi,\beta}(x-u)=G_{\xi,\beta,u}(x)\f$. Since for \f$x\geq u\f$ the distribution function \f$F(x)\f$
        can be written as
        \f[
            F(x) = [1 - \P(X \leq u)]F_u(x - u) + \P(X \leq u)
        \f]
        and the probability \f$\P(X \leq u)\f$ can be approximated by the empirical distribution function
        \f$F_n(u)\f$ evaluated at \f$u\f$, an estimator of \f$F(x)\f$ is given by
        \f[
            \widehat{F}(x) = [1 - F_n(u)]G_{\xi,\beta,u}(x) + F_n(u).
        \f]
        It can be shown that \f$\widehat{F}(x)\f$ is a generalized
        Pareto distribution \f$G_{\xi,\bar{\beta},\bar{u}}(x)\f$ with \f$\bar{\beta}=\beta[1-F_n(u)]^{\xi}\f$
        and \f$\bar{u}=u-\bar{\beta}\left\{[1-F_n(u)]^{-\xi}-1\right\}/\xi\f$. By inverting \f$\widehat{F}(x)\f$,
        one obtains an estimator for the \f$\alpha\f$-quantile,
        \f[
            \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right],
        \f]
        and similarly an estimator for the (coherent) tail mean,
        \f[
            \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi},
        \f]
        cf. McNeil and Frey (2000).

        Note that in case extreme values of the left tail are fitted, the distribution is mirrored with respect to the
        \f$y\f$ axis such that the left tail can be treated as a right tail. The computed fit parameters thus define
        the Pareto distribution that fits the mirrored left tail. When quantities like a quantile or a tail mean are
        computed using the fit parameters obtained from the mirrored data, the result is mirrored back, yielding the
        correct result.

        For further details, see

        J. R. M. Hosking and J. R. Wallis, Parameter and quantile estimation for the generalized Pareto distribution,
        Technometrics, Volume 29, 1987, p. 339-349

        A. J. McNeil and R. Frey, Estimation of Tail-Related Risk Measures for Heteroscedastic Financial Time Series:
        an Extreme Value Approach, Journal of Empirical Finance, Volume 7, 2000, p. 271-300

        @param quantile_probability
        @param pot_threshold_value
    */
    template<typename Sample, typename LeftRight>
    struct peaks_over_threshold_impl
      : accumulator_base
    {
        typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
        // for boost::result_of
        typedef boost::tuple<float_type, float_type, float_type> result_type;
        // for left tail fitting, mirror the extreme values
        typedef mpl::int_<is_same<LeftRight, left>::value ? -1 : 1> sign;

        template<typename Args>
        peaks_over_threshold_impl(Args const &args)
          : Nu_(0)
          , mu_(sign::value * numeric::fdiv(args[sample | Sample()], (std::size_t)1))
          , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
          , threshold_(sign::value * args[pot_threshold_value])
          , fit_parameters_(boost::make_tuple(0., 0., 0.))
          , is_dirty_(true)
        {
        }

        template<typename Args>
        void operator ()(Args const &args)
        {
            this->is_dirty_ = true;

            if (sign::value * args[sample] > this->threshold_)
            {
                this->mu_ += args[sample];
                this->sigma2_ += args[sample] * args[sample];
                ++this->Nu_;
            }
        }

        template<typename Args>
        result_type result(Args const &args) const
        {
            if (this->is_dirty_)
            {
                this->is_dirty_ = false;

                std::size_t cnt = count(args);

                this->mu_ = sign::value * numeric::fdiv(this->mu_, this->Nu_);
                this->sigma2_ = numeric::fdiv(this->sigma2_, this->Nu_);
                this->sigma2_ -= this->mu_ * this->mu_;

                float_type threshold_probability = numeric::fdiv(cnt - this->Nu_, cnt);

                float_type tmp = numeric::fdiv(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_);
                float_type xi_hat = 0.5 * ( 1. - tmp );
                float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp );
                float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat);
                float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat;
                this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat);
            }

            return this->fit_parameters_;
        }

    private:
        std::size_t Nu_;                     // number of samples larger than threshold
        mutable float_type mu_;              // mean of Nu_ largest samples
        mutable float_type sigma2_;          // variance of Nu_ largest samples
        float_type threshold_;
        mutable result_type fit_parameters_; // boost::tuple that stores fit parameters
        mutable bool is_dirty_;
    };

    ///////////////////////////////////////////////////////////////////////////////
    // peaks_over_threshold_prob_impl
    //  determines threshold from a given threshold probability using order statistics
    /**
        @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation

        @sa peaks_over_threshold_impl

        @param quantile_probability
        @param pot_threshold_probability
    */
    template<typename Sample, typename LeftRight>
    struct peaks_over_threshold_prob_impl
      : accumulator_base
    {
        typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
        // for boost::result_of
        typedef boost::tuple<float_type, float_type, float_type> result_type;
        // for left tail fitting, mirror the extreme values
        typedef mpl::int_<is_same<LeftRight, left>::value ? -1 : 1> sign;

        template<typename Args>
        peaks_over_threshold_prob_impl(Args const &args)
          : mu_(sign::value * numeric::fdiv(args[sample | Sample()], (std::size_t)1))
          , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
          , threshold_probability_(args[pot_threshold_probability])
          , fit_parameters_(boost::make_tuple(0., 0., 0.))
          , is_dirty_(true)
        {
        }

        void operator ()(dont_care)
        {
            this->is_dirty_ = true;
        }

        template<typename Args>
        result_type result(Args const &args) const
        {
            if (this->is_dirty_)
            {
                this->is_dirty_ = false;

                std::size_t cnt = count(args);

                // the n'th cached sample provides an approximate threshold value u
                std::size_t n = static_cast<std::size_t>(
                    std::ceil(
                        cnt * ( ( is_same<LeftRight, left>::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ )
                    )
                );

                // If n is in a valid range, return result, otherwise return NaN or throw exception
                if ( n >= static_cast<std::size_t>(tail(args).size()))
                {
                    if (std::numeric_limits<float_type>::has_quiet_NaN)
                    {
                        return boost::make_tuple(
                            std::numeric_limits<float_type>::quiet_NaN()
                          , std::numeric_limits<float_type>::quiet_NaN()
                          , std::numeric_limits<float_type>::quiet_NaN()
                        );
                    }
                    else
                    {
                        std::ostringstream msg;
                        msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")";
                        boost::throw_exception(std::runtime_error(msg.str()));
                        return boost::make_tuple(Sample(0), Sample(0), Sample(0));
                    }
                }
                else
                {
                    float_type u = *(tail(args).begin() + n - 1) * sign::value;

                    // compute mean and variance of samples above/under threshold value u
                    for (std::size_t i = 0; i < n; ++i)
                    {
                        mu_ += *(tail(args).begin() + i);
                        sigma2_ += *(tail(args).begin() + i) * (*(tail(args).begin() + i));
                    }

                    this->mu_ = sign::value * numeric::fdiv(this->mu_, n);
                    this->sigma2_ = numeric::fdiv(this->sigma2_, n);
                    this->sigma2_ -= this->mu_ * this->mu_;

                    if (is_same<LeftRight, left>::value)
                        this->threshold_probability_ = 1. - this->threshold_probability_;

                    float_type tmp = numeric::fdiv(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_);
                    float_type xi_hat = 0.5 * ( 1. - tmp );
                    float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp );
                    float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat);
                    float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat;
                    this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat);
                }
            }

            return this->fit_parameters_;
        }

    private:
        mutable float_type mu_;                     // mean of samples above threshold u
        mutable float_type sigma2_;                 // variance of samples above threshold u
        mutable float_type threshold_probability_;
        mutable result_type fit_parameters_;        // boost::tuple that stores fit parameters
        mutable bool is_dirty_;
    };

} // namespace impl

///////////////////////////////////////////////////////////////////////////////
// tag::peaks_over_threshold
//
namespace tag
{
    template<typename LeftRight>
    struct peaks_over_threshold
      : depends_on<count>
      , pot_threshold_value
    {
        /// INTERNAL ONLY
        ///
        typedef accumulators::impl::peaks_over_threshold_impl<mpl::_1, LeftRight> impl;
    };

    template<typename LeftRight>
    struct peaks_over_threshold_prob
      : depends_on<count, tail<LeftRight> >
      , pot_threshold_probability
    {
        /// INTERNAL ONLY
        ///
        typedef accumulators::impl::peaks_over_threshold_prob_impl<mpl::_1, LeftRight> impl;
    };

    struct abstract_peaks_over_threshold
      : depends_on<>
    {
    };
}

///////////////////////////////////////////////////////////////////////////////
// extract::peaks_over_threshold
//
namespace extract
{
    extractor<tag::abstract_peaks_over_threshold> const peaks_over_threshold = {};

    BOOST_ACCUMULATORS_IGNORE_GLOBAL(peaks_over_threshold)
}

using extract::peaks_over_threshold;

// peaks_over_threshold<LeftRight>(with_threshold_value) -> peaks_over_threshold<LeftRight>
template<typename LeftRight>
struct as_feature<tag::peaks_over_threshold<LeftRight>(with_threshold_value)>
{
    typedef tag::peaks_over_threshold<LeftRight> type;
};

// peaks_over_threshold<LeftRight>(with_threshold_probability) -> peaks_over_threshold_prob<LeftRight>
template<typename LeftRight>
struct as_feature<tag::peaks_over_threshold<LeftRight>(with_threshold_probability)>
{
    typedef tag::peaks_over_threshold_prob<LeftRight> type;
};

template<typename LeftRight>
struct feature_of<tag::peaks_over_threshold<LeftRight> >
  : feature_of<tag::abstract_peaks_over_threshold>
{
};

template<typename LeftRight>
struct feature_of<tag::peaks_over_threshold_prob<LeftRight> >
  : feature_of<tag::abstract_peaks_over_threshold>
{
};

// So that peaks_over_threshold can be automatically substituted
// with weighted_peaks_over_threshold when the weight parameter is non-void.
template<typename LeftRight>
struct as_weighted_feature<tag::peaks_over_threshold<LeftRight> >
{
    typedef tag::weighted_peaks_over_threshold<LeftRight> type;
};

template<typename LeftRight>
struct feature_of<tag::weighted_peaks_over_threshold<LeftRight> >
  : feature_of<tag::peaks_over_threshold<LeftRight> >
{};

// So that peaks_over_threshold_prob can be automatically substituted
// with weighted_peaks_over_threshold_prob when the weight parameter is non-void.
template<typename LeftRight>
struct as_weighted_feature<tag::peaks_over_threshold_prob<LeftRight> >
{
    typedef tag::weighted_peaks_over_threshold_prob<LeftRight> type;
};

template<typename LeftRight>
struct feature_of<tag::weighted_peaks_over_threshold_prob<LeftRight> >
  : feature_of<tag::peaks_over_threshold_prob<LeftRight> >
{};

}} // namespace boost::accumulators

#ifdef _MSC_VER
# pragma warning(pop)
#endif

#endif


//          Copyright Tom Westerhout 2018.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include "testing.hpp"
#include <utility>
#include <boost/static_views/hashed.hpp>
#include <boost/static_views/raw_view.hpp>

auto test_make()
{
    struct hasher {
        constexpr auto operator()(int const x) const noexcept
        {
            return static_cast<std::size_t>(x);
        }
    };

    static constexpr int  xs_data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    static constexpr auto xs_lvalue   = boost::static_views::raw_view(xs_data);

    auto const ys = boost::static_views::hashed<6, 2>(xs_lvalue, hasher{});
    using ys_type = std::remove_cv_t<decltype(ys)>;
    STATIC_ASSERT(boost::static_views::View<ys_type>, "");
}

int main()
{
    test_make();
    return boost::report_errors();
}


//=======================================================================
// Copyright (c)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/**
 * @file n_queens_test.cpp
 * @brief
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2014-01-04
 */

#include "test_utils/logger.hpp"

#include "paal/local_search/n_queens/n_queens_local_search.hpp"
#include "paal/data_structures/components/components_replace.hpp"

#include <boost/range/algorithm_ext/iota.hpp>

#include <iostream>

namespace ls = paal::local_search;

struct virtual_gain {
    virtual int operator()(ls::n_queens_solution_adapter<std::vector<int>> &sol,
                           ls::Move m) {
        return ls::n_queens_gain{}
        (sol, m);
    }
};

struct Virtualget_moves {
    virtual auto operator()(
        ls::n_queens_solution_adapter<std::vector<int>> &sol)
        ->decltype(ls::n_queensget_moves{
    }(sol)) {
        return ls::n_queensget_moves{}
        (sol);
    }
};

struct virtual_commit {
    virtual bool operator()(
        ls::n_queens_solution_adapter<std::vector<int>> &sol, ls::Move m) {
        return ls::n_queens_commit{}
        (sol, m);
    }
};

int main(int argc, char **argv) {
    std::string strategy = "FirstBetter";
    if (argc != 2 && argc != 3) {
        std::cout << argv[0] << " "
                  << "number_of_queens strategy=FirstBetter" << std::endl;
        return 1;
    } else if (argc == 3) {
        strategy = argv[2];
        assert(strategy == "FirstBetter" || strategy == "SteepestSlope");
    }
    const int number_of_queens = std::stoi(argv[1]);

    typedef ls::n_queens_solution_adapter<std::vector<int>> Adapter;
    std::vector<int> queens(number_of_queens);
    boost::iota(queens, 0);

    virtual_gain vgain;
    virtual_commit vcommit;
    Virtualget_moves vgetMoves;

    auto gain =
        [&](ls::n_queens_solution_adapter<std::vector<int>> & sol, ls::Move m) {
        return vgain(sol, m);
    };

    auto commit =
        [&](ls::n_queens_solution_adapter<std::vector<int>> & sol, ls::Move m) {
        return vcommit(sol, m);
    };

    auto getMoves = [&](ls::n_queens_solution_adapter<std::vector<int>> & sol) {
        return vgetMoves(sol);
    };

    ls::n_queens_local_search_components<> comps;
    int nr_of_iterations(0);
    auto countingGain =
        paal::utils::make_counting_functor_adaptor(gain, nr_of_iterations);
    auto countingComps = paal::local_search::make_search_components(
        getMoves, countingGain, commit);

    if (strategy == "FirstBetter") {
        ls::n_queens_solution_first_improving(queens, countingComps);
    } else {
        paal::utils::always_false nop;
        ls::n_queens_solution_local_search(
            queens, ls::best_improving_strategy{}, nop, nop, countingComps);
    }
    std::cout << Adapter(queens).obj_fun() << " " << nr_of_iterations
              << std::endl;

    return 0;
}