/*****************************************************************************
*
* Rokko: Integrated Interface for libraries of eigenvalue decomposition
*
* Copyright (C) 2014-2019 Rokko Developers https://github.com/t-sakashita/rokko
*
* 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 <rokko/eigen3.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

#include <gtest/gtest.h>

TEST(matrix, major) {
  int dim = 3;

  // M = 1 2 3
  //     4 5 6
  //     7 8 9

  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> M0(dim,dim); // row major
  M0 << 1,2,3,4,5,6,7,8,9;
  std::cout << M0 << std::endl;
  ASSERT_EQ(M0(0,0),1.0);
  ASSERT_EQ(M0(0,1),2.0);
  ASSERT_EQ(M0(1,0),4.0);
  double* ptr0 = &M0(0,0);
  ASSERT_EQ(*(ptr0 + 1), 2.0); // row major
  ASSERT_EQ((M0.row(0))(1), 2.0);
  ASSERT_EQ((M0.col(0))(1), 4.0);

  Eigen::MatrixXd M1(dim,dim); // column major
  M1 << 1,2,3,4,5,6,7,8,9;
  std::cout << M1 << std::endl;
  ASSERT_EQ(M1(0,0),1.0);
  ASSERT_EQ(M1(0,1),2.0);
  ASSERT_EQ(M1(1,0),4.0);
  double* ptr1 = &M1(0,0);
  ASSERT_EQ(*(ptr1 + 1), 4.0); // column major
  ASSERT_EQ((M1.row(0))(1), 2.0);
  ASSERT_EQ((M1.col(0))(1), 4.0);

  boost::numeric::ublas::matrix<double> M2(dim,dim); // row major
  for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) M2(i,j) = M0(i,j);
  std::cout << M2 << std::endl;
  ASSERT_EQ(M2(0,0),1.0);
  ASSERT_EQ(M2(0,1),2.0);
  ASSERT_EQ(M2(1,0),4.0);
  double* ptr2 = &M2(0,0);
  ASSERT_EQ(*(ptr2 + 1), 2.0); // row major

  boost::numeric::ublas::matrix<double, boost::numeric::ublas::column_major> M3(dim,dim); // column major
  for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) M3(i,j) = M0(i,j);
  std::cout << M3 << std::endl;
  ASSERT_EQ(M3(0,0),1.0);
  ASSERT_EQ(M3(0,1),2.0);
  ASSERT_EQ(M3(1,0),4.0);
  double* ptr3 = &M3(0,0);
  ASSERT_EQ(*(ptr3 + 1), 4.0); // column major

  Eigen::MatrixXd M4(dim, dim); // column major
  for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) M4(i,j) = M0(i,j);
  std::cout << M4 << std::endl;
  ASSERT_EQ(M4(0,0),1.0);
  ASSERT_EQ(M4(0,1),2.0);
  ASSERT_EQ(M4(1,0),4.0);
  double* ptr4 = &M4(0,0);
  ASSERT_EQ(*(ptr4 + 1), 4.0); // column major
}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


//
// Copyright (c) 2012 Juan Palacios juan.palacios.puyana@gmail.com
// This file is part of minimathlibs.
// Subject to the BSD 2-Clause License
// - see < http://opensource.org/licenses/BSD-2-Clause>
//
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TestTranslation3D
#include <boost/test/unit_test.hpp>
#include <vector>
#include <numeric>
#include <functional>
#include "minimath/translation3d.hpp"
#include "minimath/point3d.hpp"

namespace
{
using namespace minimath;
}

BOOST_AUTO_TEST_SUITE(TestTranslation3D)

BOOST_AUTO_TEST_CASE(testInstantiation)
{
    translation3d<double> displ1, displ2;
}

BOOST_AUTO_TEST_CASE(testDefaultEquality)
{
    BOOST_CHECK(translation3d<double>() == translation3d<double>());
}

BOOST_AUTO_TEST_CASE(testCopyConstruction)
{
    translation3d<double> displ1;
    translation3d<double> displ2(displ1);
    BOOST_CHECK(displ1==displ2);
}

BOOST_AUTO_TEST_CASE(testAssignment)
{
    translation3d<double> displ1, displ2;
    displ2 = displ1;
    BOOST_CHECK(displ1==displ2);
}

BOOST_AUTO_TEST_CASE(testNullTranslation)
{
    pointxyzd p(11, 22, 33);
    BOOST_CHECK(pointxyzd(11,22,33) == translation3d<double>()*p);
}

BOOST_AUTO_TEST_CASE(testTranslatePoint)
{
    for (int i = 0; i < 100; ++i)
    {
        pointxyzd p(11, 22, 33);
        translation3d<double> t1(pointxyzd(i, i, i));
        BOOST_CHECK(pointxyzd(11+i, 22+i, 33+i) == t1*p);
        translation3d<double> t2(pointxyzd(-i, -i, -i));
        BOOST_CHECK(pointxyzd(11-i, 22-i, 33-i) == t2*p);
    }
}

BOOST_AUTO_TEST_CASE(testCompoundTranslation)
{
    // make a vector of many translations
    std::vector<translation3d<double> > v;
    int sum = 0;
    for (int i = 0; i<10; ++i)
    {
        sum += i;
        v.push_back(translation3d<double>(pointxyzd(i,i,i)));
    }
    // multiply all the translations together
    translation3d<double> t = std::accumulate(v.begin(), v.end(),
                                              translation3d<double>(),
                                              std::multiplies<translation3d<double> >());
    BOOST_CHECK(pointxyzd(sum, sum, sum) == t*pointxyzd());
}

BOOST_AUTO_TEST_CASE(testInverse)
{
    translation3d<double> t0(pointxyzd(1., 2., 3.));
    BOOST_CHECK(t0.inverse() == translation3d<double>(pointxyzd(-1., -2., -3.)));
}
BOOST_AUTO_TEST_CASE(testInvert)
{
    translation3d<double> t0(pointxyzd(1., 2., 3.));
    t0.invert();
    BOOST_CHECK(t0 == translation3d<double>(pointxyzd(-1., -2., -3.)));
}

BOOST_AUTO_TEST_SUITE_END()


//=======================================================================
// Copyright 2007 Aaron Windsor
//
// 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 <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/ref.hpp>
#include <vector>

#include <boost/graph/planar_canonical_ordering.hpp>
#include <boost/graph/boyer_myrvold_planar_test.hpp>

using namespace boost;

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

    typedef adjacency_list< vecS, vecS, undirectedS,
        property< vertex_index_t, int >, property< edge_index_t, int > >
        graph;

    // Create a maximal planar graph on 6 vertices
    graph g(6);

    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(2, 3, g);
    add_edge(3, 4, g);
    add_edge(4, 5, g);
    add_edge(5, 0, g);

    add_edge(0, 2, g);
    add_edge(0, 3, g);
    add_edge(0, 4, g);

    add_edge(1, 3, g);
    add_edge(1, 4, g);
    add_edge(1, 5, g);

    // Initialize the interior edge index
    property_map< graph, edge_index_t >::type e_index = get(edge_index, g);
    graph_traits< graph >::edges_size_type edge_count = 0;
    graph_traits< graph >::edge_iterator ei, ei_end;
    for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
        put(e_index, *ei, edge_count++);

    // Test for planarity - we know it is planar, we just want to
    // compute the planar embedding as a side-effect
    typedef std::vector< graph_traits< graph >::edge_descriptor > vec_t;
    std::vector< vec_t > embedding(num_vertices(g));
    if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
            boyer_myrvold_params::embedding = make_iterator_property_map(
                embedding.begin(), get(vertex_index, g))))
        std::cout << "Input graph is planar" << std::endl;
    else
        std::cout << "Input graph is not planar" << std::endl;

    typedef std::vector< graph_traits< graph >::vertex_descriptor >
        ordering_storage_t;

    ordering_storage_t ordering;
    planar_canonical_ordering(g,
        make_iterator_property_map(embedding.begin(), get(vertex_index, g)),
        std::back_inserter(ordering));

    ordering_storage_t::iterator oi, oi_end;
    oi_end = ordering.end();
    std::cout << "The planar canonical ordering is: ";
    for (oi = ordering.begin(); oi != oi_end; ++oi)
        std::cout << *oi << " ";
    std::cout << std::endl;

    return 0;
}


#include<iostream>
#define EIGEN_USE_MKL_ALL
#include <Eigen/Eigenvalues>
#include"numerics.hpp"
#include"reddm.hpp"
#include"tpoperators.hpp"
#include "files.hpp"
#include"FTLanczos.hpp"
using namespace Many_Body;
    using Mat= Operators::Mat;
int main(int argc, char *argv[])
{
    size_t M{};
  size_t L{};
  double t0{};
  double omega{};
  double gamma{};
   bool PB{};
    double mean= 0.5*omega*L*M;
  double beta=22.;

  try
  {
    options_description desc{"Options"};
    desc.add_options()
      ("help,h", "Help screen")
      ("L", value(&L)->default_value(4), "L")
      ("M", value(&M)->default_value(2), "M")
      ("t", value(&t0)->default_value(1.), "t0")
      ("gam", value(&gamma)->default_value(1.), "gamma")
      ("omg", value(&omega)->default_value(1.), "omega");
   ("pb", value(&PB)->default_value(true), "PB");

    variables_map vm;
    store(parse_command_line(argc, argv, desc), vm);
    notify(vm);

    if (vm.count("help"))
      {std::cout << desc << '\n'; return 0;}
    else{
      if (vm.count("L"))
      {      std::cout << "L: " << vm["L"].as<size_t>() << '\n';

      }
     if (vm.count("M,m"))
      {
	std::cout << "M: " << vm["M"].as<size_t>() << '\n';

      }
      if (vm.count("t"))
      {
	std::cout << "t0: " << vm["t"].as<double>() << '\n';
      }
       if (vm.count("omg"))
      {
	std::cout << "omega: " << vm["omg"].as<double>() << '\n';
      }
       if (vm.count("gam"))
      {
	std::cout << "gamma: " << vm["gam"].as<double>() << '\n';
      }
                    if (vm.count("pb"))
      {
	std::cout << "PB: " << vm["pb"].as<bool>() << '\n';
      }
    }
  }
  catch (const error &ex)
  {
    std::cerr << ex.what() << '\n';
    return 0;
  }

  double T=1./beta;
   using HolsteinBasis= TensorProduct<ElectronBasis, PhononBasis>;
        PhononBasis g2{ 2, 1};
  ElectronBasis e( L, 1);

  PhononBasis ph(L, M);

  HolsteinBasis TP(e, ph);

        Mat E1=Operators::EKinOperatorL(TP, e, t0, PB);
       Mat Ebdag=Operators::BosonCOperator(TP, ph, gamma, PB);
       std::cout<< "dim "<< TP.dim<< std::endl;
       Mat Eb=Operators::BosonDOperator(TP, ph, gamma, PB);
       Mat Eph=Operators::NumberOperator(TP, ph, omega,  PB);

      //Mat E=Operators::NumberOperatore(TP, e, 1, PB);
      //    std::cout<< HH << std::endl;
      Eigen::VectorXd eigenVals(TP.dim);
       	Mat H=E1+Eph +Ebdag + Eb;
	auto O=Operators::NumberOperator(TP, ph, omega,  PB);
	std::vector<Mat> v{H, O};
       //       auto HH=Eigen::MatrixXd(H);

      auto ev=Eigen::VectorXd(H.rows());
      //    diagMat(HH, ev);

	auto o=LTLM(H, v, T, 10);

	           std::cout<< "for beta/mean = " << beta << std::endl;
       for(auto& l: o)
   	{std::cout<< l <<std::endl; }

  return 0;
}


#include <Eigen/Core>
#include <trajopt_sco/expr_ops.hpp>
#include <trajopt_sco/modeling_utils.hpp>
#include <trajopt/trajectory_costs.hpp>

using namespace std;
using namespace sco;
using namespace Eigen;

namespace {

static MatrixXd diffAxis0(const MatrixXd& in) {
  return in.middleRows(1, in.rows()-1) - in.middleRows(0, in.rows()-1);
}

}

namespace trajopt {

//////////// Quadratic cost functions /////////////////

JointPosCost::JointPosCost(const VarVector& vars, const VectorXd& vals, const VectorXd& coeffs) :
    Cost("JointPos"), vars_(vars), vals_(vals), coeffs_(coeffs) {
    for (int i=0; i < vars.size(); ++i) {
      if (coeffs[i] > 0) {
        AffExpr diff = exprSub(AffExpr(vars[i]), AffExpr(vals[i]));
        exprInc(expr_, exprMult(exprSquare(diff), coeffs[i]));
      }
    }
}
double JointPosCost::value(const vector<double>& xvec) {
  VectorXd dofs = getVec(xvec, vars_);
  return ((dofs - vals_).array().square() * coeffs_.array()).sum();
}
ConvexObjectivePtr JointPosCost::convex(const vector<double>& x, Model* model) {
  ConvexObjectivePtr out(new ConvexObjective(model));
  out->addQuadExpr(expr_);
  return out;
}

JointVelCost::JointVelCost(const VarArray& vars, const VectorXd& coeffs) :
    Cost("JointVel"), vars_(vars), coeffs_(coeffs) {
  for (int i=0; i < vars.rows()-1; ++i) {
    for (int j=0; j < vars.cols(); ++j) {
      AffExpr vel;
      exprInc(vel, exprMult(vars(i,j), -1));
      exprInc(vel, exprMult(vars(i+1,j), 1));
      exprInc(expr_, exprMult(exprSquare(vel),coeffs_[j]));
    }
  }
}
double JointVelCost::value(const vector<double>& xvec) {
  MatrixXd traj = getTraj(xvec, vars_);
  return (diffAxis0(traj).array().square().matrix() * coeffs_.asDiagonal()).sum();
}
ConvexObjectivePtr JointVelCost::convex(const vector<double>& x, Model* model) {
  ConvexObjectivePtr out(new ConvexObjective(model));
  out->addQuadExpr(expr_);
  return out;
}

JointAccCost::JointAccCost(const VarArray& vars, const VectorXd& coeffs) :
    Cost("JointAcc"), vars_(vars), coeffs_(coeffs) {
  for (int i=0; i < vars.rows()-2; ++i) {
    for (int j=0; j < vars.cols(); ++j) {
      AffExpr acc;
      exprInc(acc, exprMult(vars(i,j), -1));
      exprInc(acc, exprMult(vars(i+1,j), 2));
      exprInc(acc, exprMult(vars(i+2,j), -1));
      exprInc(expr_, exprMult(exprSquare(acc), coeffs_[j]));
    }
  }
}
double JointAccCost::value(const vector<double>& xvec) {
  MatrixXd traj = getTraj(xvec, vars_);
  return (diffAxis0(diffAxis0(traj)).array().square().matrix() * coeffs_.asDiagonal()).sum();
}
ConvexObjectivePtr JointAccCost::convex(const vector<double>& x, Model* model) {
  ConvexObjectivePtr out(new ConvexObjective(model));
  out->addQuadExpr(expr_);
  return out;
}

}


/**
 * @file odesolve.cc
 * @brief NPDE homework ODESolve code
 * @author ?, Philippe Peter
 * @date 18.03.2021
 * @copyright Developed at ETH Zurich
 */

#include "odesolve.h"

#include <Eigen/Core>
#include <cmath>
#include <iostream>
#include <vector>

#include "../../../lecturecodes/helperfiles/polyfit.h"

namespace ODESolve {

/* SAM_LISTING_BEGIN_2 */
double TestCvpExtrapolatedEuler() {
  double conv_rate;
  double T = 1.0;
  double y0 = 0.0;
  auto f = [](double y) -> double { return 1.0 + y * y; };

  // TODO : tabulate the values of the error corresponding to
  // \tilde{\psi}, where \psi is the explicit Euler method.
  // return the empirical convergence rate using polyfit.
  // Hint: first define a lambda for \psi. Then use psitilde to obtain a
  // suitable input for odeintequi.

  // ===================
  // Your code goes here
  // ===================
  return conv_rate;
}

/* SAM_LISTING_BEGIN_4 */
std::pair<std::vector<double>, std::vector<double>> SolveTangentIVP() {
  auto f = [](double y) -> double { return 1.0 + y * y; };
  double y0 = 0.0;

  // TODO: run the adaptive integration algorithm
  // ===================
  // Your code goes here
  // ===================
  // dummy vectors (if size 0, the plotting script crashes)
  std::vector<double> t(10, 0.0);
  std::vector<double> Y(10, 1.0);
  return {t, Y};
}
/* SAM_LISTING_END_4 */

}  // namespace ODESolve


#ifndef POINT_TYPE_HPP_
#define POINT_TYPE_HPP_

#include <Eigen/Dense>
#include <iostream>

#define POINT3D                                                  \
  union EIGEN_ALIGN16 {                                          \
    float data[3];                                               \
    struct {                                                     \
      float x;                                                   \
      float y;                                                   \
      float z;                                                   \
    };                                                           \
  };                                                             \
  inline Eigen::Map<Eigen::Vector3f> point() {                   \
    return (Eigen::Vector3f::Map(data));                         \
  }                                                              \
  inline const Eigen::Map<const Eigen::Vector3f> point() const { \
    return (Eigen::Vector3f::Map(data));                         \
  }

namespace point_type {
//三维点
struct EIGEN_ALIGN16 Point3f {
  POINT3D;  //点坐标

  Point3f() = default;
  explicit Point3f(const float x_, const float y_, const float z_)
      : x(x_), y(y_), z(z_) {}
  explicit Point3f(const Eigen::Vector3f& point) { this->point() = point; }

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

inline std::ostream& operator<<(std::ostream& os, const Point3f& p) {
  os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
  return os;
}
}  // namespace point_type

#endif


/* Copyright (C) 2012-2017 IBM Corp.
 * This program is Licensed under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *   http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. See accompanying LICENSE file.
 */
/**
 * @file norms.cpp - computing various norms of ring elements
 **/
#include <numeric>
#include <NTL/BasicThreadPool.h>
#include "NumbTh.h"
#include "DoubleCRT.h"
#include "norms.h"
NTL_CLIENT

long sumOfCoeffs(const zzX& f) // = f(1)
{
  long sum = 0;
  for (long i=0; i<lsize(f); i++) sum += f[i];
  return sum;
}
ZZ sumOfCoeffs(const ZZX& f) // = f(1)
{
  ZZ sum = ZZ::zero();
  for (long i=0; i<=deg(f); i++) sum += coeff(f,i);
  return sum;
}
NTL::ZZ sumOfCoeffs(const DoubleCRT& f)
{
  ZZX poly;
  f.toPoly(poly);
  return sumOfCoeffs(poly);
}

long largestCoeff(const zzX& f) // l_infty norm
{
  long mx = 0;
  for (long i=0; i<lsize(f); i++) {
    if (mx < abs(f[i]))
      mx = abs(f[i]);
  }
  return mx;
}
ZZ largestCoeff(const ZZX& f)
{
  ZZ mx = ZZ::zero();
  for (long i=0; i<=deg(f); i++) {
    if (mx < abs(coeff(f,i)))
      mx = abs(coeff(f,i));
  }
  return mx;
}
ZZ largestCoeff(const Vec<ZZ>& f)
{
  ZZ mx = ZZ::zero();
  for (auto& x : f) {
    if (mx < abs(x))
      mx = abs(x);
  }
  return mx;
}
NTL::ZZ largestCoeff(const DoubleCRT& f)
{
  ZZX poly;
  f.toPoly(poly);
  return largestCoeff(poly);
}

double coeffsL2NormSquared(const zzX& f) // l_2 norm square
{
  double s = 0.0;
  for (long i=0; i<lsize(f); i++) {
    double coef = f[i];
    s += coef * coef;
  }
  return s;
}
xdouble coeffsL2NormSquared(const ZZX& f) // l_2 norm square
{
  xdouble s(0.0);
  for (long i=0; i<=deg(f); i++) {
    xdouble coef(conv<xdouble>(coeff(f,i)));
    s += coef * coef;
  }
  return s;
}
xdouble coeffsL2NormSquared(const DoubleCRT& f) // l2 norm^2
{
  ZZX poly;
  f.toPoly(poly);
  return coeffsL2NormSquared(poly);
}

#if FFT_IMPL
// l_2 norm square of canonical embedding
double embeddingL2NormSquared(const zzX& f, const PAlgebra& palg)
{
  std::vector<cx_double> emb;
  canonicalEmbedding(emb, f, palg);
  double acc = 0.0;
  for (auto& x : emb)
    acc += std::norm(x);
  return 2*acc; // emb just has phi(m)/2 values (paired with complex conjugates)
}

//! Computing the L-infinity norm of the canonical embedding
double embeddingLargestCoeff(const zzX& f, const PAlgebra& palg)
{
  std::vector<cx_double> emb;
  canonicalEmbedding(emb, f, palg);
  double mx = 0.0;
  for (auto& x : emb) {
    double n = std::norm(x);
    if (mx < n) mx = n;
  }
  return sqrt(mx);
}

static xdouble convertAndScale(zzX& ff, const NTL::ZZX& f)
{
  const long MAX_BITS = NTL_SP_BOUND-15; // max allowed bits to avoid double overflow
                                         // in computations
  xdouble factor(1.0);
  long size = NTL::MaxBits(f);
  if (size > MAX_BITS) {
    ZZ zzFactor = ZZ(1) << (size-MAX_BITS); // divide f by this factor

    ZZX scaled = f;
    for (long i: range(f.rep.length())) RightShift(scaled.rep[i], scaled.rep[i], size-MAX_BITS);
    scaled.normalize();

    convert(factor, zzFactor);      // remember the factor
    convert(ff, scaled);            // convert to zzX
  }
  else
    convert(ff, f);                 // convert to zzX
  return factor;
}

static xdouble convertAndScale(ZZX& ff, const NTL::ZZX& f)
{
  const long MAX_BITS = 250; // max allowed bits to avoid double overflow
                             // in computations

  xdouble factor(1.0);
  long size = NTL::MaxBits(f);
  if (size > MAX_BITS) {
    ZZ zzFactor = ZZ(1) << (size-MAX_BITS); // divide f by this factor

    ZZX scaled = f;
    for (long i: range(f.rep.length())) RightShift(scaled.rep[i], scaled.rep[i], size-MAX_BITS);
    scaled.normalize();

    convert(factor, zzFactor);      // remember the factor
    ff = scaled;
  }
  else
    convert(ff, f);                 // convert to zzX
  return factor;
}

xdouble embeddingL2NormSquared(const NTL::ZZX& f, const PAlgebra& palg)
{
  zzX ff; // to hold a scaled-down version of ff;
  xdouble factor = convertAndScale(ff, f);
  return embeddingL2NormSquared(ff, palg)*factor*factor;
}

xdouble embeddingLargestCoeff(const NTL::ZZX& f, const PAlgebra& palg)
{
#if 1
  ZZX ff; // to hold a scaled-down version of ff;
  xdouble factor = convertAndScale(ff, f);
#else
  const ZZX& ff = f;
  xdouble factor { 1.0 };
#endif
  std::vector<cx_double> emb;
  canonicalEmbedding(emb, ff, palg);
  xdouble mx {0.0};
  for (auto& x : emb) {
    double re = std::real(x);
    double im = std::imag(x);
    xdouble n = xdouble(re)*xdouble(re) + xdouble(im)*xdouble(im);
    if (mx < n) mx = n;
  }
  return sqrt(mx)*factor;
}
#endif


/*
@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/config.hpp>
#include <boost/hana/ext/std/integral_constant.hpp>
#include <boost/hana/functional.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/maybe.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>

#include <sstream>
#include <string>
#include <type_traits>
using namespace boost::hana;

int main() {

{

//! [foldl]
auto to_string = [](auto x) {
    return static_cast<std::ostringstream const&>(std::ostringstream{} << x).str();
};

auto show = [=](auto x, auto y) {
    return "(" + to_string(x) + " + " + to_string(y) + ")";
};

BOOST_HANA_RUNTIME_CHECK(
    foldl(make<Tuple>(2, "3", '4'), "1", show) == "(((1 + 2) + 3) + 4)"
);
//! [foldl]

}{

//! [foldl1]
auto to_string = [](auto x) {
    return static_cast<std::ostringstream const&>(std::ostringstream{} << x).str();
};

auto show = [=](auto x, auto y) {
    return "(" + to_string(x) + " + " + to_string(y) + ")";
};

BOOST_HANA_RUNTIME_CHECK(
    foldl1(make<Tuple>(1, "2", '3'), show) == "((1 + 2) + 3)"
);
//! [foldl1]

}{

//! [foldr]
auto to_string = [](auto x) {
    return static_cast<std::ostringstream const&>(std::ostringstream{} << x).str();
};

auto show = [=](auto x, auto y) {
    return "(" + to_string(x) + " + " + to_string(y) + ")";
};

BOOST_HANA_RUNTIME_CHECK(
    foldr(make<Tuple>(1, "2", '3'), "4", show) == "(1 + (2 + (3 + 4)))"
);
//! [foldr]

}{

//! [foldrM]
BOOST_HANA_CONSTEXPR_LAMBDA auto safediv = [](auto x, auto y) {
    return eval_if(y == int_<0>,
        always(nothing),
        [=](auto _) { return just(_(x) / y); }
    );
};

BOOST_HANA_CONSTANT_CHECK(
    foldrM<Maybe>(tuple_c<int, 1000, 8, 4>, int_<2>, safediv)
        ==
    just(int_<1000> / (int_<8> / (int_<4> / int_<2>)))
);

BOOST_HANA_CONSTANT_CHECK(
    foldrM<Maybe>(tuple_c<int, 1000, 8, 4>, int_<0>, safediv)
        ==
    nothing
);
//! [foldrM]

}{

//! [foldr1]
auto to_string = [](auto x) {
    return static_cast<std::ostringstream const&>(std::ostringstream{} << x).str();
};

auto show = [=](auto x, auto y) {
    return "(" + to_string(x) + " + " + to_string(y) + ")";
};

BOOST_HANA_RUNTIME_CHECK(
    foldr1(make<Tuple>(1, "2", '3'), show) == "(1 + (2 + 3))"
);
//! [foldr1]

}{

//! [for_each]
std::stringstream ss;
for_each(make<Tuple>(0, '1', "234", 5.5), [&](auto x) {
    ss << x << ' ';
});

BOOST_HANA_RUNTIME_CHECK(ss.str() == "0 1 234 5.5 ");
//! [for_each]

}{

//! [length]
BOOST_HANA_CONSTANT_CHECK(length(make<Tuple>()) == size_t<0>);
BOOST_HANA_CONSTANT_CHECK(length(make<Tuple>(1, '2', 3.0)) == size_t<3>);

BOOST_HANA_CONSTANT_CHECK(length(nothing) == size_t<0>);
BOOST_HANA_CONSTANT_CHECK(length(just('x')) == size_t<1>);
//! [length]

}{

//! [size]
BOOST_HANA_CONSTANT_CHECK(size(make<Tuple>()) == size_t<0>);
BOOST_HANA_CONSTANT_CHECK(size(make<Tuple>(1, '2', 3.0)) == size_t<3>);

BOOST_HANA_CONSTANT_CHECK(size(nothing) == size_t<0>);
BOOST_HANA_CONSTANT_CHECK(size(just('x')) == size_t<1>);
//! [size]

}{

//! [maximum]
BOOST_HANA_CONSTANT_CHECK(
    maximum(tuple_c<int, -1, 0, 2, -4, 6, 9>) == int_<9>
);
//! [maximum]
//!
}{

//! [minimum]
BOOST_HANA_CONSTANT_CHECK(
    minimum(tuple_c<int, -1, 0, 2, -4, 6, 9>) == int_<-4>
);
//! [minimum]

}{

//! [product]
BOOST_HANA_CONSTANT_CHECK(
    product(range(int_<1>, int_<6>)) == int_<1 * 2 * 3 * 4 * 5>
);

BOOST_HANA_CONSTEXPR_CHECK(
    product(make<Tuple>(1, int_<3>, long_<-5>, 9)) == 1 * 3 * -5 * 9
);
//! [product]

}{

//! [sum]
BOOST_HANA_CONSTANT_CHECK(
    sum(range(int_<1>, int_<6>)) == int_<1 + 2 + 3 + 4 + 5>
);

BOOST_HANA_CONSTEXPR_CHECK(
    sum(make<Tuple>(1, int_<3>, long_<-5>, 9)) == 1 + 3 - 5 + 9
);
//! [sum]

}{

//! [unpack]
auto cheap_tie = [](auto& ...vars) {
    return partial(flip(unpack), [&vars...](auto ...values) {
        // Using an initializer list sequences the assignments.
        int dummy[] = {((vars = values), 0)...};
        (void)dummy;
    });
};
int a = 0;
char b = '\0';
double c = 0;

cheap_tie(a, b, c)(make<Tuple>(1, '2', 3.3));
BOOST_HANA_RUNTIME_CHECK(a == 1 && b == '2' && c == 3.3);
//! [unpack]

}{

//! [fuse]
BOOST_HANA_CONSTEXPR_LAMBDA auto add = [](auto x, auto y) {
    return x + y;
};

// Would be `boost::fusion::make_fused(add)` in Boost.Fusion.
BOOST_HANA_CONSTEXPR_LAMBDA auto add_seq = fuse(add);

BOOST_HANA_CONSTEXPR_CHECK(add_seq(make<Tuple>(1, 2)) == add(1, 2));
//! [fuse]

}{

//! [count_if]
using namespace literals;
BOOST_HANA_CONSTEXPR_LAMBDA auto odd = [](auto x) {
    return x % 2_c != 0_c;
};

constexpr auto types = tuple_t<int, char, long, short, char, double>;
constexpr auto ints = tuple_c<int, 1, 2, 3>;

BOOST_HANA_CONSTANT_CHECK(count_if(ints, odd) == size_t<2>);

BOOST_HANA_CONSTANT_CHECK(count_if(types, trait<std::is_floating_point>) == size_t<1>);
BOOST_HANA_CONSTANT_CHECK(count_if(types, _ == type<char>) == size_t<2>);
BOOST_HANA_CONSTANT_CHECK(count_if(types, _ == type<void>) == size_t<0>);
//! [count_if]

}{

//! [count]
constexpr auto types = tuple_t<int, char, long, short, char, double>;
constexpr auto ints = tuple_c<int, 1, 2, 3, 2, 2, 4, 2>;

BOOST_HANA_CONSTANT_CHECK(count(ints, int_<2>) == size_t<4>);
BOOST_HANA_CONSTEXPR_CHECK(count(ints, 2) == 4);
BOOST_HANA_CONSTANT_CHECK(count(types, type<char>) == size_t<2>);
//! [count]

}{

//! [maximum_by]
BOOST_HANA_CONSTEXPR_LAMBDA auto size = [](auto xs, auto ys) {
    return length(xs) < length(ys);
};

BOOST_HANA_CONSTEXPR_CHECK(
    maximum_by(size, make<Tuple>(make<Tuple>(),
                                 make<Tuple>(1, '2'),
                                 make<Tuple>(3.3, nullptr, 4)))
    ==
    make<Tuple>(3.3, nullptr, 4)
);
//! [maximum_by]

}{

//! [minimum_by]
BOOST_HANA_CONSTEXPR_LAMBDA auto size = [](auto xs, auto ys) {
    return length(xs) < length(ys);
};

BOOST_HANA_CONSTANT_CHECK(
    minimum_by(size, make<Tuple>(make<Tuple>(),
                                 make<Tuple>(1, '2'),
                                 make<Tuple>(3.3, nullptr, 4)))
    ==
    make<Tuple>()
);
//! [minimum_by]

}

}


/**
 * \file ToneStackFilter.cpp
 */

#include <boost/math/tools/polynomial.hpp>

#include "ToneStackFilter.h"
#include "IIRFilter.h"

namespace ATK
{
  template<typename DataType>
  ToneStackCoefficients<DataType>::ToneStackCoefficients(int nb_channels)
  :TypedBaseFilter<DataType>(nb_channels, nb_channels), R1(0), R2(0), R3(0), R4(0), C1(0), C2(0), C3(0), low(.5), middle(.5), high(.5)
  {
  }

  template<typename DataType>
  ToneStackCoefficients<DataType>::ToneStackCoefficients(ToneStackCoefficients&& other)
  :Parent(std::move(other)), R1(other.R1), R2(other.R2), R3(other.R3), R4(other.R4), C1(other.C1), C2(other.C2), C3(other.C3), low(other.low), middle(other.middle), high(other.high)
  {

  }

  template<typename DataType>
  void ToneStackCoefficients<DataType>::setup()
  {
    Parent::setup();

    coefficients_in.assign(in_order+1, 0);
    coefficients_out.assign(out_order, 0);

    DataType tempm[2] = {static_cast<DataType>(-2 * input_sampling_rate), static_cast<DataType>(2 * input_sampling_rate)};
    DataType tempp[2] = {static_cast<DataType>(1), static_cast<DataType>(1)};
    boost::math::tools::polynomial<DataType> poly1(tempm, 1);
    boost::math::tools::polynomial<DataType> poly2(tempp, 1);

    boost::math::tools::polynomial<DataType> b;
    boost::math::tools::polynomial<DataType> a;

    b = poly2 * poly2 * poly1 * (high*C1*R1 + middle*C3*R3 + low*(C1*R2 + C2*R2) + (C1*R3 + C2*R3));
    b += poly2 * poly1 * poly1 * (high*(C1*C2*R1*R4 + C1*C3*R1*R4) - middle*middle*(C1*C3*R3*R3 + C2*C3*R3*R3) + middle*(C1*C3*R1*R3 + C1*C3*R3*R3 + C2*C3*R3*R3)
      + low*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4) + low*middle*(C1*C3*R2*R3 + C2*C3*R2*R3)
      + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4));
    b += poly1 * poly1 * poly1 * (low*middle*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) - middle*middle*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4)
      + middle*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + high*C1*C2*C3*R1*R3*R4 - high*middle*C1*C2*C3*R1*R3*R4
      + high*low*C1*C2*C3*R1*R2*R4);

    a = poly2 * poly2 * poly2;
    a += poly2 * poly2 * poly1 * ((C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4) + middle*C3*R3 + low*(C1*R2 + C2*R2));
    a += poly2 * poly1 * poly1 * (middle*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*R3*R3 + C2*C3*R3*R3)
      + low*middle*(C1*C3*R2*R3 + C2*C3*R2*R3) - middle*middle*(C1*C3*R3*R3 + C2*C3*R3*R3) + low*(C1*C2*R2*R4 + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4)
      + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4 + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4));
    a += poly1 * poly1 * poly1 * (low*middle*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) - middle*middle*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4)
      + middle*(C1*C2*C3*R3*R3*R4 + C1*C2*C3*R1*R3*R3 - C1*C2*C3*R1*R3*R4)
      + low*C1*C2*C3*R1*R2*R4 + C1*C2*C3*R1*R3*R4);

    for(int i = 0; i < in_order + 1; ++i)
    {
      coefficients_in[i] = b[i] / a[out_order];
    }
    for(int i = 0; i < out_order; ++i)
    {
      coefficients_out[i] = -a[i] / a[out_order];
    }
  }

  template<typename DataType_>
  void ToneStackCoefficients<DataType_>::set_low(DataType_ low)
  {
    if(low < 0 || low > 1)
    {
      throw std::out_of_range("Low is outside the interval [0,1]");
    }
    this->low = low;

    setup();
  }

  template<typename DataType_>
  DataType_ ToneStackCoefficients<DataType_>::get_low() const
  {
    return low;
  }

  template<typename DataType_>
  void ToneStackCoefficients<DataType_>::set_middle(DataType_ middle)
  {
    if(middle < 0 || middle > 1)
    {
      throw std::out_of_range("Middle is outside the interval [0,1]");
    }
    this->middle = middle;

    setup();
  }

  template<typename DataType_>
  DataType_ ToneStackCoefficients<DataType_>::get_middle() const
  {
    return middle;
  }

  template<typename DataType_>
  void ToneStackCoefficients<DataType_>::set_high(DataType_ high)
  {
    if(high < 0 || high > 1)
    {
      throw std::out_of_range("high is outside the interval [0,1]");
    }
    this->high = high;

    setup();
  }

  template<typename DataType_>
  DataType_ ToneStackCoefficients<DataType_>::get_high() const
  {
    return high;
  }

  template<typename DataType>
  IIRFilter<ToneStackCoefficients<DataType> > ToneStackCoefficients<DataType>::buildBassmanStack()
  {
    IIRFilter<ToneStackCoefficients<DataType> > filter;
    filter.set_coefficients(static_cast<DataType>(250e3), static_cast<DataType>(1e6), static_cast<DataType>(25e3), static_cast<DataType>(45e3),
      static_cast<DataType>(250e-12), static_cast<DataType>(20e-9), static_cast<DataType>(20e-9));
    return std::move(filter);
  }

  template<typename DataType>
  IIRFilter<ToneStackCoefficients<DataType> > ToneStackCoefficients<DataType>::buildJCM800Stack()
  {
    IIRFilter<ToneStackCoefficients<DataType> > filter;
    filter.set_coefficients(static_cast<DataType>(220e3), static_cast<DataType>(1e6), static_cast<DataType>(22e3), static_cast<DataType>(33e3),
      static_cast<DataType>(470e-12), static_cast<DataType>(22e-9), static_cast<DataType>(22e-9));
    return std::move(filter);
  }

  template<typename DataType_>
  void ToneStackCoefficients<DataType_>::set_coefficients( DataType R1, DataType R2, DataType R3, DataType R4, DataType C1, DataType C2, DataType C3 )
  {
    this->R1 = R1;
    this->R2 = R2;
    this->R3 = R3;
    this->R4 = R4;
    this->C1 = C1;
    this->C2 = C2;
    this->C3 = C3;
  }

  template class ToneStackCoefficients<float>;
  template class ToneStackCoefficients<double>;

  template class IIRFilter<ToneStackCoefficients<float> >;
  template class IIRFilter<ToneStackCoefficients<double> >;
}


#include <gtest/gtest.h>

#include "mfem.hpp"
using namespace mfem;

#include <iostream>
#include <fstream>
#include <random>

#include <Eigen/Core>
#include <Eigen/Dense>

#include "../include/mymfem/mybilinearform.hpp"
#include "../include/mymfem/utilities.hpp"

#include "../include/core/config.hpp"
#include "../include/stokes/assembly.hpp"

// test velocity coefficient
class TestVelocityCoeff : public VectorCoefficient
{
public:
    TestVelocityCoeff () : VectorCoefficient (2) {}

    void Eval (Vector& v, ElementTransformation& T,
               const IntegrationPoint& ip)
    {
        Vector transip(2);
        T.Transform(ip, transip);
        v = velocity(transip);
    }

    Vector velocity (const Vector& x) const
    {
        Vector v(2);
        v(0) = x(0);
        v(1) = -x(1);
        return v;
    }
};

TEST(RStokes, vshape_test1)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"ref_tri_elem";
    Mesh mesh(mesh_file.c_str());
    assert(mesh.GetNE() == 1);

    int deg = 1;
    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(deg, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    Vector true_v(2);
    true_v(0) = +3;
    true_v(1) = -2;
    VectorConstantCoefficient vCoeff(true_v);
    GridFunction vFn(R_space);
    vFn.ProjectCoefficient(vCoeff);

    int j=0; // only 1 element in the mesh
    {
        const FiniteElement *fe = R_space->GetFE(j);
        ElementTransformation *trans
                = R_space->GetElementTransformation(j);

        Array<int> vdofs;
        Vector fe_dofs(fe->GetDof());
        R_space->GetElementVDofs(j, vdofs);
        get_dofs(vFn, vdofs, fe_dofs);

        const IntegrationRule *ir = &IntRules.Get(fe->GetGeomType(), 2);
        DenseMatrix vshape(fe->GetDof(),2);
        for (int i = 0; i < ir->GetNPoints(); i++)
        {
            const IntegrationPoint &ip = ir->IntPoint(i);
            trans->SetIntPoint(&ip);
            fe->CalcVShape(*trans, vshape);

            Vector v(2);
            vshape.MultTranspose(fe_dofs, v);

            double TOL = 1E-10;
            v -= true_v;
            ASSERT_LE(v.Norml2(), TOL);
        }
    }

    delete hdiv_coll;
    delete R_space;
}

TEST(RStokes, gradvshape_test1)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"ref_tri_elem";
    Mesh mesh(mesh_file.c_str());
    assert(mesh.GetNE() == 1);

    int deg = 1;
    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(deg, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    Vector true_v(2);
    true_v(0) = +3;
    true_v(1) = -2;
    VectorConstantCoefficient vCoeff(true_v);
    GridFunction vFn(R_space);
    vFn.ProjectCoefficient(vCoeff);

    int j=0; // only 1 element in the mesh
    {
        const FiniteElement *fe = R_space->GetFE(j);
        ElementTransformation *trans
                = R_space->GetElementTransformation(j);

        Array<int> vdofs;
        Vector fe_dofs(fe->GetDof());
        R_space->GetElementVDofs(j, vdofs);
        get_dofs(vFn, vdofs, fe_dofs);

        const IntegrationRule *ir = &IntRules.Get(fe->GetGeomType(), 0);
        DenseTensor gradvshape(2,2,fe->GetDof());
        for (int i = 0; i < ir->GetNPoints(); i++)
        {
            const IntegrationPoint &ip = ir->IntPoint(i);
            trans->SetIntPoint(&ip);
            fe->CalcGradVShape(*trans, gradvshape);

            DenseMatrix gradu(2,2);
            gradu = 0.0;
            for (int k=0; k<fe->GetDof(); k++) {
                gradu.Add(fe_dofs(k), gradvshape(k));
            }

            double TOL = 1E-10;
            ASSERT_LE(gradu.FNorm(), TOL);
        }
    }

    delete hdiv_coll;
    delete R_space;
}

TEST(RStokes, gradvshape_test2)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"ref_tri_elem";
    Mesh mesh(mesh_file.c_str());
    assert(mesh.GetNE() == 1);

    int deg = 3;
    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(deg, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    TestVelocityCoeff vCoeff;
    GridFunction vFn(R_space);
    vFn.ProjectCoefficient(vCoeff);

    DenseMatrix true_gradu(2,2);
    true_gradu = 0.0;
    true_gradu(0,0) = 1;
    true_gradu(1,1) = -1;

    int j=0; // only 1 element in the mesh
    {
        const FiniteElement *fe = R_space->GetFE(j);
        ElementTransformation *trans
                = R_space->GetElementTransformation(j);

        Array<int> vdofs;
        Vector fe_dofs(fe->GetDof());
        R_space->GetElementVDofs(j, vdofs);
        get_dofs(vFn, vdofs, fe_dofs);

        const IntegrationRule *ir = &IntRules.Get(fe->GetGeomType(), 2);
        DenseTensor gradvshape(2,2,fe->GetDof());
        for (int i = 0; i < ir->GetNPoints(); i++)
        {
            const IntegrationPoint &ip = ir->IntPoint(i);
            trans->SetIntPoint(&ip);
            fe->CalcGradVShape(*trans, gradvshape);

            DenseMatrix gradu(2,2);
            gradu = 0.0;
            for (int k=0; k<fe->GetDof(); k++) {
                gradu.Add(fe_dofs(k), gradvshape(k));
            }

            double TOL = 1E-10;
            gradu -= true_gradu;
            ASSERT_LE(gradu.FNorm(), TOL);
        }
    }

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, VectorFEDiffusion_test1)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"tri_elem1";
    Mesh mesh(mesh_file.c_str());
    assert(mesh.GetNE() == 1);

    Array<int> ess_bdr_marker;
    ess_bdr_marker.SetSize(mesh.bdr_attributes.Max());
    ess_bdr_marker = 1;

    GridFunction *gdum = nullptr; // dummy

    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(0, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    mymfem::MyBilinearForm *diffusion_form
            = new mymfem::MyBilinearForm(R_space);
    diffusion_form->MyAddDomainIntegrator
            (new mymfem::DiffusionIntegrator);
    diffusion_form->MyAssemble(gdum);
    diffusion_form->Finalize();
    SparseMatrix *diffusion_buf = diffusion_form->LoseMat();
    delete diffusion_form;
    DenseMatrix &diffusion = *(diffusion_buf->ToDenseMatrix());

    DenseMatrix true_diffusion(diffusion.NumRows(), diffusion.NumCols());
    true_diffusion = 0.0;
    true_diffusion(0,0) =  0.5;
    true_diffusion(0,1) = -0.5;
    true_diffusion(0,2) = -0.5;

    true_diffusion(1,0) = -0.5;
    true_diffusion(1,1) =  0.5;
    true_diffusion(1,2) =  0.5;

    true_diffusion(2,0) = -0.5;
    true_diffusion(2,1) =  0.5;
    true_diffusion(2,2) =  0.5;

    //true_diffusion.Print();
    //diffusion.Print();

    double TOL = 1E-10;
    diffusion -= true_diffusion;
    ASSERT_LE(diffusion.FNorm(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, VectorFEDiffusionConsistencySymmetry_test1)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"tri_elem1";
    Mesh mesh(mesh_file.c_str());

    Array<int> ess_bdr_marker;
    ess_bdr_marker.SetSize(mesh.bdr_attributes.Max());
    ess_bdr_marker = 1;

    GridFunction *gdum = nullptr; // dummy

    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(0, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    mymfem::MyBilinearForm *diffusionCons_form
            = new mymfem::MyBilinearForm(R_space);
    diffusionCons_form->MyAddFaceIntegrator
            (new mymfem::DiffusionConsistencyIntegrator);
    diffusionCons_form->MyAssemble(gdum);
    diffusionCons_form->Finalize();
    SparseMatrix *diffusionCons_buf = diffusionCons_form->LoseMat();
    delete diffusionCons_form;
    DenseMatrix &diffusionCons = *(diffusionCons_buf->ToDenseMatrix());

    mymfem::MyBilinearForm *diffusionSymm_form
            = new mymfem::MyBilinearForm(R_space);
    diffusionSymm_form->MyAddFaceIntegrator
            (new mymfem::DiffusionSymmetryIntegrator);
    diffusionSymm_form->MyAssemble(gdum);
    diffusionSymm_form->Finalize();
    SparseMatrix *diffusionSymm_buf = diffusionSymm_form->LoseMat();
    delete diffusionSymm_form;
    DenseMatrix &diffusionSymm = *(diffusionSymm_buf->ToDenseMatrix());

    DenseMatrix true_diffusion(diffusionCons.NumRows(),
                               diffusionCons.NumCols());
    true_diffusion = 0.0;
    true_diffusion(0,0) = -0.5;
    true_diffusion(0,1) = +0.5;
    true_diffusion(0,2) = +0.5;

    true_diffusion(1,0) = +0.5;
    true_diffusion(1,1) = -0.5;
    true_diffusion(1,2) = -0.5;

    true_diffusion(2,0) = +0.5;
    true_diffusion(2,1) = -0.5;
    true_diffusion(2,2) = -0.5;

    //true_diffusion.Print();
    //diffusion.Print();

    double TOL = 1E-10;
    diffusionCons -= true_diffusion;
    diffusionSymm -= true_diffusion;
    ASSERT_LE(diffusionCons.FNorm(), TOL);
    ASSERT_LE(diffusionSymm.FNorm(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, VectorFEDiffusionPenalty_test1)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"tri_elem1";
    Mesh mesh(mesh_file.c_str());

    Array<int> ess_bdr_marker;
    ess_bdr_marker.SetSize(mesh.bdr_attributes.Max());
    ess_bdr_marker = 1;

    GridFunction *gdum = nullptr; // dummy

    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(0, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    mymfem::MyBilinearForm *diffusionPen_form
            = new mymfem::MyBilinearForm(R_space);
    diffusionPen_form->MyAddFaceIntegrator
            (new mymfem::DiffusionPenaltyIntegrator(1.0));
    diffusionPen_form->MyAssemble(gdum);
    diffusionPen_form->Finalize();
    SparseMatrix *diffusionCons_buf = diffusionPen_form->LoseMat();
    delete diffusionPen_form;
    DenseMatrix &diffusionPen= *(diffusionCons_buf->ToDenseMatrix());

    DenseMatrix true_diffusion(diffusionPen.NumRows(),
                               diffusionPen.NumCols());
    true_diffusion = 0.0;
    true_diffusion(0,0) = 5./6;
    true_diffusion(0,1) = -7./12;
    true_diffusion(0,2) = 1./6;

    true_diffusion(1,0) = -7./12;
    true_diffusion(1,1) = 13./12;
    true_diffusion(1,2) = -5./12;

    true_diffusion(2,0) = 1./6;
    true_diffusion(2,1) = -5./12;
    true_diffusion(2,2) = 11./6;

    //true_diffusion.Print();
    //diffusionPen.Print();

    double TOL = 1E-10;
    diffusionPen -= true_diffusion;
    ASSERT_LE(diffusionPen.FNorm(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, VectorFEDiffusion_test2)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"test_mesh1";
    Mesh mesh(mesh_file.c_str());

    Array<int> ess_bdr_marker;
    ess_bdr_marker.SetSize(mesh.bdr_attributes.Max());
    ess_bdr_marker = 1;

    GridFunction *gdum = nullptr; // dummy

    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(0, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    mymfem::MyBilinearForm *diffusion_form
            = new mymfem::MyBilinearForm(R_space);
    diffusion_form->MyAddDomainIntegrator
            (new mymfem::DiffusionIntegrator);
    diffusion_form->MyAssemble(gdum);
    diffusion_form->Finalize();
    SparseMatrix *diffusion_buf = diffusion_form->LoseMat();
    delete diffusion_form;
    DenseMatrix &diffusion = *(diffusion_buf->ToDenseMatrix());

    DenseMatrix true_diffusion(diffusion.NumRows(), diffusion.NumCols());
    true_diffusion = 0.0;
    true_diffusion(0,0) =  2;
    true_diffusion(0,1) = -1;
    true_diffusion(0,2) = -1;
    true_diffusion(0,3) = -1;
    true_diffusion(0,4) = -1;

    true_diffusion(1,0) = -1;
    true_diffusion(1,1) =  1;
    true_diffusion(1,2) =  1;

    true_diffusion(2,0) = -1;
    true_diffusion(2,1) =  1;
    true_diffusion(2,2) =  1;

    true_diffusion(3,0) = -1;
    true_diffusion(3,3) =  1;
    true_diffusion(3,4) =  1;

    true_diffusion(4,0) = -1;
    true_diffusion(4,3) =  1;
    true_diffusion(4,4) =  1;

    //true_diffusion.Print();
    //diffusion.Print();

    double TOL = 1E-10;
    diffusion -= true_diffusion;
    ASSERT_LE(diffusion.FNorm(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, VectorFEDiffusionConsistencySymmetry_test2)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"test_mesh1";
    Mesh mesh(mesh_file.c_str());

    Array<int> ess_bdr_marker;
    ess_bdr_marker.SetSize(mesh.bdr_attributes.Max());
    ess_bdr_marker = 1;

    GridFunction *gdum = nullptr; // dummy

    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(0, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    mymfem::MyBilinearForm *diffusionCons_form
            = new mymfem::MyBilinearForm(R_space);
    diffusionCons_form->MyAddFaceIntegrator
            (new mymfem::DiffusionConsistencyIntegrator);
    diffusionCons_form->MyAssemble(gdum);
    diffusionCons_form->Finalize();
    SparseMatrix *diffusionCons_buf = diffusionCons_form->LoseMat();
    delete diffusionCons_form;
    DenseMatrix &diffusionCons = *(diffusionCons_buf->ToDenseMatrix());

    mymfem::MyBilinearForm *diffusionSymm_form
            = new mymfem::MyBilinearForm(R_space);
    diffusionSymm_form->MyAddFaceIntegrator
            (new mymfem::DiffusionSymmetryIntegrator);
    diffusionSymm_form->MyAssemble(gdum);
    diffusionSymm_form->Finalize();
    SparseMatrix *diffusionSymm_buf = diffusionSymm_form->LoseMat();
    delete diffusionSymm_form;
    DenseMatrix &diffusionSymm = *(diffusionSymm_buf->ToDenseMatrix());

    DenseMatrix true_diffusion(diffusionCons.NumRows(),
                               diffusionCons.NumCols());
    true_diffusion = 0.0;

    true_diffusion(1,0) = +1;
    true_diffusion(1,1) = -1;
    true_diffusion(1,2) = -1;

    true_diffusion(2,0) = +1;
    true_diffusion(2,1) = -1;
    true_diffusion(2,2) = -1;

    true_diffusion(3,0) = +1;
    true_diffusion(3,3) = -1;
    true_diffusion(3,4) = -1;

    true_diffusion(4,0) = +1;
    true_diffusion(4,3) = -1;
    true_diffusion(4,4) = -1;

    //true_diffusion.Print();
    //diffusionCons.Print();
    //diffusionSymm.Print();

    double TOL = 1E-10;
    diffusionCons -= true_diffusion;
    ASSERT_LE(diffusionCons.FNorm(), TOL);

    true_diffusion.Transpose();
    diffusionSymm -= true_diffusion;
    ASSERT_LE(diffusionSymm.FNorm(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, consistency_quad_elem)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"ref_quad_elem";
    Mesh mesh(mesh_file.c_str());

    GridFunction *gdum = nullptr; // dummy

    int deg = 2;
    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(deg, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    Vector true_v(2);
    true_v(0) = +3;
    true_v(1) = -2;
    //VectorConstantCoefficient vCoeff(true_v);
    TestVelocityCoeff vCoeff;
    GridFunction v(R_space);
    v.ProjectCoefficient(vCoeff);

    mymfem::MyBilinearForm *diffusion_form
            = new mymfem::MyBilinearForm(R_space);
    diffusion_form->MyAddDomainIntegrator
            (new mymfem::DiffusionIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionConsistencyIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionSymmetryIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionPenaltyIntegrator(1.0));
    diffusion_form->MyAssemble(gdum);
    diffusion_form->Finalize();
    SparseMatrix *diffusion = diffusion_form->LoseMat();
    delete diffusion_form;

    // Diffusion * V
    Vector buf1(R_space->GetTrueVSize());
    diffusion->Mult(v, buf1);

    // Right-hand side
    Vector buf2(R_space->GetTrueVSize());
    LinearForm bdryDiffusion_form(R_space);
    bdryDiffusion_form.AddBdrFaceIntegrator
            (new mymfem::BdryDiffusionConsistencyIntegrator(vCoeff));
    bdryDiffusion_form.AddBdrFaceIntegrator
            (new mymfem::BdryDiffusionPenaltyIntegrator(vCoeff, 1.0));
    bdryDiffusion_form.Assemble();
    buf2 = bdryDiffusion_form.GetData();

    double TOL = 1E-10;
    buf1 -= buf2;
    ASSERT_LE(buf1.Norml2(), TOL);

    delete hdiv_coll;
    delete R_space;
}

TEST(Stokes, consistency_tri_elem)
{
    std::string input_dir = "../input/";
    const std::string mesh_file = input_dir+"ref_tri_elem";
    Mesh mesh(mesh_file.c_str());

    GridFunction *gdum = nullptr; // dummy

    int deg = 2;
    FiniteElementCollection *hdiv_coll
            = new RT_FECollection(deg, mesh.Dimension());
    FiniteElementSpace *R_space
            = new FiniteElementSpace(&mesh, hdiv_coll);

    Vector true_v(2);
    true_v(0) = +3;
    true_v(1) = -2;
    //VectorConstantCoefficient vCoeff(true_v);
    TestVelocityCoeff vCoeff;
    GridFunction vFn(R_space);
    vFn.ProjectCoefficient(vCoeff);

    mymfem::MyBilinearForm *diffusion_form
            = new mymfem::MyBilinearForm(R_space);
    diffusion_form->MyAddDomainIntegrator
            (new mymfem::DiffusionIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionConsistencyIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionSymmetryIntegrator);
    diffusion_form->MyAddFaceIntegrator
            (new mymfem::DiffusionPenaltyIntegrator(1.0));
    diffusion_form->MyAssemble(gdum);
    diffusion_form->Finalize();
    SparseMatrix *diffusion = diffusion_form->LoseMat();
    delete diffusion_form;

    // Diffusion * V
    Vector buf1(R_space->GetTrueVSize());
    diffusion->Mult(vFn, buf1);

    // Right-hand side
    Vector buf2(R_space->GetTrueVSize());
    LinearForm bdryDiffusion_form(R_space);
    bdryDiffusion_form.AddBdrFaceIntegrator
            (new mymfem::BdryDiffusionConsistencyIntegrator(vCoeff));
    bdryDiffusion_form.AddBdrFaceIntegrator
            (new mymfem::BdryDiffusionPenaltyIntegrator(vCoeff, 1.0));
    bdryDiffusion_form.Assemble();
    buf2 = bdryDiffusion_form.GetData();

    double TOL = 1E-10;
    buf1 -= buf2;
    ASSERT_LE(buf1.Norml2(), TOL);

    delete hdiv_coll;
    delete R_space;
}

// End of file


/**
 * @file asymptotic.cc
 * @brief Creates convergence plots for experiment 3.2.3.12
 * @author Tobias Rohner
 * @date April 2020
 * @copyright MIT License
 */

#define _USE_MATH_DEFINES

#include <lf/quad/gauss_quadrature.h>

#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <boost/program_options.hpp>
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>

namespace po = boost::program_options;

// Code for empiric exploration of asymptotic convergence of norms of the
// discretization error for 1D finite element discretization of a 2-point BVP.
// Special example with a highly oscillatory solution
int main(int argc, char *argv[]) {
  po::options_description desc("Allowed options");
  // clang-format off
  desc.add_options()
  ("output,o", po::value<std::string>(), "Name of the output file")
  ("M_max,M", po::value<int>()->default_value(500), "Maximum number of cells")
  ("dM,m", po::value<int>()->default_value(5), "Increment in M")
  ("num_quad_points,n", po::value<int>()->default_value(2), "Number of points for numerical quadrature");
  // clang-format on
  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  if (vm.count("output") == 0) {
    std::cout << desc << std::endl;
    exit(1);
  }
  const int M_max = vm["M_max"].as<int>();
  const int dM = vm["dM"].as<int>();
  const int num_quad_points = vm["num_quad_points"].as<int>();
  const std::string output_file = vm["output"].as<std::string>();
  const auto [quad_points, quad_weights] = lf::quad::GaussLegendre(2);

  // Load function
  const auto f = [](double x) {
    return 10000 * M_PI * M_PI * x * x * std::sin(50 * M_PI * x * x) -
           100 * M_PI * std::cos(50 * M_PI * x * x);
  };
  // Analytic solution (highly oscillatory)
  const auto u = [](double x) { return std::sin(50 * M_PI * x * x); };
  // Gradient of analytic solution
  const auto u_grad = [](double x) {
    return 100 * M_PI * x * std::cos(50 * M_PI * x * x);
  };

  Eigen::MatrixXd results(M_max / dM, 4);
  // Loop over meshes with increasing numbers of cells
  for (int M = dM; M <= M_max; M += dM) {
    // The mesh width
    const double h = 1. / M;

    // Generate the tri-diagonal stiffness matrix for an equidistant
    // mesh on [0, 1] with M cells and p.w. linear Lagrangian finite elements
    // Formulas are explained in Section 2.3 of the lecture document
    Eigen::SparseMatrix<double> A(M + 1, M + 1);
    A.reserve(3 * (M + 1));
    // Fill the diagonal
    for (int i = 0; i < M + 1; ++i) {
      A.coeffRef(i, i) += 2. / h;
    }
    // Fill the off-diagonals
    for (int i = 0; i < M; ++i) {
      A.coeffRef(i, i + 1) += -1. / h;
      A.coeffRef(i + 1, i) += -1. / h;
    }

    // Generate the load vector
    Eigen::VectorXd rhs = Eigen::VectorXd::Zero(M + 1);
    for (int i = 0; i < M; ++i) {
      const double a = static_cast<double>(i) / M;
      const Eigen::VectorXd loc_quad_points =
          Eigen::VectorXd::Constant(num_quad_points, a) + h * quad_points;
      const Eigen::VectorXd loc_quad_weights = h * quad_weights;
      // Perform the integration over the cell for both basis functions
      const auto b1 = [&](double x) { return (x - a) / h; };
      const auto b2 = [&](double x) { return 1. - b1(x); };
      for (int k = 0; k < num_quad_points; ++k) {
        rhs[i] += loc_quad_weights[k] * b2(loc_quad_points[k]) *
                  f(loc_quad_points[k]);
        rhs[i + 1] += loc_quad_weights[k] * b1(loc_quad_points[k]) *
                      f(loc_quad_points[k]);
      }
    }

    // Enforce zero dirichlet boundary conditions
    for (long k = 0; k < A.outerSize(); ++k) {
      for (Eigen::SparseMatrix<double>::InnerIterator it(A, k); it; ++it) {
        const int row = it.row();
        const int col = it.col();
        if ((row == 0 && col == 0) || (row == M && col == M)) {
          it.valueRef() = 1;
        } else if (row == 0 || row == M || col == 0 || col == M) {
          it.valueRef() = 0;
        }
      }
    }
    // Set the boundary values to zero
    rhs[0] = 0;
    rhs[M] = 0;

    // Solve the resulting linear system
    Eigen::SparseLU<Eigen::SparseMatrix<double>> solver(A);
    const Eigen::VectorXd sol = solver.solve(rhs);

    // Compute the norms and store them in the results matrix
    double norm_max = 0;
    double norm_H1_squared = 0;
    double norm_L2_squared = 0;
    for (int i = 0; i < M; ++i) {
      const double a = static_cast<double>(i) / M;
      const double b = static_cast<double>(i + 1) / M;
      const Eigen::VectorXd loc_quad_points =
          Eigen::VectorXd::Constant(num_quad_points, a) + h * quad_points;
      const Eigen::VectorXd loc_quad_weights = h * quad_weights;

      // The approximate solution on the current cell
      const auto u_h = [&](double x) {
        return sol[i + 1] * (x - a) / h + sol[i] * (1. - (x - a) / h);
      };
      // The gradient of the approximate solution on the current cell
      const auto u_h_grad = [&](double /*x*/) {
        return (sol[i + 1] - sol[i]) / h;
      };
      // The difference of the approximate and the exact solution
      const auto diff = [&](double x) { return u_h(x) - u(x); };
      // The difference in the gradient of the approximate and the exact
      // solution
      const auto diff_grad = [&](double x) { return u_h_grad(x) - u_grad(x); };

      // Compute the max norm by evaluating the functions on a fine grid
      norm_max =
          std::max(norm_max, Eigen::ArrayXd::LinSpaced(10 * M_max / M, a, b)
                                 .unaryExpr(diff)
                                 .abs()
                                 .maxCoeff());
      // Compute the H1 and L2 norms by integrating using a numerical quadrature
      for (int k = 0; k < num_quad_points; ++k) {
        norm_H1_squared += loc_quad_weights[k] * diff_grad(loc_quad_points[k]) *
                           diff_grad(loc_quad_points[k]);
        norm_L2_squared += loc_quad_weights[k] * diff(loc_quad_points[k]) *
                           diff(loc_quad_points[k]);
      }
    }
    results((M / dM) - 1, 0) = M;
    results((M / dM) - 1, 1) = norm_max;
    results((M / dM) - 1, 2) = std::sqrt(norm_H1_squared);
    results((M / dM) - 1, 3) = std::sqrt(norm_L2_squared);
  }

  // Output the resulting errors to a file
  const static Eigen::IOFormat CSVFormat(Eigen::StreamPrecision,
                                         Eigen::DontAlignCols, ", ", "\n");
  std::ofstream file;
  file.open(output_file);
  file << results.format(CSVFormat);
  file.close();

  return 0;
}


#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Suites
#include <boost/test/unit_test.hpp>
 #include"basis.hpp"
#include"operators.hpp"
#include"timeev.hpp"
#include"diag.hpp"
#include "files.hpp"
using namespace boost::unit_test;
using boost::unit_test_framework::test_suite;
using namespace Many_Body;
BOOST_AUTO_TEST_SUITE(timeevesting)
BOOST_AUTO_TEST_CASE(timeev)
{
  {
  size_t numberOfSteps=10;
   const size_t L=4;
   ElectronBasis<L> e(2);
   //std::cout << e << std::endl;
   // Eigen::MatrixXd AA = Eigen::MatrixXd::Random(e.dim, e.dim);
   // 	 Eigen::MatrixXd H = AA + AA.transpose();
        Operators::Mat H= Operators::NumberOperator(e)+Operators::EKinOperator(e);
   Eigen::VectorXcd inistate(e.dim);

   inistate.setZero();
   inistate[0]=1;
   Eigen::VectorXd eigenVals(e.dim);

   Operators::Mat O(e.dim, e.dim);
    O.setZero();
    O.coeffRef(1, 1)=0.5;
    O.coeffRef(2, 2)=0.5;

    // HAmiltonian =H
   Eigen::MatrixXd HH=Eigen::MatrixXd(H);
   // Eigen::MatrixXd HH2=Eigen::MatrixXd(H);

   Many_Body::diag(HH, eigenVals);

   double dt= 5;

   Eigen::MatrixXcd evExp=TimeEv::EigenvalExponent(eigenVals, dt);
   Eigen::MatrixXcd cEVec=HH.cast<std::complex<double>>();
   Eigen::VectorXd outputTime(numberOfSteps);
   Eigen::VectorXd outputVals(numberOfSteps);
       Eigen::VectorXd outputVals2(numberOfSteps);
       Eigen::VectorXcd newIn=inistate;
              Eigen::VectorXcd newIn2=inistate;
           for (size_t i = 0; i < numberOfSteps; ++i)
       {

       	 TimeEv::timeev_exact(newIn, cEVec, evExp);
  	 TimeEv::timeev_lanzcos(newIn2, H, 3, dt);
  	 std::complex<double> c=(newIn.adjoint()*(O*newIn))(0);
  	 std::complex<double> c2=(newIn2.adjoint()*(O*newIn2))(0);

  			// 	outputVals(i)=real(c);
  			// 	outputVals2(i)=real(c2);
        		// outputTime(i)=i*dt;

  	 BOOST_CHECK(std::abs(real(c2)-real(c))<Many_Body::err);
        }

      // Many_Body::ToFile(outputTime, outputVals, "timetestexact.dat", numberOfSteps);
      // Many_Body::ToFile(outputTime, outputVals2, "timetestexact2.dat", numberOfSteps);
     // Eigen::VectorXd q(numberOfSteps);
       }

	   {
  size_t numberOfSteps=2;
   const size_t L=4;
   ElectronBasis<L> e(2);
   // Operators::Mat H= Operators::NumberOperator(e)+Operators::EKinOperator(e);
   //std::cout << e << std::endl;
   //   Eigen::MatrixXd HH=Eigen::MatrixXd(H);
    Eigen::MatrixXcd AA = Eigen::MatrixXcd::Random(e.dim, e.dim);
   Eigen::MatrixXcd H = AA.adjoint()*AA;
Eigen::MatrixXcd HH=Eigen::MatrixXcd(H);
   Eigen::VectorXcd inistate=Eigen::VectorXcd::Random(e.dim);
   inistate=inistate/inistate.norm();

   Eigen::VectorXd eigenVals(e.dim);
   // Eigen::MatrixXcd BB = Eigen::MatrixXcd::Random(e.dim, e.dim);
   // Eigen::MatrixXcd B = BB.adjoint()*BB;
  Operators::Mat B(e.dim, e.dim);
    B.setZero();
    B.coeffRef(1, 1)=0.5;
    B.coeffRef(2, 2)=0.5;

    //Eigen::MatrixXcd HH=Eigen::MatrixXcd(H);

   Many_Body::diag(HH, eigenVals);

   double dt= 5;

	   Eigen::MatrixXcd cEVec=HH.cast<std::complex<double>>();

   Eigen::MatrixXcd evExp=TimeEv::EigenvalExponent(eigenVals, dt);

   Eigen::VectorXd outputTime(numberOfSteps);
   Eigen::VectorXd outputVals(numberOfSteps);
   Eigen::VectorXd outputVals2(numberOfSteps);
   Eigen::VectorXcd newIn=inistate;
   Eigen::VectorXcd newIn2=inistate;
           for (size_t i = 0; i < numberOfSteps; ++i)
       {

       	 TimeEv::timeev_exact(newIn, cEVec, evExp);
	 TimeEv::timeev_lanzcos(newIn2, H, e.dim, dt);
	 std::complex<double> c=(newIn.adjoint()*(B*newIn))(0);
	 std::complex<double> c2=(newIn2.adjoint()*(B*newIn2))(0);

	 	 BOOST_CHECK(std::abs(real(c2)-real(c))<0.001);
        }

       }
}

BOOST_AUTO_TEST_SUITE_END()
// EOF


/* ---------------------------------------------------------------------
 *
 * Copyright (C) 1999 - 2019 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE.md at
 * the top level of the deal.II distribution.
 *
 * ---------------------------------------------------------------------
 *
 * based on deal.II step-1
 */

#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>

#include <cmath>
#include <fstream>
#include <iostream>

using namespace dealii;

std::tuple<int, int, int>
grid_parameters(const Triangulation<2> &tria)
{
  return std::make_tuple(tria.n_levels(),
                         tria.n_cells(),
                         tria.n_active_cells());
}

void
first_grid()
{
  Triangulation<2> triangulation;

  GridGenerator::hyper_cube(triangulation);
  std::cout << "Number of original vertices:" << triangulation.n_vertices()
            << std::endl;

  triangulation.refine_global(4);

  std::cout << "Number of original vertices after 4 refinements:"
            << triangulation.n_vertices() << std::endl;

  {
    std::ofstream out("grid-1.svg");
    GridOut       grid_out;
    grid_out.write_svg(triangulation, out);
    std::cout << "Grid written to grid-1.svg" << std::endl;
  }

  {
    std::ofstream out("grid-1.vtk");
    GridOut       grid_out;
    grid_out.write_vtk(triangulation, out);
    std::cout << "Grid written to grid-1.vtk" << std::endl;
  }
  auto params = grid_parameters(triangulation);
  std::cout << std::get<0>(params) << " " << std::get<1>(params) << "  "
            << std::get<2>(params) << std::endl;
}

void
second_grid()
{
  Triangulation<2> triangulation;

  const Point<2> center(1, 0);
  const double   inner_radius = 0.5, outer_radius = 1.0;
  GridGenerator::hyper_shell(
    triangulation, center, inner_radius, outer_radius, 10);

  triangulation.reset_all_manifolds();
  for (unsigned int step = 0; step < 5; ++step)
    {
      std::ofstream out("grid-2-" + std::to_string(step) + ".vtk");
      GridOut       grid_out;
      grid_out.write_vtk(triangulation, out);

      for (auto &cell : triangulation.active_cell_iterators())
        {
          for (const auto v : cell->vertex_indices())
            {
              const double distance_from_center =
                center.distance(cell->vertex(v));

              if (std::fabs(distance_from_center - inner_radius) <=
                  1e-6 * inner_radius)
                {
                  cell->set_refine_flag();
                  break;
                }
            }
        }

      triangulation.execute_coarsening_and_refinement();
    }
  {
    std::ofstream out("grid-2.svg");
    GridOut       grid_out;
    grid_out.write_svg(triangulation, out);
    std::cout << "Grid written to grid-2.svg" << std::endl;
  }
  auto params = grid_parameters(triangulation);
  std::cout << std::get<0>(params) << " " << std::get<1>(params) << "  "
            << std::get<2>(params) << std::endl;
}

void
third_grid()
{
  Triangulation<2> triangulation;
  GridGenerator::hyper_L(triangulation);
  std::cout << "Number of original vertices:" << triangulation.n_vertices()
            << std::endl;

  triangulation.refine_global(1);

  std::cout << "Number of original vertices after 1 refinement:"
            << triangulation.n_vertices() << std::endl;

  {
    std::ofstream out("grid-3.vtk");
    GridOut       grid_out;
    grid_out.write_vtk(triangulation, out);
    std::cout << "Grid written to grid-3.vtk" << std::endl;
  }

  const Point<2> corner(0, 0);
  for (unsigned int step = 0; step < 5; ++step)
    {
      std::ofstream out("grid-3-" + std::to_string(step) + ".vtk");
      GridOut       grid_out;
      grid_out.write_vtk(triangulation, out);

      for (auto &cell : triangulation.active_cell_iterators())
        {
          for (const auto v : cell->vertex_indices())
            {
              const double distance_from_center =
                corner.distance(cell->vertex(v));

              if (std::fabs(distance_from_center) <= 1. / 3.)
                {
                  cell->set_refine_flag();
                  break;
                }
            }
        }

      triangulation.execute_coarsening_and_refinement();
    }

  auto params = grid_parameters(triangulation);
  std::cout << std::get<0>(params) << " " << std::get<1>(params) << "  "
            << std::get<2>(params) << std::endl;
}

void
circle_grid()
{
  Triangulation<2> triangulation;
  GridGenerator::hyper_ball<2>(triangulation);
  // triangulation.set_all_manifold_ids(0);
  triangulation.set_manifold(0, SphericalManifold<2>());
  const Point<2> mesh_center;
  for (const auto &cell : triangulation.active_cell_iterators())
    if (mesh_center.distance(cell->center()) > cell->diameter() / 10)
      cell->set_all_manifold_ids(0);
  triangulation.refine_global(2);
  std::ofstream out("circle.vtk");
  GridOut       grid_out;
  grid_out.write_vtk(triangulation, out);
}

void
torus_grid()
{
  Triangulation<2, 3> triangulation;
  GridGenerator::torus<2, 3>(triangulation, 4, 1);
  triangulation.refine_global(2);
  std::ofstream out("torus.vtk");
  GridOut       grid_out;
  grid_out.write_vtk(triangulation, out);
}

int
main()
{
  first_grid();
  second_grid();
  third_grid();
  circle_grid();
  torus_grid();
}


///////////////////////////////////////////////////////////////////////////////
//  Copyright Christopher Kormanyos 2015.
//  Copyright Nikhar Agrawal 2015.
//  Copyright Paul Bristow 2015.
//  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
//!\brief Tests for the hyperbolic arccosine function of (fixed_point) for a small digit range.

#include <cmath>

#define BOOST_TEST_MODULE test_negatable_func_hyperbolic_arccosine_small
#define BOOST_LIB_DIAGNOSTIC

#include <boost/fixed_point/fixed_point.hpp>
#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_negatable_func_hyperbolic_arccosine_small)
{
  typedef boost::fixed_point::negatable<7, -24> fixed_point_type;
  typedef fixed_point_type::float_type          float_point_type;

  const fixed_point_type tol = ldexp(fixed_point_type(1), fixed_point_type::resolution + 4);

  using std::acosh;

  // Check positive arguments.
  for(int i = 0; i < 16; ++i)
  {
    const fixed_point_type x = acosh(1 + (fixed_point_type(i) / fixed_point_type(3.1415926535897932385L)));
    const float_point_type y = acosh(1 + (float_point_type(i) / float_point_type(3.1415926535897932385L)));

    BOOST_CHECK_CLOSE_FRACTION(x, fixed_point_type(y), tol);
  }

  fixed_point_type x;
  float_point_type y;

  // Check a positive argument clost to 1.
  x = acosh(1 + (1 / (fixed_point_type(97) / 10)));
  y = acosh(1 + (1 / (float_point_type(97) / 10)));

  BOOST_CHECK_CLOSE_FRACTION(x, fixed_point_type(y), tol);

  // Check an invalid zero argument.
  x = acosh(0);
  y = float_point_type(0);

  BOOST_CHECK_CLOSE_FRACTION(x, fixed_point_type(y), tol);

  // Check an invalid argument that lies between 0 < x < 1.
  x = acosh(fixed_point_type(1) / 2);
  y = float_point_type(0);

  BOOST_CHECK_CLOSE_FRACTION(x, fixed_point_type(y), tol);
}


/*
 * Copyright (c) 2013-2016 Masahide Kashiwagi (kashi@waseda.jp)
 */

#ifndef STROBOMAP_HPP
#define STROBOMAP_HPP

#include <stdexcept>
#include <kv/ode-nv.hpp>
#include <kv/ode-autodif-nv.hpp>
#include <kv/ode-maffine.hpp>
#ifdef USE_MAFFINE2
#include <kv/ode-maffine2.hpp>
#endif
#include <kv/ode-param.hpp>

namespace kv {

namespace ub = boost::numeric::ublas;

// Generate function object of strobomap
// using function object of r.h.s of differential equation.
// Generated function object can receive
//   vector<T>,
//   vector< autodif<T> >,
//   vector< interval<T> >,
//   vector< affine<T> >,
//   vector< autodif< interval<T> > >
// as argument. In each case,
//   odelong_nv in ode-nv.hpp,
//   odelong_nv in ode-autodif-nv.hpp,
//   odelong_maffine in ode-maffine.hpp (interval version)
//   odelong_maffine in ode-maffine.hpp (affine version),
//   odelong_maffine in ode-maffine.hpp (autodif version)
// is called inside.
// (If -DUSE_MAFFINE2 then ode-maffine2.hpp is used instead.)

template <class F, class T> class StroboMap {
	public:
	F f;
	interval<T> start, end;
	ode_param<T> p;

	StroboMap(F f, interval<T> start, interval<T> end, ode_param<T> p = ode_param<T>())
	: f(f), start(start), end(end), p(p) {}

	ub::vector<T> operator() (const ub::vector<T>& x){
		ub::vector<T> result;

		result = x;

		odelong_nv(f, result, mid(start), mid(end), p);

		return result;
	}

	ub::vector< autodif<T> > operator() (const ub::vector< autodif<T> >& x){
		ub::vector< autodif<T> > result;

		result = x;

		odelong_nv(f, result, mid(start), mid(end), p);

		return result;
	}

	ub::vector< interval<T> > operator() (const ub::vector< interval<T> >& x){
		ub::vector< interval<T> > result;
		interval<T> end2;
		int r;

		result = x;
		end2 = end;

		#ifdef USE_MAFFINE2
		r = odelong_maffine2(f, result, start, end2, p);
		#else
		r = odelong_maffine(f, result, start, end2, p);
		#endif

		if (r != 2) {
			throw std::domain_error("StroboMap(): cannot calculate validated solution.");
		}

		return result;
	}

	ub::vector< affine<T> > operator() (const ub::vector< affine<T> >& x){
		ub::vector< affine<T> > result;
		interval<T> end2;
		int r;

		result = x;
		end2 = end;

		#ifdef USE_MAFFINE2
		r = odelong_maffine2(f, result, start, end2, p);
		#else
		r = odelong_maffine(f, result, start, end2, p);
		#endif

		if (r != 2) {
			throw std::domain_error("StroboMap(): cannot calculate validated solution.");
		}

		return result;
	}

	ub::vector< autodif< interval<T> > > operator() (const ub::vector< autodif< interval<T> > >& x){
		ub::vector< autodif< interval<T> > > result;
		interval<T> end2;
		int r;

		result = x;
		end2 = end;

		r = odelong_maffine(f, result, start, end2, p);
		if (r != 2) {
			throw std::domain_error("StroboMap(): cannot calculate validated solution.");
		}

		return result;
	}
};

// Generate function object of "x-f(x)" from function object of f.

template <class F> class FixedPoint {
	public:
	F f;
	FixedPoint(F f) : f(f) {}
	template <class T> ub::vector<T> operator() (const ub::vector<T>& x){
		return x - f(x);
	}
};

// Generate function object for shooting method of two point
// boundary value problem from 2-variable strobomap.
//   boundary condition:
//     x(start_index) = start_value, x(end_index) = end_value
//   unknown variable:
//     x(index != start_index)
// Solve ODE from initial value (start_value, unknown) and try to
// satisfy x(end_index) = end_value by changing unknown.

template <class F, class TV> class Shooting_TPBVP {
	public:
	F f;
	TV start_value, end_value;
	int start_index, end_index;
	int variable_index;

	Shooting_TPBVP(F f, TV start_value, TV end_value, int start_index, int end_index) : f(f) , start_value(start_value), end_value(end_value), start_index(start_index), end_index(end_index) {
		variable_index = 1 - start_index;
	}

	// mid_ifnecessary<T1,T2>(x) returns x if T2 is convertible to T1,
	// and returns mid(x) if impossoble.

	#include <boost/utility/enable_if.hpp>

	template <class T1, class T2> T1 inline static mid_ifnecessary(T2& x, typename boost::enable_if_c< convertible<T2, T1>::value >::type* =0) {
		return T1(x);
	}

	template <class T1, class T2> T1 inline static mid_ifnecessary(T2& x, typename boost::enable_if_c< ! convertible<T2, T1>::value >::type* =0) {
		return T1(mid(x));
	}

	template <class T> ub::vector<T> operator() (const ub::vector<T>& s) {
		ub::vector<T> x, y, r;
		x.resize(2);
		r.resize(1);
		x(variable_index) = s(0);
		x(start_index) = mid_ifnecessary<T,TV>(start_value);
		y = f(x);
		r(0) = y(end_index) - mid_ifnecessary<T,TV>(end_value);
		return r;
	}
};

} // namespace kv

#endif // STROBOMAP_HPP


#include "conex/cone_program.h"
#include "conex/constraint.h"
#include "conex/dense_lmi_constraint.h"
#include "conex/linear_constraint.h"
#include "conex/test/test_util.h"
#include <Eigen/Dense>

using DenseMatrix = Eigen::MatrixXd;

namespace conex {
void TestSDP(int i) {
  SolverConfiguration config;
  int n = 300;
  int m = 50;
  auto constraints2 = GetRandomDenseMatrices(n, m);

  DenseMatrix affine2 = Eigen::MatrixXd::Identity(n, n);
  DenseLMIConstraint LMI{n, constraints2, affine2};

  Program prog(m);
  DenseMatrix y(m, 1);
  prog.AddConstraint(LMI);

  auto b = GetFeasibleObjective(&prog);
  Solve(b, prog, config, y.data());
}
}  // namespace conex

int main() {
  for (int i = 0; i < 1; i++) {
    conex::TestSDP(i);
  }
  return 0;
}


#include <cstdlib>
#include <iostream>
#include <complex>
#include <boost/numeric/ublas/matrix.hpp>
#include <Eigen/Core>
#include <boost/numeric/bindings/ublas/matrix.hpp>
#include <boost/numeric/bindings/eigen/matrix.hpp>
#include <boost/numeric/bindings/blas/level3.hpp>
#include <boost/numeric/bindings/trans.hpp>
#include <boost/numeric/bindings/conj.hpp>
#include "print.hpp"
#include "random.hpp"

namespace ublas=boost::numeric::ublas;
namespace blas=boost::numeric::bindings::blas;

int main(int argc, char *argv[]) {
  {
    typedef std::complex<double> complex;
    typedef ublas::matrix<complex, ublas::column_major> matrix;
    typedef matrix::size_type size_type;
    rand_normal<complex>::reset();
    size_type m=6, k=7, n=8;
    matrix A(m, k);
    matrix B(k, n);
    matrix C(m, n);
    for (size_type j=0; j<k; ++j)
      for (size_type i=0; i<m; ++i)
 	A(i, j)=rand_normal<complex>::get();
    for (size_type j=0; j<n; ++j)
      for (size_type i=0; i<k; ++i)
 	B(i, j)=rand_normal<complex>::get();
    for (size_type j=0; j<n; ++j)
      for (size_type i=0; i<m; ++i)
 	C(i, j)=rand_normal<complex>::get();
    matrix A_t(ublas::trans(A));
    matrix B_t(ublas::trans(B));
    matrix A_h(ublas::conj(A_t));
    matrix B_h(ublas::conj(B_t));
    complex alpha(rand_normal<complex>::get());
    complex beta(rand_normal<complex>::get());
    matrix C1(alpha*ublas::prod(A, B)+beta*C);
    matrix C2(C);
    blas::gemm(alpha, A, B, beta, C2);
    matrix C3(C);
    blas::gemm(alpha, blas::trans(A_t), blas::trans(B_t), beta, C3);
    matrix C4(C);
    blas::gemm(alpha, blas::conj(A_h), blas::conj(B_h), beta, C4);
    std::cout << "testing boost::ublas containers\n"
     	      << "using ublas:\n" << print_mat(C1) << '\n'
     	      << "using blas:\n" << print_mat(C2) << '\n'
     	      << "using blas (transposed):\n" << print_mat(C3) << '\n'
     	      << "using blas (hermitian transposed):\n" << print_mat(C4) << '\n'
	      << '\n';
  }
  {
    typedef std::complex<double> complex;
    typedef Eigen::Matrix<complex, Eigen::Dynamic, Eigen::Dynamic> matrix;
    typedef int size_type;
    rand_normal<complex>::reset();
    size_type m=6, k=7, n=8;
    matrix A(m, k);
    matrix B(k, n);
    matrix C(m, n);
    for (size_type j=0; j<k; ++j)
      for (size_type i=0; i<m; ++i)
 	A(i, j)=rand_normal<complex>::get();
    for (size_type j=0; j<n; ++j)
      for (size_type i=0; i<k; ++i)
 	B(i, j)=rand_normal<complex>::get();
    for (size_type j=0; j<n; ++j)
      for (size_type i=0; i<m; ++i)
 	C(i, j)=rand_normal<complex>::get();
    matrix A_t(A.transpose());
    matrix B_t(B.transpose());
    matrix A_h(A.adjoint());
    matrix B_h(B.adjoint());
    complex alpha(rand_normal<complex>::get());
    complex beta(rand_normal<complex>::get());
    matrix C1(alpha*A*B+beta*C);
    matrix C2(C);
    blas::gemm(alpha, A, B, beta, C2);
    matrix C3(C);
    blas::gemm(alpha, blas::trans(A_t), blas::trans(B_t), beta, C3);
    matrix C4(C);
    blas::gemm(alpha, blas::conj(A_h), blas::conj(B_h), beta, C4);
    std::cout << "testing Eigen containers\n"
     	      << "using Eigen:\n" << print_mat(C1) << '\n'
     	      << "using blas:\n" << print_mat(C2) << '\n'
     	      << "using blas (transposed):\n" << print_mat(C3) << '\n'
     	      << "using blas (hermitian transposed):\n" << print_mat(C4) << '\n'
    	      << '\n';
  }
  return EXIT_SUCCESS;
}


#include <blitz/tinyvec-et.h>
#include <blitz/tinymat.h>

using namespace blitz;

template<typename T>
void optimizationSink(T&);

void foo()
{
    TinyMatrix<float,3,3> A;
    TinyVector<float,3> b, c;

    optimizationSink(A);
    optimizationSink(b);

    c = product(A,b);

    optimizationSink(c);
}


/* test_fisher_f_distribution.cpp
 *
 * Copyright Steven Watanabe 2011
 * 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)
 *
 * $Id$
 *
 */

#include <boost/random/fisher_f_distribution.hpp>
#include <limits>

#define BOOST_RANDOM_DISTRIBUTION boost::random::fisher_f_distribution<>
#define BOOST_RANDOM_ARG1 m
#define BOOST_RANDOM_ARG2 n
#define BOOST_RANDOM_ARG1_DEFAULT 1.0
#define BOOST_RANDOM_ARG2_DEFAULT 1.0
#define BOOST_RANDOM_ARG1_VALUE 7.5
#define BOOST_RANDOM_ARG2_VALUE 0.25

#define BOOST_RANDOM_DIST0_MIN 0.0
#define BOOST_RANDOM_DIST0_MAX (std::numeric_limits<double>::infinity)()
#define BOOST_RANDOM_DIST1_MIN 0.0
#define BOOST_RANDOM_DIST1_MAX (std::numeric_limits<double>::infinity)()
#define BOOST_RANDOM_DIST2_MIN 0.0
#define BOOST_RANDOM_DIST2_MAX (std::numeric_limits<double>::infinity)()

#define BOOST_RANDOM_TEST1_PARAMS (1.0, 2.1)
#define BOOST_RANDOM_TEST2_PARAMS (10.0, 10.0)

#include "test_distribution.ipp"


//=======================================================================
// 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 local_search_multi_solution_test.cpp
 * @brief this is implementation using lagrangian relaxation and c++11 lambdas
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2013-02-04
 */

#include "test_utils/logger.hpp"

#include "paal/local_search/local_search.hpp"
#include "paal/local_search/search_components.hpp"
#include "paal/data_structures/combine_iterator.hpp"
#include "paal/utils/irange.hpp"

#include <boost/test/unit_test.hpp>

#include <vector>
#include <string>
#include <cstdlib>
#include <iomanip>

using namespace paal;

struct value_diff {
    value_diff(double &value, double diff) : m_value(value), m_diff(diff) {}

    double &m_value;
    double m_diff;
};

struct make_value_diff {
    value_diff operator()(double &value, double diff) const {
        return value_diff{ value, diff };
    }
};

BOOST_AUTO_TEST_CASE(local_search_multi_lamdas_first_improving_test) {
    typedef double SolutionElement;
    typedef std::vector<SolutionElement> Solution;
    typedef SolutionElement Move;
    const int DIM = 3;
    const double LOWER_BOUND = 0.;
    const double UPPER_BOUND = 1.;

    // creating local search
    const std::vector<double> neighb{ .1, -.1, .01, -.01, .001, -.001 };
    std::vector<double> neighbCut(neighb.size());
    double G{ 1 };

    // components for vector
    auto f = [&](Solution & x) {
        double &x1(x[0]), &x2(x[1]), &x3(x[2]);
        return x1 * x2 + x2 * x3 + x3 * x1 - 3 * x1 * x2 * x3 +
               G * (2 - (x1 + x2 + x3));
    };

    auto normalize = [ = ](SolutionElement el) {
        return std::min(std::max(el, LOWER_BOUND), UPPER_BOUND);
    };

    auto getMoves = [&](Solution & s) {
        auto b = data_structures::make_combine_iterator(make_value_diff{}, s,
                                                        neighb);
        return boost::make_iterator_range(b, decltype(b) {});
    };

    auto gain = [&](Solution & s, value_diff vd) {
        auto old = vd.m_value;
        auto val = f(s);
        vd.m_value = normalize(vd.m_value + vd.m_diff);
        auto valMove = f(s);
        vd.m_value = old;
        return valMove - val - 1e-6;
    };

    auto commit = [&](Solution &, value_diff vd) {
        vd.m_value = normalize(vd.m_value + vd.m_diff);
        return true;
    };

    auto ls = [ = ](Solution & x) {
        x = { .3, .3, .3 };
        first_improving(
            x, local_search::make_search_components(getMoves, gain, commit));
    };

    // components for G.
    std::vector<double> neighbCutG(neighb.size());
    std::vector<double> x(DIM, 0);
    first_improving(
        x, local_search::make_search_components(getMoves, gain, commit));
    double best = f(x);

    auto getMovesG = [&](const double g)->const std::vector<double> & {
        for (int j : paal::irange(neighb.size())) {
            neighbCutG[j] = neighb[j] + g;
        }
        return neighbCutG;
    };

    auto gainG = [&](double, double g) {
        std::vector<double> x(DIM, 0);
        auto old = G;
        G = g;
        ls(x);
        auto newRes = f(x);
        G = old;
        return best - newRes - 1e-6;
    };

    auto commitG = [&](double & s, double u) {
        assert(G == s);
        s = u;
        best = f(x);
        return true;
    };

    first_improving(
        G, local_search::make_search_components(getMovesG, gainG, commitG));

    ls(x);

    // printing
    LOG(std::setprecision(10));
    LOGLN("G = " << G);
    G = 0;
    LOG("f(");
    LOG_COPY_RANGE_DEL(x, ",");
    // TODO it would be interesting how G depends on starting point ( (0.3, 0.3,
    // 0.3) now)
    LOGLN(") = \t" << f(x));
    LOGLN("approximation " << 2. / f(x));
}


#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <CGAL/Random.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Surface_mesh_shortest_path.h>

#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>

#include <cstdlib>
#include <iostream>
#include <fstream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> Triangle_mesh;
typedef CGAL::Surface_mesh_shortest_path_traits<Kernel, Triangle_mesh> Traits;
typedef CGAL::Surface_mesh_shortest_path<Traits> Surface_mesh_shortest_path;
typedef Traits::Barycentric_coordinates Barycentric_coordinates;
typedef boost::graph_traits<Triangle_mesh> Graph_traits;
typedef Graph_traits::vertex_iterator vertex_iterator;
typedef Graph_traits::face_iterator face_iterator;
typedef Graph_traits::vertex_descriptor vertex_descriptor;
typedef Graph_traits::face_descriptor face_descriptor;
typedef Graph_traits::halfedge_descriptor halfedge_descriptor;

// A model of SurfacemeshShortestPathVisitor storing simplicies
// using boost::variant
struct Sequence_collector
{
  typedef boost::variant< vertex_descriptor,
                         std::pair<halfedge_descriptor,double>,
                         std::pair<face_descriptor, Barycentric_coordinates> > Simplex;
  std::vector< Simplex > sequence;

  void operator()(halfedge_descriptor he, double alpha)
  {

    sequence.push_back( std::make_pair(he, alpha) );
  }

  void operator()(vertex_descriptor v)
  {
    sequence.push_back( v );
  }

  void operator()(face_descriptor f, Barycentric_coordinates alpha)
  {
    sequence.push_back( std::make_pair(f, alpha) );
  }
};

// A visitor to print what a variant contains using boost::apply_visitor
struct Print_visitor : public boost::static_visitor<> {
  int i;
  Triangle_mesh& g;

  Print_visitor(Triangle_mesh& g) :i(-1), g(g) {}

  void operator()(vertex_descriptor v)
  {
    std::cout << "#" << ++i << " : Vertex : " << get(boost::vertex_index, g)[v] << "\n";
  }

  void operator()(const std::pair<halfedge_descriptor,double>& h_a)
  {
    std::cout << "#" << ++i << " : Edge : " << get(CGAL::halfedge_index, g)[h_a.first] << " , ("
                                            << 1.0 - h_a.second << " , "
                                            << h_a.second << ")\n";
  }

  void operator()(const std::pair<face_descriptor, Barycentric_coordinates>& f_bc)
  {
    std::cout << "#" << ++i << " : Face : " << get(CGAL::face_index, g)[f_bc.first] << " , ("
                                            << f_bc.second[0] << " , "
                                            << f_bc.second[1] << " , "
                                            << f_bc.second[2] << ")\n";
  }
};

int main(int argc, char** argv)
{
  const char* filename = (argc>1) ? argv[1] : "data/elephant.off";

  Triangle_mesh tmesh;
  if(!CGAL::read_polygon_mesh(filename, tmesh) ||
     !CGAL::is_triangle_mesh(tmesh))
  {
    std::cerr << "Invalid input file." << std::endl;
    return EXIT_FAILURE;
  }

  // pick up a random face
  const unsigned int randSeed = argc > 2 ? boost::lexical_cast<unsigned int>(argv[2]) : 7915421;
  CGAL::Random rand(randSeed);
  const int target_face_index = rand.get_int(0, static_cast<int>(num_faces(tmesh)));
  face_iterator face_it = faces(tmesh).first;
  std::advance(face_it,target_face_index);
  // ... and define a barycentric coordinates inside the face
  Barycentric_coordinates face_location = {{0.25, 0.5, 0.25}};

  // construct a shortest path query object and add a source point
  Surface_mesh_shortest_path shortest_paths(tmesh);
  shortest_paths.add_source_point(*face_it, face_location);

  // pick a random target point inside a face
  face_it = faces(tmesh).first;
  std::advance(face_it, rand.get_int(0, static_cast<int>(num_faces(tmesh))));

  // collect the sequence of simplicies crossed by the shortest path
  Sequence_collector sequence_collector;
  shortest_paths.shortest_path_sequence_to_source_points(*face_it, face_location, sequence_collector);

  // print the sequence using the visitor pattern
  Print_visitor print_visitor(tmesh);
  for (size_t i = 0; i < sequence_collector.sequence.size(); ++i)
    boost::apply_visitor(print_visitor, sequence_collector.sequence[i]);

  return 0;
}


//==============================================================================
//         Copyright 2015 J.T. Lapreste
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#include <nt2/exponential/include/functions/significants.hpp>

#include <boost/dispatch/functor/meta/call.hpp>
#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <boost/simd/sdk/simd/io.hpp>
#include <boost/simd/sdk/simd/native.hpp>
#include <complex>
#include <nt2/sdk/complex/complex.hpp>
#include <nt2/sdk/complex/dry.hpp>
#include <nt2/sdk/unit/tests/ulp.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <boost/simd/sdk/config.hpp>
#include <nt2/include/functions/splat.hpp>

#include <nt2/include/constants/mone.hpp>
#include <nt2/include/constants/one.hpp>
#include <nt2/include/constants/zero.hpp>
#include <nt2/include/constants/inf.hpp>
#include <nt2/include/constants/minf.hpp>
#include <nt2/include/constants/nan.hpp>

NT2_TEST_CASE_TPL ( significants,  NT2_SIMD_REAL_TYPES)
{
  using nt2::significants;
  using nt2::tag::significants_;
  using boost::simd::native;
  typedef BOOST_SIMD_DEFAULT_EXTENSION  ext_t;
  typedef std::complex<T> cT;
  typedef native<cT,ext_t>                cvT;

  // specific values tests
#ifndef BOOST_SIMD_NO_INVALIDS
  NT2_TEST_ULP_EQUAL(significants(nt2::Inf<cvT>(), 1), nt2::Inf<cvT>(), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::Minf<cvT>(), 1), nt2::Minf<cvT>(), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::Nan<cvT>(), 1), nt2::Nan<cvT>(), 0.5);
#endif
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(25.34)),  1), nt2::splat<cvT>(30), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(25.34)),  2), nt2::splat<cvT>(25), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(25.34)),  3), nt2::splat<cvT>(25.3), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(25.34)),  4), nt2::splat<cvT>(25.34), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(-25.34)), 1), nt2::splat<cvT>(-30), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(-25.34)), 2), nt2::splat<cvT>(-25), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(-25.34)), 3), nt2::splat<cvT>(-25.3), 0.5);
  NT2_TEST_ULP_EQUAL(significants(nt2::splat<cvT>(cT(-25.34)), 4), nt2::splat<cvT>(-25.34), 0.5);
}


//    Copyright 2017 Rainer Gemulla
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
/** \file
 *
 * Illustrates matrix factorization with distributed Gaussian non-negative matrix factorization.
 * We first create factors and then a data matrix
 * from these factors. THis process ensures that we know the best factorization of the input.
 * We then try to reconstruct the factors.
 */
#include <iostream>

#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/binomial.hpp>
#include <boost/random/uniform_real.hpp>

#include <util/evaluation.h>
#include <util/io.h>

#include <mf/mf.h>

using namespace std;
using namespace mf;
using namespace rg;
using namespace boost::numeric::ublas;

log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

int main(int argc, char* argv[]) {
	boost::mpi::communicator& world = mfInit(argc, argv);

	// parameters for the factorization
	mf_size_type size1 = 10000;
	mf_size_type size2 = 10000;
	mf_size_type nnz = 1000000;
	double sigma = 1; // standard deviation
	mf_size_type r = 10;

	// parameters for ALS
	unsigned epochs = 20;
	SlLoss loss;
	mf_size_type testNnz = nnz/100;

	BalanceType type = BALANCE_L2;;
	BalanceMethod method = BALANCE_SIMPLE;

	// parameters for distribution
	int tasksPerRank = 2;
	mf_size_type blocks = world.size() * tasksPerRank;

	mfStart();

	if (world.rank() == 0) {
	#ifndef NDEBUG
		LOG4CXX_WARN(logger, "Warning: Debug mode activated (runtimes may be slow).");
	#endif
		// generate original factors by sampling from a uniform[0,1] distribution
		Random32 random; // note: this takes a default seed (not randomized!)
		DenseMatrix wIn(size1, r);
		DenseMatrixCM hIn(r, size2);
		generateRandom(wIn, random, boost::uniform_real<>(0,1));
		generateRandom(hIn, random, boost::uniform_real<>(0,1));

		// generate a sparse matrix by selecting random entries from the generated factors
		// and add small Gaussian noise
		SparseMatrix v;
		generateRandom(v, nnz, wIn, hIn, random);
		//addRandom(v, random, boost::normal_distribution<>(0, 0.1));
		LOG4CXX_INFO(logger, "Data matrix: "
			<< v.size1() << " x " << v.size2() << ", " << v.nnz() << " nonzeros");
		v.sort();
		LOG4CXX_INFO(logger, "Loss with original factors: " << loss((FactorizationData<>(v, wIn, hIn))));
		SparseMatrixCM vc;
		copyCm(v, vc);

		// create a test matrix (without noise)
		SparseMatrix vTest;
		generateRandom(vTest, testNnz, wIn, hIn, random);
		LOG4CXX_INFO(logger, "Test matrix: "
			<< v.size1() << " x " << v.size2() << ", " << vTest.nnz() << " nonzeros");

		// generate initial factors by sampling from a uniform[0,1] distribution
		DenseMatrix w(size1, r);
		DenseMatrixCM h(r, size2);
		generateRandom(w, random, boost::uniform_real<>(0.0, 1.0));
		generateRandom(h, random, boost::uniform_real<>(0.0, 1.0));

		// distribute the input matrices and test matrix
		DistributedSparseMatrix dv = distributeMatrix("V", blocks, 1, true, v);
		LOG4CXX_INFO(logger, "Distributed data matrix: "
				<< dv.blocks1() << " x " << dv.blocks2() << " blocks");
		DistributedSparseMatrixCM dvc = distributeMatrix("VC", 1, blocks, false, vc);
		LOG4CXX_INFO(logger, "Distributed data matrix (CM): "
				<< dvc.blocks1() << " x " << dvc.blocks2() << " blocks");
		DistributedSparseMatrix dvTest = distributeMatrix("Vtest", blocks, blocks, true, vTest);
		LOG4CXX_INFO(logger, "Distributed test matrix: "
				<< dvTest.blocks1() << " x " << dvTest.blocks2() << " blocks");
		DistributedDenseMatrix dw = distributeMatrix("W", blocks, 1, true, w);
		DistributedDenseMatrixCM dh = distributeMatrix("H", 1, blocks, false, h);
		LOG4CXX_INFO(logger, "Distributed factor matrices");

		// initialize
		DapFactorizationData<> data(dv, dw, dh, tasksPerRank, &dvc);
		DsgdFactorizationData<> testJob(dvTest, dw, dh, tasksPerRank);
		Trace trace;
		Timer t;

		// run GNMF to try to reconstruct the original factors
		t.start();
		dgnmf(data, epochs, trace, type, method, &testJob);
		t.stop();
		LOG4CXX_INFO(logger, "Total time: " << t);

		// write trace to an R file
		LOG4CXX_INFO(logger, "Writing trace to " << "/tmp/dgnmf-trace.R");
		trace.toRfile("/tmp/dgnmf-trace.R", "dgnmf");
	}

	mfStop();
	mfFinalize();

	return 0;
}


#ifndef MATHTOOLBOX_SOM_HPP
#define MATHTOOLBOX_SOM_HPP

#include <Eigen/Core>
#include <memory>

namespace mathtoolbox
{
    class DataNormalizer;

    class Som
    {
    public:
        /// \param data An n-by-m matrix representing m data points lying in an n-dimensional space.
        ///
        /// \param latent_num_dims The dimensionality of the latent (map) space. It should be either 1 or 2.
        Som(const Eigen::MatrixXd& data,
            const int              latent_num_dims      = 2,
            const int              resolution           = 10,
            const double           init_var             = 0.50,
            const double           min_var              = 0.01,
            const double           var_decreasing_speed = 20.0,
            const bool             normalize_data       = true);

        const Eigen::MatrixXd& GetLatentSpaceNodePositions() const { return m_latent_node_positions; }
        const Eigen::MatrixXd& GetLatentSpaceDataPositions() const { return m_Z; }

        Eigen::MatrixXd GetDataSpaceNodePositions() const;

        void Step();

    private:
        const int m_latent_num_dims;
        const int m_resolution;

        const double m_init_var;
        const double m_min_var;
        const double m_var_decreasing_speed;

        const bool m_normalize_data;

        /// \brief Grid node positions in the latent space.
        const Eigen::MatrixXd m_latent_node_positions;

        int m_iter_count;

        /// \brief Observed data points.
        Eigen::MatrixXd m_X;

        /// \brief Vector values on grid nodes.
        Eigen::MatrixXd m_Y;

        /// \brief Embeded data points.
        Eigen::MatrixXd m_Z;

        std::shared_ptr<const DataNormalizer> m_data_normalizer;

        /// \brief Perform normalization for the current data.
        void NormalizeData();

        /// \brief Perform initialization.
        ///
        /// \details Currently, only the random initialization strategy is implemented.
        void PerformInitialization();
    };
} // namespace mathtoolbox

#endif // MATHTOOLBOX_SOM_HPP