/**
 * @file   test_GraphSimplification.cpp
 * @brief  test graph simplification algorithms @ref limbo::algorithms::coloring::GraphSimplification
 * @author Yibo Lin
 * @date   May 19 01:15:09 2015
 */

#include <iostream>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/undirected_graph.hpp>
#include <limbo/algorithms/coloring/GraphSimplification.h>
#include <boost/version.hpp>
#if BOOST_VERSION <= 14601
#include <boost/graph/detail/is_same.hpp>
#else
#include <boost/type_traits/is_same.hpp>
#endif

using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
using std::pair;
using namespace boost;

/// @nowarn
// do not use setS, it does not compile for subgraph
// do not use custom property tags, it does not compile for most utilities
typedef adjacency_list<vecS, vecS, undirectedS,
		property<vertex_index_t, std::size_t, property<vertex_color_t, int> >,
		property<edge_index_t, std::size_t, property<edge_weight_t, int> >,
		property<graph_name_t, string> > graph_type;
typedef subgraph<graph_type> subgraph_type;
typedef property<vertex_index_t, std::size_t> VertexId;
typedef property<edge_index_t, std::size_t> EdgeID;
typedef graph_traits<graph_type>::vertex_descriptor vertex_descriptor;
typedef graph_traits<graph_type>::edge_descriptor edge_descriptor;
typedef property_map<graph_type, edge_weight_t>::type edge_weight_map_type;
typedef property_map<graph_type, vertex_color_t>::type vertex_color_map_type;
/// @endnowarn

/// test 1: a real graph from input
/// @param filename input file in graphviz format
void realGraph(string const& filename)
{
	ifstream in (filename.c_str());

	// the graphviz reader in boost cannot specify vertex_index_t
	// I have to create a temporary graph and then construct the real graph
	typedef adjacency_list<vecS, vecS, undirectedS,
			property<vertex_index_t, std::size_t, property<vertex_color_t, int, property<vertex_name_t, std::size_t> > >,
			property<edge_index_t, std::size_t, property<edge_weight_t, int> >,
			property<graph_name_t, string> > tmp_graph_type;
	tmp_graph_type tmpg;
	dynamic_properties tmpdp;
	tmpdp.property("node_id", get(vertex_name, tmpg));
	tmpdp.property("label", get(vertex_name, tmpg));
	tmpdp.property("weight", get(edge_weight, tmpg));
	tmpdp.property("label", get(edge_weight, tmpg));
	assert(read_graphviz(in, tmpg, tmpdp, "node_id"));

	// real graph
	graph_type g (num_vertices(tmpg));
	graph_traits<tmp_graph_type>::vertex_iterator vit, vit_end;
	for (tie(vit, vit_end) = vertices(tmpg); vit != vit_end; ++vit)
	{
		size_t name  = get(vertex_name, tmpg, *vit);
		int color = get(vertex_color, tmpg, *vit);
		put(vertex_color, g, (vertex_descriptor)name, color);
	}

	graph_traits<tmp_graph_type>::edge_iterator eit, eit_end;
	for (tie(eit, eit_end) = edges(tmpg); eit != eit_end; ++eit)
	{
		size_t s_name = get(vertex_name, tmpg, source(*eit, tmpg));
		size_t t_name = get(vertex_name, tmpg, target(*eit, tmpg));
		pair<edge_descriptor, bool> pe = add_edge(s_name, t_name, g);
		assert(pe.second);
		int weight = get(edge_weight, g, *eit);
		put(edge_weight, g, pe.first, weight);
	}

#ifdef DEBUG_GRAPHSIMPLIFICATION
	dynamic_properties dp;
	dp.property("id", get(vertex_index, g));
	dp.property("node_id", get(vertex_index, g));
	dp.property("label", get(vertex_index, g));
	dp.property("weight", get(edge_weight, g));
	dp.property("label", get(edge_weight, g));
	ofstream out ("graph_init.gv");
	write_graphviz_dp(out, g, dp, string("id"));
	out.close();
	system("dot -Tpdf graph_init.gv -o graph_init.pdf");
#endif

	//test relaxed LP based coloring
	typedef limbo::algorithms::coloring::GraphSimplification<graph_type> simplification_type;
	simplification_type gs (g, 3);
	std::vector<int> vPrecolor (num_vertices(g), -1);
	if (vPrecolor.size() > 0) vPrecolor[0] = 0;
	if (vPrecolor.size() > 3) vPrecolor[3] = 0;
	if (vPrecolor.size() > 4) vPrecolor[4] = 0;
	gs.precolor(vPrecolor.begin(), vPrecolor.end());
#if 0
	gs.hide_small_degree();
	gs.write_graph_dot("graph_simpl1");
	//gs.merge_subK4();
	gs.biconnected_component();
	//gs.connected_component();
#else
	gs.simplify(simplification_type::HIDE_SMALL_DEGREE | simplification_type::BICONNECTED_COMPONENT);
#endif
	gs.write_graph_dot("graph_simpl3");
	gs.write_simplified_graph_dot("graph_simpl_merge");

	in.close();
}

/// main function \n
/// test either on real graph
/// @param argc number of arguments
/// @param argv values of arguments
/// @return 0
int main(int argc, char** argv)
{
	assert(argc >= 2);
	realGraph(argv[1]);

	return 0;
}


//
// Copyright 2018 Mateusz Loskot <mateusz at loskot dot net>
//
// 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
//
#define BOOST_TEST_MODULE gil/test/core/algorithm/for_each_pixel
#include "unit_test.hpp"

#include <boost/gil/algorithm.hpp>
#include <boost/gil/image.hpp>

namespace gil = boost::gil;

BOOST_AUTO_TEST_CASE(lambda_expression)
{
    gil::gray8_pixel_t const gray128(128);
    gil::gray8_image_t image(2, 2, gray128);

    int sum{0};
    gil::for_each_pixel(gil::view(image), [&sum](gil::gray8_pixel_t& p) {
        sum += gil::at_c<0>(p);
    });
    BOOST_TEST(sum == 2 * 2 * 128);
}


/////////////////////////////////////////////////////////////////////////////////////
// distribution::survival::response::right_truncated::is_right_truncated.hpp 	   //
//                                                                                //
//  Copyright 2009 Erwann Rogard. Distributed under the Boost                      //
//  Software License, Version 1.0. (See accompanying file                          //
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)               //
/////////////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_STATISTICS_DETAIL_DISTRIBUTION_SURVIVAL_RESPONSE_RIGHT_TRUNCATED_IS_RIGHT_TRUNCATED_HPP_ER_2009
#define BOOST_STATISTICS_DETAIL_DISTRIBUTION_SURVIVAL_RESPONSE_RIGHT_TRUNCATED_IS_RIGHT_TRUNCATED_HPP_ER_2009
#include <boost/statistics/detail/distribution/survival/response/types/right_truncated/event.hpp>

namespace boost {
namespace statistics{
namespace detail{
namespace distribution{
namespace survival {
namespace response {
namespace meta{

	template<typename S>
	struct is_event : boost::mpl::bool_<false>{};

    template<typename T,typename B>
    struct is_event< event<T,B> > : boost::mpl::bool_<true>{};

}// meta
}// response
}// survival
}// distribution
}// detail
}// statistics
}// boost

#endif


#include "../geometry.hpp"
#include "../graph_util.hpp"
#include "../static_graph.hpp"

#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>

#include <algorithm>

BOOST_AUTO_TEST_SUITE(geometry_tests)

struct TestEdge
{
    unsigned first;
    unsigned last;
};

BOOST_AUTO_TEST_CASE(topo_sort)
{
    //
    //   4----->--\/---------->---------\
    //             1--------->3-------->5
    //   0----->--/ \
    //               \
    //                2
    std::vector<TestEdge> edges = {
        {0, 1},
        {1, 2},
        {1, 3},
        {1, 5},
        {3, 5},
        {4, 1}
    };

    static_graph<TestEdge> graph(6, std::move(edges));
    auto ordering = graph_util::topo_sort(graph);
    BOOST_CHECK_EQUAL(ordering.size(), 6);
    BOOST_CHECK_EQUAL(ordering[5], 5);
    BOOST_CHECK_EQUAL(ordering[4], 3);
    BOOST_CHECK_EQUAL(ordering[3], 2);
    BOOST_CHECK_EQUAL(ordering[2], 1);
    BOOST_CHECK_EQUAL(ordering[1], 0);
    BOOST_CHECK_EQUAL(ordering[0], 4);
}

BOOST_AUTO_TEST_CASE(shortest_dag_path)
{
    //
    //   4----->--\/---------->---------\
    //             1--------->3-------->5
    //   0----->--/ \
    //               \
    //                2
    std::vector<TestEdge> edges = {
        {0, 1},
        {1, 2},
        {1, 3},
        {1, 5},
        {3, 5},
        {4, 1}
    };

    static_graph<TestEdge> graph(6, std::move(edges));
    auto info = graph_util::shortest_dag_path(graph, 0, 5);
    BOOST_CHECK_EQUAL(info.distance.size(), 6);
    BOOST_CHECK_EQUAL(info.distance[5], 2);
    BOOST_CHECK_EQUAL(info.parents.size(), 6);
    BOOST_CHECK_EQUAL(info.parents[5], 1);
    BOOST_CHECK_EQUAL(info.parents[1], 0);
    BOOST_CHECK_EQUAL(info.parents[0], 0);
}

BOOST_AUTO_TEST_SUITE_END()


//////////////////////////////////////////////////////////////////////////////////////////////
/// \file DoglegGaussNewtonSolver.hpp
///
/// \author Sean Anderson, ASRL
//////////////////////////////////////////////////////////////////////////////////////////////

#ifndef STEAM_DOGLEG_GAUSS_NEWTON_SOLVER_HPP
#define STEAM_DOGLEG_GAUSS_NEWTON_SOLVER_HPP

#include <Eigen/Core>

#include <steam/solver/GaussNewtonSolverBase.hpp>

namespace steam {

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Solver using Powell's Dogleg for the trust region
//////////////////////////////////////////////////////////////////////////////////////////////
class DoglegGaussNewtonSolver : public GaussNewtonSolverBase
{
public:

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Dogleg parameters
  //////////////////////////////////////////////////////////////////////////////////////////////
  struct Params : public SolverBase::Params {

    //////////////////////////////////////////////////////////////////////////////////////////////
    /// \brief Default constructor
    //////////////////////////////////////////////////////////////////////////////////////////////
    Params() : SolverBase::Params(), ratioThresholdShrink(0.25), ratioThresholdGrow(0.75),
      shrinkCoeff(0.5), growCoeff(3.0), maxShrinkSteps(50) {
    }

    /// Minimum ratio of actual to predicted cost reduction, shrink trust region if lower (range: 0.0-1.0)
    double ratioThresholdShrink;

    /// Grow trust region if ratio of actual to predicted cost reduction above this (range: 0.0-1.0)
    double ratioThresholdGrow;

    /// Amount to shrink by (range: <1.0)
    double shrinkCoeff;

    /// Amount to grow by (range: >1.0)
    double growCoeff;

    /// Maximum number of times to shrink trust region before giving up
    unsigned int maxShrinkSteps;

  };

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Constructor
  //////////////////////////////////////////////////////////////////////////////////////////////
  DoglegGaussNewtonSolver(OptimizationProblem* problem, const Params& params = Params());

private:

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Build the system, solve for a step size and direction, and update the state
  //////////////////////////////////////////////////////////////////////////////////////////////
  virtual bool linearizeSolveAndUpdate(double* newCost, double* gradNorm);

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Casts parameters to base type (for SolverBase class)
  //////////////////////////////////////////////////////////////////////////////////////////////
  virtual const SolverBase::Params& getSolverBaseParams() const;

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Parameters
  //////////////////////////////////////////////////////////////////////////////////////////////
  Params params_;

  //////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief Trust region size
  //////////////////////////////////////////////////////////////////////////////////////////////
  double trustRegionSize;

};

} // steam

#endif // STEAM_DOGLEG_GAUSS_NEWTON_SOLVER_HPP


#include <metaSMT/API/AssignRandomBits.hpp>
#include <boost/proto/debug.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
#include <metaSMT/frontend/Logic.hpp>

using namespace std;
using namespace metaSMT;
using namespace metaSMT::solver;
using namespace metaSMT::logic;
namespace proto = boost::proto;
using boost::dynamic_bitset;

BOOST_FIXTURE_TEST_SUITE(assign_random_bits_t, Solver_Fixture )

BOOST_AUTO_TEST_CASE( test_random_bits )
{
  bitvector x = new_bitvector(32);
  bitvector y = new_bitvector(32);
  bitvector z = new_bitvector(32);

  std::vector<bitvector> variables;
  variables.push_back(x);
  variables.push_back(y);
  variables.push_back(z);

  unsigned x1, y1, z1;
  unsigned x2, y2, z2;

  BOOST_REQUIRE( solve(ctx) );
  assign_random_bits(ctx, variables);

  x1 = read_value(ctx,x);
  y1 = read_value(ctx,y);
  z1 = read_value(ctx,z);

  BOOST_REQUIRE ( solve(ctx) );
  assign_random_bits(ctx, variables);

  x2 = read_value(ctx,x);
  y2 = read_value(ctx,y);
  z2 = read_value(ctx,z);

  BOOST_REQUIRE ( solve(ctx) );

  BOOST_REQUIRE ( x1 != x2 || y1 != y2 || z1 != z2 );

}

BOOST_AUTO_TEST_CASE( test_solve_random )
{
  bitvector x = new_bitvector(32);
  bitvector y = new_bitvector(32);
  bitvector z = new_bitvector(32);

  std::vector<bitvector> variables;
  variables.push_back(x);
  variables.push_back(y);
  variables.push_back(z);

  unsigned x1, y1, z1;
  unsigned x2, y2, z2;

  BOOST_REQUIRE( solve_with_random_bits(ctx, variables) );

  x1 = read_value(ctx,x);
  y1 = read_value(ctx,y);
  z1 = read_value(ctx,z);

  BOOST_REQUIRE ( solve_with_random_bits(ctx,variables) );
  x2 = read_value(ctx,x);
  y2 = read_value(ctx,y);
  z2 = read_value(ctx,z);

  BOOST_REQUIRE ( solve_with_random_bits(ctx,variables) );

  BOOST_REQUIRE ( x1 != x2 || y1 != y2 || z1 != z2 );

}

BOOST_AUTO_TEST_SUITE_END() //Solver

//  vim: ft=cpp:ts=2:sw=2:expandtab


#include "stdlib.h"

#include <boost/program_options/options_description.hpp>
#include <boost/program_options.hpp>

#include <frovedis.hpp>
#include "frovedis/matrix/rowmajor_matrix.hpp"
#include "frovedis/matrix/crs_matrix.hpp"

#define DOC_COUNT 2000

void append_crs_matrix(frovedis::crs_matrix_local<int>& m1, frovedis::crs_matrix_local<int>& m2){
    for (int i=0; i<m2.idx.size(); i++){
        m1.idx.push_back(m2.idx[i]);
        m1.val.push_back(m2.val[i]);
    }
    int curr_element = m1.off.back();
    for(int r=1; r<m2.off.size(); r++){
        m1.off.push_back(m2.off[r]+curr_element);
    }
}

int main(int argc, char* argv[]){
    frovedis::use_frovedis use(argc, argv);

    using namespace boost::program_options;

    options_description opt("option");
    opt.add_options()
        ("help,h", "print help message")
        ("input,i", value<std::string>(), "path for input data with bag-of-words format")  // see https://archive.ics.uci.edu/ml/datasets/bag+of+words
        ("split_size", value<size_t>()->default_value(0), "size of test split")
        ("train", value<std::string>(), "path for output data for training")
        ("test", value<std::string>(), "path for output data for testing. if the number of test samples is 0, this will not be made.")
        ("binary", "save/load file with binary")
        ;

    variables_map argmap;
    store(command_line_parser(argc,argv).options(opt).allow_unregistered().run(), argmap);
    notify(argmap);

    std::string input_path;
    std::string train_path;
    std::string test_path;

    uint32_t test_doc = 0, train_doc = 0, num_voc, num_doc;

    test_doc = argmap["split_size"].as<size_t>();

    if(argmap.count("input")){
      input_path = argmap["input"].as<std::string>();
    } else {
      std::cerr << "input is not specified" << std::endl;
      std::cerr << opt << std::endl;
      exit(1);
    }
    if(argmap.count("train")){
      train_path = argmap["train"].as<std::string>();
    } else {
      std::cerr << "train is not specified" << std::endl;
      std::cerr << opt << std::endl;
      exit(1);
    }
    if(argmap.count("test")){
      test_path = argmap["test"].as<std::string>();
    } else if (test_doc > 0) {
      std::cerr << "test is not specified" << std::endl;
      std::cerr << opt << std::endl;
      exit(1);
    }

    bool binary = argmap.count("binary") ? true : false;
    std::ifstream fin(input_path);

    frovedis::rowmajor_matrix_local<int> dataset_train;
    frovedis::rowmajor_matrix_local<int> dataset_test;
    frovedis::crs_matrix_local<int> dataset_train_sparse;
    frovedis::crs_matrix_local<int> dataset_test_sparse;

    std::string line;
    std::getline(fin, line);
    std::istringstream ss1(line);
    ss1 >> num_doc;
    assert(test_doc<num_doc);
    train_doc = num_doc-test_doc;
    std::getline(fin, line);
    std::istringstream ss2(line);
    ss2 >> num_voc;
    std::getline(fin, line);

    int left_train = train_doc, left_test = test_doc;
    left_train = left_train < DOC_COUNT? left_train : DOC_COUNT;
    left_test = left_test < DOC_COUNT? left_test : DOC_COUNT;
    dataset_train.set_local_num(left_train, num_voc);
    dataset_train.val.resize(left_train*num_voc);
    if(test_doc!=0){
        dataset_test.set_local_num(left_test, num_voc);
        dataset_test.val.resize(left_train*num_voc);
    }

    std::cout<<"training document:" << train_doc << std::endl;
    std::cout<<"test document:" << test_doc << std::endl;
    std::cout<<"words: " << num_voc << std::endl;

    int loop_count_test = 1, loop_count_train = 1;
    while (std::getline(fin, line)) {
        std::istringstream ss3(line);
        int word_id, count, doc_id;
        ss3 >> doc_id >> word_id >> count;
        doc_id --; word_id --;
        if(doc_id < test_doc){
            if(doc_id < DOC_COUNT*loop_count_test){
                int doc_idx = doc_id - (loop_count_test-1)*DOC_COUNT;
                dataset_test.val[doc_idx*num_voc+word_id] = count;
            } else {
                if(loop_count_test==1) dataset_test_sparse = dataset_test.to_crs();
                else {
                    auto tmp_test_sparse = dataset_test.to_crs();
                    append_crs_matrix(dataset_test_sparse,tmp_test_sparse);
                }
                left_test = test_doc - DOC_COUNT*loop_count_test;
                left_test = left_test < DOC_COUNT? left_test:DOC_COUNT;
                dataset_test.local_num_row = left_test;
                dataset_test.val.assign(left_test*num_voc,0);
                int doc_idx = doc_id - loop_count_test*DOC_COUNT;
                dataset_test.val[doc_idx*num_voc+word_id] = count;
                loop_count_test ++;
            }
        } else {
            if(doc_id - test_doc < DOC_COUNT*loop_count_train){
                int doc_idx = doc_id - test_doc - (loop_count_train-1)*DOC_COUNT;
                assert(doc_idx>=0 && doc_idx<DOC_COUNT);
                dataset_train.val[doc_idx*num_voc+word_id] = count;
            } else {
                if(loop_count_train==1) dataset_train_sparse = dataset_train.to_crs();
                else {
                    auto tmp_train_sparse = dataset_train.to_crs();
                    append_crs_matrix(dataset_train_sparse,tmp_train_sparse);
                }
                left_train = train_doc - DOC_COUNT*loop_count_train;
                left_train = left_train < DOC_COUNT? left_train:DOC_COUNT;
                dataset_train.local_num_row = left_train;
                dataset_train.val.assign(left_train*num_voc,0);
                int doc_idx = doc_id - test_doc - loop_count_train*DOC_COUNT;
                dataset_train.val[doc_idx*num_voc+word_id] = count;
                loop_count_train ++;
            }
        }
    }

    if(loop_count_train==1) dataset_train_sparse = dataset_train.to_crs();
    else {
        auto tmp_train_sparse = dataset_train.to_crs();
        append_crs_matrix(dataset_train_sparse,tmp_train_sparse);
    }

    dataset_train_sparse.set_local_num(num_voc);
    if (binary) {
        dataset_train_sparse.savebinary(train_path);
    } else {
        make_crs_matrix_scatter(dataset_train_sparse).save(train_path);
    }
    assert(dataset_train_sparse.local_num_row==train_doc);

    if(test_doc != 0) {
        if(loop_count_test==1)  dataset_test_sparse = dataset_test.to_crs();
        else {
            auto tmp_test_sparse = dataset_test.to_crs();
            append_crs_matrix(dataset_test_sparse,tmp_test_sparse);
        }
        dataset_test_sparse.set_local_num(num_voc);
        if (binary) {
            dataset_test_sparse.savebinary(test_path);
        } else {
            make_crs_matrix_scatter(dataset_test_sparse).save(test_path);
        }
        assert(dataset_test_sparse.local_num_row==test_doc);
    }

}


//
// Created by Alex Beccaro on 18/01/18.
//

#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "../../src/problems/1-50/36/problem36.hpp"

BOOST_AUTO_TEST_SUITE( Problem36 )

    BOOST_AUTO_TEST_CASE( Solution ) {
        auto res = problems::problem36::solve();
        BOOST_CHECK_EQUAL(res, 872187);
    }

BOOST_AUTO_TEST_SUITE_END()


// Copyright Jason Rice 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/bool.hpp>
#include <boost/hana/find_if.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/map.hpp>
namespace hana = boost::hana;

struct is_last {
    template <typename N>
    constexpr auto operator()(N) const {
        return hana::bool_c<N::value == <%= input_size %>>;
    }
};

struct undefined {};

int main() {
    constexpr auto map = hana::make_map(
        <%= (1..input_size).map { |n|
            "hana::make_pair(hana::int_c<#{n}>, undefined{})"
        }.join(', ') %>
    );
    constexpr auto result = hana::find_if(map, is_last{});
    (void)result;
}


#ifndef CANNON_PHYSICS_LAGRANGIAN_MECHANICS
#define CANNON_PHYSICS_LAGRANGIAN_MECHANICS

/*!
 * \file cannon/physics/lagrangian_mechanics.hpp
 * \brief File containing class and free function definitions for working with
 * Lagrangian dynamics, as in Structure and Interpretation of Classical
 * Mechanics.
 */

#include <functional>

#include <Eigen/Dense>

#include <cannon/log/registry.hpp>

using namespace Eigen;

using namespace cannon::log;

namespace cannon {
  namespace physics {

    /*!
     * \brief Struct representing a local tuple consisting of a coordinate
     * vector, velocity vector, and time.
     */
    struct LocalTuple {

      LocalTuple() = delete;

      /*!
       * \brief Constructor taking generalized coordinate dimension and
       * initializing coordinates and time to zero.
       */
      LocalTuple(unsigned int dim) : dim(dim), time(0.0) {
        coordinates = VectorXd::Zero(dim);
        velocities = VectorXd::Zero(dim);
      }

      /*!
       * \brief Copy constructor.
       */
      LocalTuple(const LocalTuple &l) : dim(l.dim), time(l.time),
      coordinates(l.coordinates), velocities(l.velocities) {}

      /*!
       * \brief Move constructor.
       */
      LocalTuple(LocalTuple &&l) : dim(l.dim), time(l.time),
      coordinates(std::move(l.coordinates)),
      velocities(std::move(l.velocities)) {}

      /*!
       * \brief Copy assignment operator.
       */
      LocalTuple& operator=(const LocalTuple& o) {
        dim = o.dim;
        time = o.time;
        coordinates = o.coordinates;
        velocities = o.velocities;

        return *this;
      }

      /*!
       * \brief Get a vector representation of this local tuple.
       *
       * \returns A vector containing the time, generalized coordinates, and
       * generalized velocity for this local tuple, in that order.
       */
      VectorXd to_vec();

      /*!
       * \brief Initialize this local tuple with the input vector, which should
       * have the time, generalized coordinates, and generalized velocities, in
       * that order.
       *
       * \param vec The vector to use for initialization.
       */
      void from_vec(const VectorXd& vec);

      unsigned int dim; //!< Dimension of generalized coordinates
      double time; //!< Time for this local tuple
      VectorXd coordinates; //!< Generalized coordinates for this local tuple.
      VectorXd velocities; //!< Generalized velocities for this local tuple

    };

    /*!
     * \brief Struct representing a path as a series of waypoints in
     * generalized coordinates for doing Lagrangian mechanics.
     */
    struct Path {
      Path() = delete;

      /*!
       * \brief Straight-line constructor taking a start, and end time and
       * start and end coordinates, as well as the number of waypoints to
       * construct.
       */
      Path(double t0, double t1, VectorXd start, VectorXd end,
          unsigned int length) : t0(t0), t1(t1) {
        assert(0 <= t0);
        assert(t0 < t1);
        assert(start.size() == end.size());
        assert(length >= 2);

        VectorXd delta = (end - start) / (double)(length-1);

        for (unsigned int i = 0; i < length; i++) {
          waypoints.push_back(start + i * delta);
        }
      }

      /*!
       * \brief Constructor taking generalized coordinate dimension and a
       * vector of appended waypoints.
       */
      Path(unsigned int dim, const VectorXd& vec) {
        from_vec(dim, vec);
      }

      /*!
       * \brief Get a vector representation of this path by appending all
       * waypoints.
       *
       * \returns The vector representation.
       */
      VectorXd to_vec();

      /*!
       * \brief Load a path with waypoints of the input dimension from the
       * input vector.
       *
       * \param vec The vector to load.
       */
      void from_vec(unsigned int dim, const VectorXd& vec);

      /*!
       * \brief Get the local tuple at time t from this path.
       *
       * Just doing linear interpolation for now.
       *
       * \param t The time to get local tuple for.
       *
       * \returns Local tuple at the input time along this path.
       */
      LocalTuple get_local_tuple(double t) const;

      double t0; //!< Start time for this path
      double t1; //!< End time for this path
      std::vector<VectorXd> waypoints; //!< Waypoints making up this path
    };

    using Lagrangian = std::function<double(const LocalTuple&)>;

    /*!
     * \brief Compute path action of the input Lagrangian on the input path.
     *
     * \param L The Lagrangian to use
     * \param q The path to evaluate path action on
     *
     * \returns The path action
     */
    double compute_path_action(Lagrangian L, const Path& q);

  } // namespace physics
} // namespace cannon

#endif /* ifndef CANNON_PHYSICS_LAGRANGIAN_MECHANICS */


/**
 * @author    Aldrin I. Racelis
 * @copyright Aldrin Racelis (c)2017
 * @file      game.cpp
 * @brief     Class Implementation of the Game Object
 */

#include "../include/game.h"
#include <Eigen/Dense>
#include <iostream>
#include <vector>

using std::cout;  using std::cin;
using std::endl;

game::game() : position(0), inGame(true), turn(0) {
  boardValue = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  winCheck = {1, 2, 3};
  winCond <<  0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 6, 1, 4, 7, 2, 5, 8, 2, 4, 6, 0,
                4, 8;
  winArray <<  0, 0, 0;
  winning = {0, 0, 0 };
}

game::~game() { }

/**
 * @brief Determines if there is a winner in the game.
 */
bool game::checkWinner() {
  int i, j;
  if (fmod(turn, 2) == 1) {
    player = "Player O";
    winning = {1, 1, 1};
  } else {
    player = "Player X";
    winning = {2, 2, 2};
  }
  for (i = 0; i <= 21; i += 3) {
    winArray = winCond.segment<3>(i);
    for (int k=0; k < 3; ++k) {
      j = winArray[k];
      winCheck[k] = boardValue.at(j);
    }

    if ( winCheck == winning ) {
        cout << player << " is the winner." << endl;
        return false;
    }
  }
  return true;
}

/**
 * @brief Initiates each step for playing the game. It asks for the input,
 * checks for valid input, updates the board values, prints the board
 * and determines if there is a winner.
 */
void game::playingGame() {
  while (inGame) {
    cout << "Please enter a number from 1-9" << endl;
    cin >> position;

    CheckInput();

    board.UpdateBoard(boardValue, turn, position);
    board.PrintBoard();
    turn += 1;
    inGame = checkWinner();
    if (turn == 9)
      inGame = false;
  }
}

/**
 * @brief Validates the input for choosing the next move.
 */
void game::CheckInput() {
  while (cin.fail() || position < 1 || position > 9 ||
            boardValue[position-1] != 0) {
    cout << "Invalid input, please enter an open number from 1-9" << endl;
    cin.clear();
    cin.ignore(999, '\n');
    cin >> position;
  }
}


//==================================================================================================
/*!
  @file
  @copyright 2016 NumScale SAS

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

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{
  /*!
    @ingroup group-swar
    This function object concatenates two values of the same type to build a boost::simd::pack
    but with a cardinal twice as large.

    @par Scalar Semantic:
    For any scalar value @c a and @c b of type @c T , the following code:
    @code
    auto c = combine(a,b);
    @endcode
    is equivalent to :
    @code
    pack<T, 2> c(a,b);
    @endcode

    @par SIMD Semantic:
    For any type value @c a and @c b of type boost::simd::pack<T,N>, the following code:
    @code
    pack<T,2*N> c = combine(a,b);
    @endcode
    is equivalent to :
    @code
    pack<T,2*N> c(a[0],....,a[N-1],b[0],....,b[N-1]);
    @endcode
    where @c N is equal to the cardinal of both @c a and @c b.

    @param v0 First  value to combine
    @param v1 Second value to combine

    @return The concatenation of both inputs
  **/
  auto combine(Value const& v0, Value const& v1);
} }
#endif

#include <boost/simd/function/simd/combine.hpp>

#endif


#if COMPILATION_INSTRUCTIONS /* -*- indent-tabs-mode: t -*- */
(echo "#include\""$0"\"" > $0x.cpp) && mpic++ -O3 -std=c++14 -Wfatal-errors -D_TEST_BOOST_MPI3_GRAPH_COMMUNICATOR $0x.cpp -o $0x.x && time mpirun -n 5 $0x.x $@ && rm -f $0x.x $0x.cpp; exit
#endif
#ifndef BOOST_MPI3_GRAPH_COMMUNICATOR_HPP
#define BOOST_MPI3_GRAPH_COMMUNICATOR_HPP

#include "../mpi3/communicator.hpp"
#include <boost/graph/adjacency_list.hpp>
#include <iterator>
#include <boost/graph/graphviz.hpp>

namespace boost{
namespace mpi3{

struct graph_communicator : communicator{
	using graph = boost::adjacency_list<boost::setS, boost::vecS, boost::directedS>;

	std::vector<int> neighbors(int rank) const{
		int nneighbors;
		MPI_Graph_neighbors_count(impl_, rank, &nneighbors);
		std::vector<int> ret(nneighbors);
		MPI_Graph_neighbors(impl_, rank, ret.size(), ret.data());
		return ret;
	}

	graph topology() const{
		int nnodes;
		int nedges;
		MPI_Graphdims_get(impl_, &nnodes, &nedges);
		std::vector<int> index(nnodes);
		std::vector<int> edges(nedges);
		MPI_Graph_get(impl_, nnodes, nedges, index.data(), edges.data());
		auto ite = std::begin(edges);
		int source = 0;
		graph ret;
	//	std::vector<decltype(add_vertex(g))> v_ptr;
	//	for(int i = 0; i != nnodes; ++i){
	//		v_ptr.push_back(add_vertex(g));
	//	}
	//	std::cout << " index: ";
	//	for(auto e: index) std::cout << e << " ";
	//	std::cout << '\n';

	//	std::cout << " edges: ";
	//	for(auto e: edges) std::cout << e << " ";
	//	std::cout << '\n';
	//	return ret;
		int j = 0;
		for(int i : index){
			for(; j != i; ++j){
				add_edge(source, edges[j], ret);
			}
			++source;
		}
		return ret;
	}
};

/*
template<class Graph>
graph_communicator communicator::make_graph(Graph const& g) const{
	graph_communicator ret;
	std::vector<int> indx;
	std::vector<int> edges;
	std::pair<typename Graph::vertex_iterator, typename Graph::vertex_iterator> vs = boost::vertices(g);
	for(auto vit = vs.first; vit != vs.second; ++vit){
		auto neighbors = boost::adjacent_vertices(*vit, g);
		for(auto nit = neighbors.first; nit != neighbors.second; ++nit) edges.push_back(*nit);
		indx.push_back(edges.size()); // http://stackoverflow.com/a/32833024/225186
	}
	MPI_Graph_create(impl_, num_vertices(g), indx.data(), edges.data(), true, &ret.impl_);
	return ret;
}*/

/*
template<class Graph>
int communicator::graph_rank(Graph const& g) const{
	std::vector<int> indx;
	std::vector<int> edges;
	std::pair<typename Graph::vertex_iterator, typename Graph::vertex_iterator> vs = boost::vertices(g);
	for(auto vit = vs.first; vit != vs.second; ++vit){
		auto neighbors = boost::adjacent_vertices(*vit, g);
		for(auto nit = neighbors.first; nit != neighbors.second; ++nit) edges.push_back(*nit);
		indx.push_back(edges.size()); // http://stackoverflow.com/a/32833024/225186
	}
	int ret;
	MPI_Graph_map(impl_, num_vertices(g), indx.data(), edges.data(), &ret);
	return ret;
}*/

}}

#ifdef _TEST_BOOST_MPI3_GRAPH_COMMUNICATOR

#include<iostream>
#include "../mpi3/main.hpp"
#include "../mpi3/version.hpp"
#include "../mpi3/ostream.hpp"

#include<boost/graph/adjacency_list.hpp>
#include<boost/graph/random.hpp>
#include<random>

#include<boost/graph/graphviz.hpp>
#include <boost/graph/isomorphism.hpp>

int boost::mpi3::main(int argc, char* argv[], boost::mpi3::communicator world){
	if(world.size() != 5) return 1;

	typedef boost::adjacency_list<boost::setS, boost::vecS, boost::directedS> graph;
	graph g;

	std::default_random_engine rd;
	boost::generate_random_graph(g, 5, 8, rd);

	if(world.rank()==0){
		write_graphviz(std::cout, g);
		std::cout << "---\n";
	}

//	auto world_graph = world.make_graph(g);

/*	auto outg = world_graph.topology();

	if(world.rank()==0){
		write_graphviz(std::cout, outg);
		std::cout << "---\n";
	}

	assert(boost::isomorphism(outg, g));
*/

	return 0;

}

#endif
#endif


//*****************************************************************
// Copyright 2013 MIT Lincoln Laboratory
// Project:            SPAR
// Authors:            OMD
// Description:        Unit tests for IntegerField
//
// Modifications:
// Date          Name           Modification
// ----          ----           ------------
// 31 Jan 2013   omd            Original Version
//*****************************************************************

#define BOOST_TEST_MODULE IntegerFieldTest
#include "common/test-init.h"

#include "integer-field.h"

#include <boost/assign/list_inserter.hpp>
#include <map>
#include <string>

using namespace std;
namespace ba = boost::assign;

BOOST_AUTO_TEST_CASE(NumValuesWorks) {
  IntegerField int_f1("testing", "%d", 10, 13);
  // 10, 11, and 12 are the only legal values.
  BOOST_CHECK_EQUAL(int_f1.NumValues(), 3);

  IntegerField int_f2("testing", "%d", 0, 20);
  // 10, 11, and 12 are the only legal values.
  BOOST_CHECK_EQUAL(int_f2.NumValues(), 20);
}

BOOST_AUTO_TEST_CASE(MaxLengthWorks) {
  IntegerField f1("test", "%d", 0, 5);
  BOOST_CHECK_EQUAL(f1.MaxLength(), 1);

  IntegerField f2("test", "%d", 0, 10);
  // End is exclusive so max val == 9
  BOOST_CHECK_EQUAL(f2.MaxLength(), 1);

  IntegerField f3("test", "%d", -9, 10);
  // The end of the range is exclusive so the max value is 9, but -9 requires 2
  // characters.
  BOOST_CHECK_EQUAL(f3.MaxLength(), 2);

  IntegerField f4("test", "%d", 0, 100);
  // The end of the range is exclusive so the largest value this can generate is
  // 99.
  BOOST_CHECK_EQUAL(f4.MaxLength(), 2);

  IntegerField f5("test", "%d", 99, 101);
  BOOST_CHECK_EQUAL(f5.MaxLength(), 3);

  IntegerField f6("test", "%d", 0, 101);
  BOOST_CHECK_EQUAL(f6.MaxLength(), 3);

  IntegerField f7("another test", "%d", 0, 105);
  BOOST_CHECK_EQUAL(f7.MaxLength(), 3);
}

// Create a field that can only generate one of two dates. Generate a
// hundred values and make sure only the two expected values are seen and that
// they're both seen roughly equally. To test the equality we assume that the
// number of times each value was seen should have a binomial distribution. If
// we generate 100 values the probability of seeing one of the two values less
// than 27 times is less than 1 in 1 million.
BOOST_AUTO_TEST_CASE(DistributionCorrect) {
  IntegerField f("test field", "%d", 1, 3);

  map<string, int> obs_counts;
  obs_counts["1"] = 0;
  obs_counts["2"] = 0;

  for (int i = 0; i < 100; ++i) {
    char buffer[f.MaxLength()];
    char* end_c = f.RandomValue(f.MaxLength(), buffer);
    string val(buffer, end_c - buffer);
    BOOST_CHECK_MESSAGE(
        obs_counts.find(val) != obs_counts.end(),
        "Only expected values are 1 and 2 but "
        << val << " was generated");
    obs_counts[val] += 1;
  }

  BOOST_CHECK_EQUAL(obs_counts.size(), 2);
  BOOST_CHECK_EQUAL(obs_counts["1"] + obs_counts["2"], 100);

  BOOST_CHECK_GE(obs_counts["1"], 27);
  BOOST_CHECK_GE(obs_counts["2"], 27);
}

// Same as the above but we exclude some values leaving only legal ones left.
BOOST_AUTO_TEST_CASE(DistributionCorrectWithExclude) {
  set<string> exclude_vals;
  ba::insert(exclude_vals)("0")("1")("3");
  IntegerField f("test field", "%d", -1, 4);

  map<string, int> obs_counts;
  // These are the only values in [-1, 3) that haven't been excluded.
  obs_counts["-1"] = 0;
  obs_counts["2"] = 0;

  for (int i = 0; i < 100; ++i) {
    char buffer[f.MaxLength()];
    char* end_c = f.RandomValueExcluding(exclude_vals, f.MaxLength(), buffer);
    string val(buffer, end_c - buffer);
    BOOST_CHECK_MESSAGE(
        obs_counts.find(val) != obs_counts.end(),
        "Only expected values are 1 and 2 but "
        << val << " was generated");
    obs_counts[val] += 1;
  }

  BOOST_CHECK_EQUAL(obs_counts.size(), 2);
  BOOST_CHECK_EQUAL(obs_counts["-1"] + obs_counts["2"], 100);

  BOOST_CHECK_GE(obs_counts["-1"], 27);
  BOOST_CHECK_GE(obs_counts["2"], 27);
}

// Try an IntegerField with various format strings and make sure the right
// values get returned and that MaxLength() returns the expected values.
BOOST_AUTO_TEST_CASE(FormatStringsWork) {
  {
    IntegerField f("test", "%05d", 1, 3);
    BOOST_CHECK_EQUAL(f.MaxLength(), 5);
    char buffer[f.MaxLength()];
    char* end_ptr = f.RandomValue(f.MaxLength(), buffer);
    string result(buffer, end_ptr - buffer);
    BOOST_CHECK_MESSAGE(
        result == "00001" || result == "00002",
        "Expected 00001 or 00002 but got " << result);
  }

  {
    IntegerField f("test", "%+d", 1, 3);
    BOOST_CHECK_EQUAL(f.MaxLength(), 2);
    char buffer[f.MaxLength()];
    char* end_ptr = f.RandomValue(f.MaxLength(), buffer);
    string result(buffer, end_ptr - buffer);
    BOOST_CHECK_MESSAGE(
        result == "+1" || result == "+2",
        "Expected +1 or +2 but got " << result);
  }

  {
    IntegerField f("test", "foo %02d bar", 1, 3);
    BOOST_CHECK_EQUAL(f.MaxLength(), 10);
    char buffer[f.MaxLength()];
    char* end_ptr = f.RandomValue(f.MaxLength(), buffer);
    string result(buffer, end_ptr - buffer);
    BOOST_CHECK_MESSAGE(
        result == "foo 01 bar" || result == "foo 02 bar",
        "Expected 'foo 01 bar' or 'foo 02 bar' but got " << result);
  }

}


/*
 * H.cpp
 *
 *  Created on: Apr 11, 2014
 *      Author: wilfeli
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

#include <Eigen/Dense>
#include <math.h>

#include "H.h"
#include "Asset.h"
#include "W.h"
#include "Contract.h"
#include "Market.h"
#include "Tools.h"

using Eigen::MatrixXd;

H::H(W &w_, int id_):w(w_),
l_ask(0.0, 0.0),
c_bid(0.0, 0.0),
id(id_),
theta_x(1,3),
s0(1,18){
	// create reference to the world
	w.AddH(this);

	//create storage for goods
	ass_asGC.push_back(new GoodC(this, 0.0));

	//create HK
	ass_asHK.push_back(new HK(1.0));

	type = "H";

	c_bid.issuer = this;
	l_ask.issuer = this;

	//create wm
	ExpectationBackward* exp = new ExpectationBackward(1.0, 10, 0.5);
	wm["MasCHK"] = exp;

	//create wm
	exp = new ExpectationBackward(1.0, 10, 0.5);
	wm["MasGC"] = exp;

	//create wm
	exp = new ExpectationBackward(1.0, 0, 0.0);
	wm["api"] = exp;

	//create wm
	exp = new ExpectationBackward(0.0, 0, 0.01);
	wm["fi_ti"] = exp;

	//parameters
	param = new Parameters();
	param->init();

	//accounting
	account = new AccountH();

};

void
H::init(){
    //ADP setup
    theta_V = Eigen::MatrixXd::Constant(1, 1, param->ADP_BF_N);
    B_n_1_RLS = Eigen::MatrixXd::Zero(param->ADP_BF_N, param->ADP_BF_N);

    //QL setup
    _set_QL();

    //mRe setup
    _set_mRE();

};

void
H::ac_W(MessageMakeDec* mes){

	//calls opt choice
	_s0();
	//calls opt choice
    if (param->opt_TYPE == "EO_CS"){
        opt_CS(&s0,&theta_x, param->opt_CS_N);
    };

    if (param->opt_TYPE == "EO_ADP"){
        theta_V = _API_LM(&s0, param->ADP_API_LM_N, param->ADP_API_LM_M);

        Eigen::Block<Eigen::MatrixXd> s = s0.block(0,0,s0.rows(),s0.cols());
        _opt_CS_s_V(s,theta_x, theta_V, param->opt_CS_N);
    };

    if (param->opt_TYPE == "QL"){
        opt_QL();
    };

    if (param->opt_TYPE == "mRE"){
        opt_mRE();

    };

	//transforms it into ask and bid
	l_ask.q = theta_x(0,0) * s0(0,1);
	l_ask.p = theta_x(0,1) * s0(0,4);

	c_bid.pq_share = theta_x(0,2);

};

Ask*
H::ac_L(){
	//update numbers in bid
	l_ask.supply_curve = Eigen::MatrixXd::Zero(1,2);
	l_ask.supply_curve << l_ask.p , l_ask.q;

	l_ask.p_t_0 = l_ask.p;
	l_ask.q_t_0 = l_ask.q;

	//return reference to the ask
	return &l_ask;
};

Bid*
H::ac_C(){
	//update numbers in bid
	c_bid.pq = _s0()(0,0) * c_bid.pq_share;

	c_bid.pq_t_0 = c_bid.pq;
	c_bid.pq_share_t_0 = c_bid.pq_share;

	//update numbers in bid

//    if (param->GRID == "test"){
//        c_bid.demand_curve = Eigen::MatrixXd::Zero(1,2);
//        c_bid.demand_curve.row(0) << wm["MasGC"]->mu , c_bid.pq/wm["MasGC"]->mu ;
//        return &c_bid;
//    };

	//number of steps
	int N_STEPS_dc = 30;
	double P_MAX_dc = wm["MasGC"]->mu * 10;
	double P_MIN_dc = wm["MasGC"]->mu * 0.01;
	double STEP_SIZE = (P_MAX_dc - P_MIN_dc)/N_STEPS_dc;

	c_bid.demand_curve = Eigen::MatrixXd::Zero(N_STEPS_dc,2);
	for (int i = 0; i < N_STEPS_dc; i++){

		c_bid.demand_curve.row(i) << P_MIN_dc + i * STEP_SIZE, c_bid.pq/(P_MIN_dc + i * STEP_SIZE);

	};

	//return reference to the bid
	return &c_bid;
};

double
H::_mas_q_sell(MessageMarketLCheckAsk* inf){
	//checks how much to sell
	//return q from ask

	double q_sell;

	if (inf->p_eq >= l_ask.p){
		q_sell = l_ask.q;
	};

	return q_sell;
};

double
H::_mas_q_buy(MessageMarketCCheckBid* inf){
	//checks how much to sell
	//return q from ask

	double q_buy;

	int i=0;

	while ((c_bid.demand_curve(i,0) < inf->p_eq) && (i<c_bid.demand_curve.rows())){
		i++;
	};

	if (i<c_bid.demand_curve.rows()){
		q_buy = c_bid.demand_curve(i,1);
	}else{
		//buys zero
		q_buy = 0.0;
	};

	return q_buy;
};

void
H::_sell_asCHK(MessageMarketLSellC* inf){
	//new contract
	ContractHK* cHK = new ContractHK(this,
                                     inf->buyer,
                                     inf->p,
                                     inf->q,
                                     w.t,
                                     w.t);

	type = "H_EO";

	ass_asCHK.push_back(cHK);

	//?update ask
	l_ask.q -= cHK->q;

	//tell market about the contract
	inf->sender->_clear_C(cHK);

	//call accounting
	//create accounting message
    //	MessageSellC* mes = new MessageSellC(inf, cHK);
	account->ac_get_inf(inf, cHK);

    //	delete mes;

};

double
H::_goal_t(Eigen::MatrixXd* s){

	double l;
	double c;

	if ((*s)(0,3) <= 0.0){
		c = -0.5;
//        c = 0.0;
	}else{
        c = (*s)(0,3);
    };

	l = (*s)(0,2);

	return (param->GOAL_T_theta(0,0) * log(1+c) + param->GOAL_T_theta(0,1) * (1-l));
//    return (param->GOAL_T_theta(0,0) * log(0.5+c) + param->GOAL_T_theta(0,1) * (1-l));
};

void
H::_buy_asGC(MessageGoodC* mes){

	ass_asGC.back()->q += mes->q;
	account->ac_get_inf(mes);

};

void
H::_PS_receive_payment(MessagePSSendPayment* mes){

	account->ac_get_inf(mes);

};

bool
H::_PS_send_payment(MessagePSSendPayment* inf){

	inf->sender = this; //static_cast<IHolderPS*>(const_cast<H*>(this));

	bool FLAG_CLEARED = ass_asCBDt0.front()->issuer->_PS_accept_PO(inf);

	if(FLAG_CLEARED){
		account->ac_get_inf(inf);

	};

	return FLAG_CLEARED;

};

void
H::ac_W_begin_step(){

	//update accounting
	account->ac_W_initialize_step();

	//
	for (auto c:ass_asCHK){
		if (c->t_end <= w.t){
			delete c;
			c = NULL;
		};
	};

	//clear contracts
	ass_asCHK.erase(std::remove_if(ass_asCHK.begin(), ass_asCHK.end(),
                                   [&](ContractHK* x) -> bool { return (x); }),
                    ass_asCHK.end());

};

void
H::ac_W_begin_step(MessageStatus* mes){
	if (mes->status <= 0.0){
		account->ac_W_initialize_step(mes);
	};
};

void
H::ac_W_end_step(){
	//updates state
	_s0();
	double ut = _goal_t(&s0);
	account->ac_W_end_step(&s0, ut);

	//eats good
	ass_asGC.front()->q = 0.0;

};

void
H::ac_W_end_step(MessageStatus* mes){
    if (mes->status <= 0.0){
        ac_W_end_step();
    };
};

void
H::wm_update_k_s(){
	if (w.t > 0.0){

		MatrixXd w0 = wm_w0_tbeg();
		ExpectationBackward* exp_i;
		std::vector<double> s_t_i;

		//update k_s if conditions are met
//		if ((w0(0,1) > 0.0) || ((w0(0,1) == 0.0) && (w0(0,0) != 0.0)) || ((w0(0,4) > 0.0) && (w0(0,0) == 0.0))){
			s_t_i.push_back(w0(0,0));
			s_t_i.push_back((w0(0,1) > 0.0)? w0(0,1):w0(0,7));

			exp_i = wm["MasCHK"];

			exp_i->s_t.push_back(s_t_i);

			wm_update_expectation_backward(exp_i, 1, true);
//		};

		s_t_i.clear();

		s_t_i.push_back(w0(0,2));
		s_t_i.push_back((w0(0,2) > 0.0)? w0(0,3)/w0(0,2):w0(0,8));

		exp_i = wm["MasGC"];

		exp_i->s_t.push_back(s_t_i);

		wm_update_expectation_backward(exp_i, 1, true);

		s_t_i.clear();

		if (w.t > 0.0){
			exp_i = wm["api"];

			s_t_i.push_back(w0(0,5));
			exp_i->s_t.push_back(s_t_i);

			wm_update_expectation_backward(exp_i, 0, false);

			s_t_i.clear();

			exp_i = wm["fi_ti"];

			s_t_i.push_back(w0(0,6));
			exp_i->s_t.push_back(s_t_i);

//			wm_update_expectation_backward(exp_i, 0, false);
            wm_update_expectation_backward(exp_i, 0, true);

		};

        if (param->opt_TYPE == "QL"){
            wm_update_Q();

        };

        if (param->opt_TYPE == "mRE"){
            wm_update_mRE();

        };

	};

};

void
H::wm_update_expectation_backward(ExpectationBackward* exp_i, int p_position, bool FLAG_UPDATE_V){

	std::vector<double> p;

	int i_s_t_1_max = 0;
	long i_s_t_max = 0;

	//depending on the length of the wm and accumulated number of prices
	if (std::isinf(param->WM_LENGTH)){
		i_s_t_1_max = exp_i->s_t_1["n"];
		i_s_t_max = exp_i->s_t.size();
	}else{
		i_s_t_1_max = std::min(std::max(param->WM_LENGTH - exp_i->s_t.size(), 0.0), exp_i->s_t_1["n"]);
		i_s_t_max = std::min(param->WM_LENGTH, (double)exp_i->s_t.size());
	};

	for (int i = 0; i < i_s_t_1_max; i++){
		p.push_back(exp_i->s_t_1["mu"]);
	};

	//push other prices
	for (std::size_t i = (exp_i->s_t.size() - i_s_t_max);i < exp_i->s_t.size();i++){
		p.push_back(exp_i->s_t[i][p_position]);
	};

	MatrixXd mean_variance = wm_mean_variance(p);

	exp_i->mu = mean_variance(0,0);
	exp_i->n += 1.0;

    if (FLAG_UPDATE_V){
        exp_i->v = mean_variance(1,0);

        if (exp_i->v <= 0.0){
            exp_i->v = exp_i->mu * 0.01;
        };

    };

};

Eigen::MatrixXd
H::wm_mean_variance(std::vector<double> &x){
	MatrixXd mean_variance(2,1);

	//gets mean and variance
	double sum = std::accumulate(x.begin(), x.end(), 0.0);
	double mean = sum / x.size();
	std::vector<double> diff(x.size());
	std::transform(x.begin(), x.end(), diff.begin(),
	               std::bind2nd(std::minus<double>(), mean));
	double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
    //	double stdev = std::sqrt(sq_sum / x.size());
	double variance = sq_sum/x.size();

	mean_variance(0,0) = mean;
	mean_variance(1,0) = variance;

	return mean_variance;
};

Eigen::MatrixXd
H::wm_w0_tbeg(){
	MatrixXd w0(1,9);

	long life_length = account->asCHK_q.size();

	w0(0,0) = account->asCHK_q.at(life_length - 2);
	w0(0,1) = account->asCHK_p.at(life_length - 2);
	w0(0,2) = account->asGC_q.at(life_length - 2);
	w0(0,3) = account->asGC_pq.at(life_length - 2);

	w0(0,4) = l_ask.q_t_0;
	w0(0,5) = account->FI_div_t.at(life_length - 2) + account->asCHK_p_t.at(life_length - 2);
	w0(0,6) = account->FI_div_t.at(life_length - 2);

	w0(0,7) = w.ml->market_price.at(w.t - 1)->p;
	w0(0,8) = w.mc->market_price.at(w.t - 1)->p;

    //	std::cout << w0 << std::endl;

	return w0;
};

Eigen::MatrixXd
H::_s0(){
	//money holdings
	s0(0,0) = ass_asCBDt0.front()->q;

	s0(0,1) = ass_asHK.front()->q;

	s0(0,2) = 0.0;
	//labor to be supplied
	for (auto c:ass_asCHK){
		s0(0,2) += c->q;
	};

	//amount of good c
	s0(0,3) = ass_asGC.front()->q;

	//expected price on labor market
	s0(0,4) = wm["MasCHK"]->mu;

	//number of observations
	s0(0,5) = wm["MasCHK"]->n;

	//expected price on goods market
	s0(0,6) = wm["MasGC"]->mu;

	//number of observations
	s0(0,7) = wm["MasGC"]->n;

	//average past income
	s0(0,8) = wm["api"]->mu;

	s0(0,9) = wm["api"]->n;

	//current income
	s0(0,10) = account->FI_div_t.back() + account->asCHK_p_t.back();

	//to be used in max routinue
	//current signed labor contracts - q
	s0(0,11) = 0.0;

	//current signed labor contracts - p
	s0(0,12) = 0.0;

	//financial income
	s0(0,13) = wm["fi_ti"]->mu;

	s0(0,14) = wm["fi_ti"]->n;

	//variance of labor market
	s0(0,15) = wm["MasCHK"]->v;

	//variance of goods market
	s0(0,16) = wm["MasGC"]->v;

	//variance of financial income
	s0(0,17) = wm["fi_ti"]->v;

	//

	return s0;
};

void
H::opt_CS(MatrixXd* s0,  MatrixXd* theta_x, int N){

//	N = 1;

	//gets matrix of thetas
	//prepare initial matrix
	MatrixXd m_s0 = MatrixXd::Zero(N, s0->cols());

	m_s0.rowwise() += s0->row(0);

	//allocate space to the matrix
	MatrixXd n_w;
	MatrixXd n_x;
	MatrixXd n_s = MatrixXd::Zero(N, s0->cols());
	MatrixXd n_c;

	//create matrix for the grid - small size here
	MatrixXd grid(3,3);

    create_decision_grid(grid,0);

    if (w.param->SIMULATION_MODE == "test"){
        Tools::mgrid_test(grid, &theta_x_all);

    } else{

        Tools::mgrid(grid, &theta_x_all);
    };

    //	std::cout << theta_x_all.transpose() << "\n";

	//create random number generators for the implementation

	boost::normal_distribution<> nd_w1((*s0)(0,4), pow((*s0)(0,15),0.5));
	boost::normal_distribution<> nd_w2((*s0)(0,6), pow((*s0)(0,16),0.5));
	boost::normal_distribution<> nd_w3((*s0)(0,13), pow((*s0)(0,17),0.5));

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w1(w.rng, nd_w1);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w2(w.rng, nd_w2);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w3(w.rng, nd_w3);

    if (w.param->SIMULATION_MODE != "test"){

        //draw random variables
        //fast realization
        n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
        for (int i = 0; i < N; i++){
            for(int j=0; j< n_w.cols(); j++){
                if (j%3 == 0){
                    n_w(i,j) = rng_w1();
                } else {
                    if (j%3 == 1){
                        n_w(i,j) = rng_w2();
                    }else{
                        n_w(i,j) = rng_w3();
                    };

                };
                n_w(i,j) = std::max(0.0, (double)n_w(i,j));
            };
        };
    };

	//matrix of all
	MatrixXd c_all(theta_x_all.cols(),1);

	for (int i = 0 ; i < theta_x_all.cols(); i++){
        if (w.param->SIMULATION_MODE == "test"){
            n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
            for (int i = 0; i < N; i++){
                for(int j=0; j< n_w.cols(); j++){
                    if (j%3 == 0){
                        n_w(i,j) = Tools::get_normal((*s0)(0,4), pow((*s0)(0,15),0.5), w.myrng);
                    } else {
                        if (j%3 == 1){
                            n_w(i,j) = Tools::get_normal((*s0)(0,6), pow((*s0)(0,16),0.5), w.myrng);
                        }else{
                            n_w(i,j) = Tools::get_normal((*s0)(0,13), pow((*s0)(0,17),0.5), w.myrng);
                        };

                    };
                    n_w(i,j) = std::max(0.0, (double)n_w(i,j));
                };
            };
        };

		//call estimator of results of steps, given theta_x
        theta_x->row(0) = theta_x_all.col(i).transpose();
		n_x = MatrixXd::Zero(N, 3);
		n_s = m_s0;
		n_c = MatrixXd::Zero(N, param->T_MAX);
		_step_opt_CS(theta_x, &n_w, &n_x, &n_s, &n_c, param->T_MAX);

		//after n_c
		//average over n runs
//        std::cout << n_w << std::endl;
//        std::cout << n_c << std::endl;
		c_all(i,0) = (n_c * param->BETA_T).mean();

	};

    //	std::cout << c_all << "\n";

	//find all max elements
	double max = c_all(0,0);
	std::list<int> i_max;
	for (int i=0; i<c_all.rows(); i++){
		if (c_all(i,0) == max){
			i_max.push_back(i);
		}else{
			if (c_all(i,0) > max){
				max = c_all(i,0);
				i_max.clear();
				i_max.push_back(i);
			};
		}
	};

	//if more than 1 max - randomly pick
	long theta_max_i;
	if (i_max.size()>1){
		boost::random::uniform_int_distribution<> i_max_dist(0, i_max.size()-1);
		theta_max_i = i_max_dist(w.rng);
	}else{
		theta_max_i = i_max.front();
	};

	theta_x->row(0) = theta_x_all.col(theta_max_i).transpose();

    //	std::cout << "theta" << *theta_x << "\n";
};

double
H::get_status(){
	return status;
};

void
H::_step_opt_CS(MatrixXd *theta_x,
                MatrixXd *w,
                MatrixXd *x,
                MatrixXd *s,
                MatrixXd *c,
                int T){

	double l_t;
	double c_t;

    //	std::cout <<"w" << *w << "\n";

	for (int i=0; i< T; i++){

		x->col(0) = (*theta_x)(0,0) * s->col(1).array();
		x->col(1) = (*theta_x)(0,1) * s->col(4).array();

		//labor market results
		//if wage is less than realized wage - get hired, otherwise zero
		s->col(11) = (w->col(i*3).array() >= x->col(1).array()).cast<double>().array() *x->col(0).array();
		s->col(12) = w->col(i*3);

        //		auto FLAG_UPDATE = ((s->col(12) > 0.0).array() ||
        //							((s->col(12) == 0.0).array() &&
        //							(s->col(11) != 0.0).array()) ||
        //							((x->col(0) > 0.0).array() &&
        //							(s->col(11) == 0.0).array()));

		//TODO update inside , not coded for now
        //		if (param->wm_INSIDE_UPDATE){
        //		};

		//made consumption good decision
		x->col(2) = (*theta_x)(0,2) * s->col(0).array();

		//buy consumption goods , assume all goods are consumed in the previous
		//period, so no addition here
		for (int j=0; j<s->rows(); j++){
			if ((*w)(j,i*3 + 1) > 0.0){
				(*s)(j,3) = (*x)(j,2) / (*w)(j,i*3 + 1);

				//for speed calculate goal in this cycle
				//stores realization of a goal
				//as couldn't pass block need to calculate in place?

                //				(*c)(j,i) = _goal_t(&(s->block(1,s->cols(),j,0)));
			}else{
				(*s)(j,3) = 0.0;
			};

			if ((*s)(j,3) <= 0.0){
				c_t = -0.5;
//                c_t = 0.0;
			} else {
				c_t = (*s)(j,3);
			};

			l_t = (*s)(j,11);

			(*c)(j,i) = param->GOAL_T_theta(0,0) * log(1+c_t) + param->GOAL_T_theta(0,1) * (1-l_t);
//            (*c)(j,i) = param->GOAL_T_theta(0,0) * log(0.5+c_t) + param->GOAL_T_theta(0,1) * (1-l_t);

		};

		//account for money being spent
		s->col(0) = s->col(0).array() - w->col(i*3 + 1).array() * s->col(3).array();

		//labor payments
		s->col(0) = s->col(0).array() + s->col(11).array() * s->col(12).array();

		//dividend payment
		s->col(0) += w->col(i*3 + 2);

        //		std::cout << s->col(0) << "\n";
//        std::cout << *s << "\n";
        //		std::cout << *c << "\n";
        //		std::cout << *x << "\n";

		//skipped, because they are assigned, not added in a cycle
		//zero labor contracts
		//zero consumption good

	};

};

void
H::_bf(Eigen::MatrixXd* s, Eigen::MatrixXd* ret){
    (*ret)(0,0) = (*s)(0,0);
};

void
H::_bf(Eigen::Block<Eigen::MatrixXd>& s, Eigen::MatrixXd* ret){
    (*ret)(0,0) = s(0,0);
};

double
H::_V(Eigen::MatrixXd* s, Eigen::MatrixXd* phi_f, Eigen::MatrixXd& theta_V){
    _bf(s, phi_f);

    return (theta_V*(*phi_f).transpose()).sum();

};

double
H::_V(Eigen::Block<Eigen::MatrixXd>& s, Eigen::MatrixXd* phi_f, Eigen::MatrixXd& theta_V){
    _bf(s, phi_f);

    return (theta_V*(*phi_f).transpose()).sum();

};

Eigen::MatrixXd
H::_API_LM(Eigen::MatrixXd* s0, int N, int M){
    //Approximate policy iteration using linear models.
    //
    //p.407 ADP
    //

    //fix basis functions
    long n_theta_t = param->ADP_BF_N;

    //inner theta
    //theta for now and future
    Eigen::MatrixXd theta_V_n = Eigen::MatrixXd::Constant(1, n_theta_t, 1);

    //policy theta
    Eigen::MatrixXd theta_V_pi = theta_V;

    Eigen::MatrixXd s_n_m;
    Eigen::MatrixXd v_n_m;
    Eigen::MatrixXd x_n_m(1,3);
    Eigen::MatrixXd phi(1, param->ADP_BF_N);
    Eigen::MatrixXd phi1(1, param->ADP_BF_N);

    for (int n=0; n<N; n++){
        theta_V_n = theta_V_pi;

        s_n_m = MatrixXd::Zero(M+1, s0->cols());
        s_n_m.row(0) += s0->row(0);
        //v_n_m_T1 = 0
        v_n_m = Eigen::MatrixXd::Constant(M, n_theta_t, 0.0);

        for (int m=0; m<M; m++){

            Eigen::Block<Eigen::MatrixXd> s = s_n_m.block(m,0,1,(*s0).cols());

            //choose action, takes reference to s
            _opt_CS_s_V(s, x_n_m, theta_V_pi, param->opt_CS_N);

            s_n_m.block(m+1,0,1,(*s0).cols()) = s;

            Eigen::Block<Eigen::MatrixXd> s1 = s_n_m.block(m+1,0,1,(*s0).cols());
            s = s_n_m.block(m,0,1,(*s0).cols());

            //make step given action, to update state and return value function
            double _c = _c_theta_x(x_n_m, s1, theta_V_pi);

            double c_n_m = _c - _V(s1,&phi,theta_V_pi);

            _bf(s,&phi);
            _bf(s1,&phi1);
            Eigen::MatrixXd v_n_m = phi - param->BETA*phi1;

            //            std::cout << s_n_m.row(m) << std::endl;
            //            std::cout << s << std::endl;
            //
            //            std::cout << s_n_m.row(m+1) << std::endl;
            //            std::cout << theta_V_pi << std::endl;
            //            std::cout << theta_V_n << std::endl;

            //update theta_V_n
            theta_V_n = _RLS(theta_V_n,
                             v_n_m,
                             s,
                             m,
                             c_n_m);
            //assume that only 1 element in v and restrict it
            if (theta_V_n(0,0) > 1000){
                theta_V_n(0,0) = 1000;
            };
            if (theta_V_n(0,0) < 0.0){
                theta_V_n(0,0) = 0.01;
            };

        };

        theta_V_pi = theta_V_n;
    };

    //std::cout << theta_V_pi << std::endl;
    return theta_V_pi;
};

Eigen::MatrixXd
H::_RLS(Eigen::MatrixXd& theta, Eigen::MatrixXd& v, Eigen::Block<Eigen::MatrixXd>& s, int i, double c){

    //i - iteration if i = 0 - initialize B
    //for each theta_t:
    Eigen::MatrixXd B_n_1;

    if (i == 0){
        //identity matrix
        double e_B_0 = 0.0005;

        //B(n-1)
        B_n_1 = e_B_0 * Eigen::MatrixXd::Identity(param->ADP_BF_N, param->ADP_BF_N);

    }else{
        B_n_1 = B_n_1_RLS;
    };

    //container for basis functions
    Eigen::MatrixXd phi(1, param->ADP_BF_N);
    _bf(s,&phi);

    double e_n = c - (v.transpose()*theta)(0,0);

    double gamma_n = 1 + ((v.transpose()*B_n_1)*phi)(0,0);

    Eigen::MatrixXd B_n = B_n_1 - 1/gamma_n *((B_n_1*(phi*v.transpose()))*B_n_1);

    Eigen::MatrixXd theta_n = theta + 1/gamma_n * ((e_n*B_n_1)*phi);

    //    std::cout << 1/gamma_n * ((e_n*B_n_1)*phi) << std::endl;

    //    std::cout << theta_n << std::endl;

    B_n_1_RLS = B_n;

    return theta_n;

};

void
H::_opt_CS_s_V(Eigen::Block<Eigen::MatrixXd>& s0,  Eigen::MatrixXd& theta_x, Eigen::MatrixXd& theta_V, int N){

    //	N = 1;

	//gets matrix of thetas
	//prepare initial matrix
	MatrixXd m_s0 = MatrixXd::Zero(N, s0.cols());

	m_s0.rowwise() += s0.row(0);

	//allocate space to the matrix
	MatrixXd n_w;
	MatrixXd n_x;
	MatrixXd n_s = MatrixXd::Zero(N, s0.cols());
	MatrixXd n_c;
    MatrixXd v_bf_ret = MatrixXd::Zero(1, param->ADP_BF_N);
    MatrixXd n_v;

	//create matrix for the grid - small size here
	MatrixXd grid(3,3);

    create_decision_grid(grid,0);

    if (w.param->SIMULATION_MODE == "test"){
        Tools::mgrid_test(grid, &theta_x_all);

    } else{

        Tools::mgrid(grid, &theta_x_all);
    };

	//create random number generators for the implementation

	boost::normal_distribution<> nd_w1(s0(0,4), pow(s0(0,15),0.5));
	boost::normal_distribution<> nd_w2(s0(0,6), pow(s0(0,16),0.5));
	boost::normal_distribution<> nd_w3(s0(0,13), pow(s0(0,17),0.5));

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w1(w.rng, nd_w1);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w2(w.rng, nd_w2);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w3(w.rng, nd_w3);

    if (w.param->SIMULATION_MODE != "test"){

        //draw random variables
        //fast realization
        n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
        for (int i = 0; i < N; i++){
            for(int j=0; j< n_w.cols(); j++){
                if (j%3 == 0){
                    n_w(i,j) = rng_w1();
                } else {
                    if (j%3 == 1){
                        n_w(i,j) = rng_w2();
                    }else{
                        n_w(i,j) = rng_w3();
                    };

                };
                n_w(i,j) = std::max(0.0, (double)n_w(i,j));
            };
        };
    };

	//matrix of all
	MatrixXd c_all(theta_x_all.cols(),1);

	for (int i = 0 ; i < theta_x_all.cols(); i++){
        if (w.param->SIMULATION_MODE == "test"){
            n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
            for (int i = 0; i < N; i++){
                for(int j=0; j< n_w.cols(); j++){
                    if (j%3 == 0){
                        n_w(i,j) = Tools::get_normal(s0(0,4), pow(s0(0,15),0.5), w.myrng);
                    } else {
                        if (j%3 == 1){
                            n_w(i,j) = Tools::get_normal(s0(0,6), pow(s0(0,16),0.5), w.myrng);
                        }else{
                            n_w(i,j) = Tools::get_normal(s0(0,13), pow(s0(0,17),0.5), w.myrng);
                        };

                    };
                    n_w(i,j) = std::max(0.0, (double)n_w(i,j));
                };
            };
        };

		//call estimator of results of steps, given theta_x
		theta_x.row(0) = theta_x_all.col(i).transpose();
		n_x = MatrixXd::Zero(N, 3);
		n_s = m_s0;
		n_c = MatrixXd::Zero(N, 1);
        n_v = MatrixXd::Zero(N, 1);
		_step_opt_CS(theta_x, &n_w, &n_x, &n_s, &n_c, &n_v, theta_V, &v_bf_ret, 1);

		//after n_c
		//average over n runs
        c_all(i,0) = (n_c + param->BETA*n_v).mean();

	};

    //    std::cout << (n_c + param->BETA*n_v).mean() << std::endl;

	//find all max elements
	double max = c_all(0,0);
	std::list<int> i_max;
	for (int i=0; i<c_all.rows(); i++){
		if (c_all(i,0) == max){
			i_max.push_back(i);
		}else{
			if (c_all(i,0) > max){
				max = c_all(i,0);
				i_max.clear();
				i_max.push_back(i);
			};
		}
	};

	//if more than 1 max - randomly pick
	long theta_max_i;
	if (i_max.size()>1){
		boost::random::uniform_int_distribution<> i_max_dist(0, i_max.size()-1);
		theta_max_i = i_max_dist(w.rng);
	}else{
		theta_max_i = i_max.front();
	};

	theta_x.row(0) = theta_x_all.col(theta_max_i).transpose();

    //    std::cout << theta_x << std::endl;
};

void
H::_step_opt_CS(MatrixXd& theta_x,
                MatrixXd *w,
                MatrixXd *x,
                MatrixXd *s,
                MatrixXd *c,
                MatrixXd* v,
                MatrixXd& theta_v,
                MatrixXd* ret,
                int T){

	double l_t;
	double c_t;

	//zero vector
	auto s_zero = MatrixXd::Zero(s->rows(),1);
    Eigen::Block<Eigen::MatrixXd> s_block = s->block(0,0,1,s->cols());;

    //	std::cout <<"w" << *w << "\n";

	for (int i=0; i< T; i++){

		x->col(0) = theta_x(0,0) * s->col(1).array();
		x->col(1) = theta_x(0,1) * s->col(4).array();

		//labor market results
		//if wage is less than realized wage - get hired, otherwise zero
		s->col(11) = (w->col(i*3).array() >= x->col(1).array()).cast<double>().array() *x->col(0).array();
		s->col(12) = w->col(i*3);

		//made consumption good decision
		x->col(2) = theta_x(0,2) * s->col(0).array();

		//buy consumption goods , assume all goods are consumed in the previous
		//period, so no addition here
		for (int j=0; j<s->rows(); j++){
			if ((*w)(j,i*3 + 1) > 0.0){
				(*s)(j,3) = (*x)(j,2) / (*w)(j,i*3 + 1);

				//for speed calculate goal in this cycle
				//stores realization of a goal
				//as couldn't pass block need to calculate in place?

                //				(*c)(j,i) = _goal_t(&(s->block(1,s->cols(),j,0)));
			}else{
				(*s)(j,3) = 0.0;
			};

			if ((*s)(j,3) <= 0.0){
				c_t = -0.5;
//                c_t = 0.0;
			} else {
				c_t = (*s)(j,3);
			};

			l_t = (*s)(j,11);

			(*c)(j,i) = param->GOAL_T_theta(0,0) * log(1+c_t) + param->GOAL_T_theta(0,1) * (1-l_t);
//            (*c)(j,i) = param->GOAL_T_theta(0,0) * log(0.5+c_t) + param->GOAL_T_theta(0,1) * (1-l_t);

		};

		//account for money being spent
		s->col(0) = s->col(0).array() - w->col(i*3 + 1).array() * s->col(3).array();

		//labor payments
		s->col(0) = s->col(0).array() + s->col(11).array() * s->col(12).array();

		//dividend payment
		s->col(0) += w->col(i*3 + 2);

        //zero out labor contracts
        s->col(11) = s_zero;
        s->col(12) = s_zero;
        //zero out consumption goods
        s->col(3) = s_zero;

        //add value function estimation
        for (int j=0; j < s->rows(); j++){
            s_block  = s->block(j,0,1,s->cols());

            (*v)(j,i) = _V(s_block,ret, theta_V);
        };

	};

};

double
H::_c_theta_x(Eigen::MatrixXd& theta_x, Eigen::Block<Eigen::MatrixXd>& s0, Eigen::MatrixXd& theta_V){

    int N = 1;
    double _c = 0.0;

    //    std::cout << s0 << std::endl;

	//gets matrix of thetas
	//prepare initial matrix
	MatrixXd m_s0 = MatrixXd::Zero(N, s0.cols());

	m_s0.rowwise() += s0.row(0);

	//allocate space to the matrix
	MatrixXd n_w;
	MatrixXd n_x = MatrixXd::Zero(N, 3);
	MatrixXd n_s = MatrixXd::Zero(N, s0.cols());
    MatrixXd v_bf_ret = MatrixXd::Zero(1, param->ADP_BF_N);
	MatrixXd n_c = MatrixXd::Zero(N, 1);;
    MatrixXd n_v = MatrixXd::Zero(N, 1);;

	//create random number generators for the implementation

	boost::normal_distribution<> nd_w1(s0(0,4), pow(s0(0,15),0.5));
	boost::normal_distribution<> nd_w2(s0(0,6), pow(s0(0,16),0.5));
	boost::normal_distribution<> nd_w3(s0(0,13), pow(s0(0,17),0.5));

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w1(w.rng, nd_w1);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w2(w.rng, nd_w2);

	boost::variate_generator<boost::mt19937&,
    boost::normal_distribution<>> rng_w3(w.rng, nd_w3);

    if (w.param->SIMULATION_MODE != "test"){

        //draw random variables
        //fast realization
        n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
        for (int i = 0; i < N; i++){
            for(int j=0; j< n_w.cols(); j++){
                if (j%3 == 0){
                    n_w(i,j) = rng_w1();
                } else {
                    if (j%3 == 1){
                        n_w(i,j) = rng_w2();
                    }else{
                        n_w(i,j) = rng_w3();
                    };

                };
                n_w(i,j) = std::max(0.0, (double)n_w(i,j));
            };
        };
    };

    //redraw random in comparative with Python mode
    if (w.param->SIMULATION_MODE == "test"){
        n_w = MatrixXd::Zero(N, 3 * param->T_MAX);
        for (int i = 0; i < N; i++){
            for(int j=0; j< n_w.cols(); j++){
                if (j%3 == 0){
                    n_w(i,j) = Tools::get_normal(s0(0,4), pow(s0(0,15),0.5), w.myrng);
                } else {
                    if (j%3 == 1){
                        n_w(i,j) = Tools::get_normal(s0(0,6), pow(s0(0,16),0.5), w.myrng);
                    }else{
                        n_w(i,j) = Tools::get_normal(s0(0,13), pow(s0(0,17),0.5), w.myrng);
                    };

                };
                n_w(i,j) = std::max(0.0, (double)n_w(i,j));
            };
        };
    };

    //call estimator of results of steps, given theta_x
    n_s = m_s0;
    _step_opt_CS(theta_x, &n_w, &n_x, &n_s, &n_c, &n_v, theta_V, &v_bf_ret, 1);
    _c = (n_c + param->BETA*n_v).mean();

    s0.row(0) = n_s.row(0);

    //    std::cout << s0 << std::endl;

    return _c;

};

void
H::opt_QL(){
    //find best action for the state

    //find current bin for the state
    _s0();
    std::vector<double> s_bin = _place_state_QL(s0);
    s_t_bin = s_bin;
    std::vector<int> Q_s;

    //create list of all indexes that correspond to current state
    for (int i = 0; i < s_bin.size(); i++){
        for (int j = 0; j< Q.cols(); j++){
            if (_is_bin(j, i, s_bin)){
                Q_s.push_back(j);
            };

        };
    };

    //find index with max Q
    std::vector<int> Q_max;
    double max = Q(4,Q_s.at(0));

    for (auto j:Q_s){
        if (Q(4,j) > max){
            max = Q(4,j);
            Q_max.clear();
            Q_max.push_back(j);

        }else{
            if (Q(4,j) == max){
                Q_max.push_back(j);
            };
        };

    };

    boost::random::uniform_01<> _exp_dist;
    double exp_rate = _exp_dist(w.rng);

    boost::random::uniform_int_distribution<> Q_dist(0, Q.cols()-1);
    long theta_max_i;

    if (exp_rate < param->QL_experimental_rate){
        theta_max_i = Q_dist(w.rng);
    }else{
        //pick randomly best action
        if (Q_max.size()>1){
            boost::random::uniform_int_distribution<> Q_max_dist(0, Q_max.size()-1);
            theta_max_i = Q_max.at(Q_max_dist(w.rng));

        }else{
            theta_max_i = Q_max.front();
        };
    };

    theta_x_t_bin.push_back(theta_max_i);

    //transform from index to decision
    theta_x.row(0) = Q.block(s_bin.size(),theta_max_i,3,1).transpose();

};

bool
H::_is_bin(int j, int i, std::vector<double>& s_bin){
    bool is_bin = false;

    if (i < s_bin.size()){
        is_bin = (Q(i,j) == Q_bin.at(i).at(s_bin.at(i))) && _is_bin(j, i+1, s_bin);
        //        std::cout << (Q(i,j) == s_bin.at(i)) << std::endl;
        //        std::cout << _is_bin(j, i+1, s_bin) << std::endl;
    }else{
        is_bin = true;
    };

    return is_bin;
};

void
H::wm_update_Q(){
    //updates Q matrix
    //reward
    double R_t1 = account->g_t.at(account->g_t.size()-2);

    //new state
    _s0();
    std::vector<double> s_bin = _place_state_QL(s0);
    std::vector<int> Q_s;

    //create list of all indexes that correspond to current state
    for (int i = 0; i < s_bin.size(); i++){
        for (int j = 0; j< Q.cols(); j++){
            if (_is_bin(j, i+1, s_bin)){
                Q_s.push_back(j);
            };

        };
    };

    //find index with max Q
    std::vector<int> Q_max;
    double max = Q(4,Q_s.at(0));

    for (auto j:Q_s){
        if (Q(4,j) > max){
            max = Q(4,j);
            Q_max.clear();
            Q_max.push_back(j);

        }else{
            if (Q(4,j) == max){
                Q_max.push_back(j);
            };
        };

    };

    //pick best action
    long theta_max_i;
    long max_i;
    if (Q_max.size()>1){
        boost::random::uniform_int_distribution<> Q_max_dist(0, Q_max.size()-1);
        max_i = Q_max_dist(w.rng);
        theta_max_i = Q_max.at(max_i);
    }else{
        theta_max_i = Q_max.front();
    };

    //update Q value
    Q(4,theta_x_t_bin.back()) = Q(4,theta_x_t_bin.back())
    + Q(5,theta_x_t_bin.back())
    * (R_t1 + param->BETA*Q(4,theta_max_i) - Q(4,theta_x_t_bin.back()));
    //    std::cout << Q << std::endl;

};

void
H::_set_QL(){
    //setup QL matrix
    //create matrix for the grid - small size here
	Q_grid = Eigen::MatrixXd::Zero(6,3);

    //money and stock of goods on hand
    Q_grid(0,0) = 0.0;
    Q_grid(0,1) = 10.0;
    Q_grid(0,2) = ((Q_grid(0,1) - Q_grid(0,0))/2);

    create_decision_grid(Q_grid, 1);

    //Q factors
    Q_grid(4,0) = 0.0;
    Q_grid(4,1) = 0.1;
    Q_grid(4,2) = 1.0;

    Q_grid(5,0) = param->QL_L; //speed of learning
    Q_grid(5,1) = Q_grid(5,0) + 0.1;
    Q_grid(5,2) = Q_grid(5,0) + 1.0;

    if (w.param->SIMULATION_MODE == "test"){
        Tools::mgrid_test(Q_grid, &Q);

    } else{

        Tools::mgrid(Q_grid, &Q);
    };

    create_bin_values(Q_grid, Q_bin);

    //update Q to push to hiring all of them
    for (int j = 0; j < Q.cols(); j++){
        if (Q(1,j) == Q_bin.at(1).back()){
            Q(4,j) = 0.05;
        };
    };

    //    std::cout << Q << std::endl;

    //    Tools::print_vector(Q_bin);

};

void
H::create_bin_values(Eigen::MatrixXd& _grid, std::vector<std::vector<double>>& _bin){
    long N_rows = _grid.rows();
	int n_steps_i;
	double n_steps_i_int;

	double val;
    std::vector<double> values_temp;

    //create matrix of bin values
    //create list of values
	for (int i=0; i < N_rows; i++){
		//n_steps
		n_steps_i_int = (_grid(i,1) - _grid(i,0))/_grid(i,2);

		n_steps_i = static_cast<int>(floor(n_steps_i_int)) + 1;

		for (int j=0; j<n_steps_i; j++){
			val = _grid(i,0) + _grid(i,2)*j;
			values_temp.push_back(val);
		};

		_bin.push_back(values_temp);
		values_temp.clear();
	};

};

std::vector<double>
H::_place_state_QL(Eigen::MatrixXd& s){
    std::vector<double> s_bin;

    //pick first and compare
    //push values for bins ina  vector

    bool FLAG_PLACED = false;

    int j = Q_bin.at(0).size()-1;
    while ((j>=0) && !FLAG_PLACED){

        if (s(0,0) >= Q_bin.at(0).at(j)){
            s_bin.push_back(j);
            FLAG_PLACED = true;
        };
        j -= 1;
    };

    return s_bin;
};

void
H::create_decision_grid(Eigen::MatrixXd& grid, int begin_index){
    int i = begin_index;

    if (param->GRID == "small"){
		grid(i,0) = 0.0;
		grid(i,1) = 1.1;
		grid(i,2) = 1.0;
		grid(i+1,0) = 0.8;
		grid(i+1,1) = 1.25;
		grid(i+1,2) = 0.2;
		grid(i+2,0) = 0.0;
		grid(i+2,1) = 1.0;
		grid(i+2,2) = 0.5;
	};

    if (param->GRID == "big"){
		grid(i,0) = 0.0;
		grid(i,1) = 1.1;
		grid(i,2) = 1.0;
		grid(i+1,0) = 0.1;
		grid(i+1,1) = 2.1;
		grid(i+1,2) = 0.45;
		grid(i+2,0) = 0.0;
		grid(i+2,1) = 1.0;
		grid(i+2,2) = 0.5;

	};
    if (param->GRID == "test"){

        grid(i,0) = 1.0;
        grid(i,1) = 1.1;
        grid(i,2) = 1.0;

        grid(i+1,0) = 0.8;
        grid(i+1,1) = 1.2;
        grid(i+1,2) = 1.0;

        grid(i+2,0) = 0.5;
        grid(i+2,1) = 1.1;
        grid(i+2,2) = 1.0;

    };

};

void
H::_set_mRE(){
    //
    mRE_grid = Eigen::MatrixXd::Zero(4,3);
    create_decision_grid(mRE_grid, 0);
    mRE_grid(3,0) = 1.0;
    mRE_grid(3,1) = 1.1;
    mRE_grid(3,2) = 1.0;

    if (w.param->SIMULATION_MODE == "test"){
        Tools::mgrid_test(mRE_grid, &mRE);

    } else{

        Tools::mgrid(mRE_grid, &mRE);
    };

    create_bin_values(mRE_grid, mRE_bin);

    //update mRE to push to hiring all of them
    for (int j = 0; j < mRE.cols(); j++){
        if (mRE(0,j) == mRE_bin.at(0).back()){
            mRE(3,j) = 1.05;
        };
    };

};

void
H::opt_mRE(){
    //form matrix of probabilities
    double sum_prob = 0.0;

    for (int j=0; j<mRE.cols();j++){
        sum_prob += exp(mRE(3,j)/param->mRE_T);
    };

    std::vector<double> probs;

    for (int j=0; j<mRE.cols();j++){
        probs.push_back(exp(mRE(3,j)/param->mRE_T)/sum_prob);
    };

    //roll weighted dice
    boost::random::discrete_distribution<> dist(probs.begin(), probs.end());

    int theta_i = dist(w.rng);

    theta_x_t_bin.push_back(theta_i);

    //transform from index to decision
    theta_x.row(0) = mRE.block(0,theta_i,3,1).transpose();

};

void
H::wm_update_mRE(){
    //adjustment matrix
    Eigen::MatrixXd _E_re  = Eigen::MatrixXd::Zero(1, mRE.cols());

    //reward
    double R_t1 = account->g_t.at(account->g_t.size()-2);

    //adjustment
    _E_re = mRE.row(3) * (param->mRE_EPSILON/(mRE.cols()-1));

    //include reward
    _E_re(0,theta_x_t_bin.back()) = R_t1 * (1 - param->mRE_EPSILON);

    //update whole matrix
    mRE.row(3) = mRE.row(3) * (1 - param->mRE_PHI) + _E_re;

};

bool
H::_PS_accept_PO(MessagePSSendPayment* mes){
	return true;
};

ContractBDt0*
H::_PS_contract(){
	return ass_asCBDt0.front();
};


#include <EigenPerformance.h>
#include <iostream>
#include <chrono>

using Eigen::Matrix3f;
using Eigen::Matrix;

typedef std::chrono::high_resolution_clock::time_point time_point;
typedef std::chrono::high_resolution_clock::duration duration;

unsigned long long max_counter = (unsigned long long)1e6;

// the compiler is not allowed to optimize out global variables
Matrix3f inverse3x3;
Matrix<float,6,6> inverse6x6;
Matrix<float,4,100> y;
Matrix<float,2,1> y2;

void test_invert(){
    time_point begin;
    time_point end;

    duration sum = duration::zero();
    unsigned long long counter = 0;

    while (counter < max_counter){
        Matrix3f test;
        test << Matrix3f::Random();

        if(test.determinant()){
            begin = std::chrono::high_resolution_clock::now();
            inverse3x3 = test.inverse();
            end = std::chrono::high_resolution_clock::now();

            // we assume, that difference doesn't exeed the size of int
            sum += end - begin;

            counter++;

            if(counter%(max_counter/10) == 0){
               std::cout << "." << std::flush;
            }
        }
    }

    std::cout << std::endl;
    std::cout << "average time 3x3: " << sum.count()/counter << " ns" << std::endl;

    sum = duration::zero();
    counter = 0;

    while (counter < max_counter ){
        Matrix<float,6,6> test;

        test << Matrix<float,6,6>::Random();

        if(test.determinant()){
            begin = std::chrono::high_resolution_clock::now();
            inverse6x6 = test.inverse();
            end = std::chrono::high_resolution_clock::now();

            // we assume, that difference doesn't exeed the size of int
            sum += end - begin;

            counter++;

            if(counter%(max_counter/10) == 0){
               std::cout << "." << std::flush;
            }
        }
    }

    std::cout << std::endl;
    std::cout << "average time 6x6: " << sum.count()/max_counter << " ns" << std::endl;
}

void test_sse(){
    time_point begin;
    time_point end;

    duration sum = duration::zero();
    unsigned long long counter = 0;

    Matrix<float, 4,4> A;
    Matrix<float, 4,100> x;

    while (counter < max_counter ){
        A << Matrix<float,4,4>::Random();
        x << Matrix<float,4,100>::Random();

        begin = std::chrono::high_resolution_clock::now();
        y = A*x;
        end = std::chrono::high_resolution_clock::now();

        // we assume, that difference doesn't exeed the size of int
        sum += end - begin;

        counter++;

        if(counter%(max_counter/10) == 0){
            std::cout << "." << std::flush;
        }
    }

    std::cout << std::endl;
    std::cout << "average time 4x4*4x100 float: " << sum.count()/max_counter << " ns" << std::endl;

    sum = duration::zero();
    counter = 0;

    Matrix<float, 2,2> A2;
    Matrix<float, 2,1> x2;

    while (counter < max_counter ){
        A2 << Matrix<float,2,2>::Random();
        x2 << Matrix<float,2,1>::Random();

        begin = std::chrono::high_resolution_clock::now();
        y2 = A2*x2;
        end = std::chrono::high_resolution_clock::now();

        // we assume, that difference doesn't exeed the size of int
        sum += end - begin;

        counter++;

        if(counter%(max_counter/10) == 0){
            std::cout << "." << std::flush;
        }
    }

    std::cout << std::endl;
    std::cout << "average time 2x2*2x1 float: " << sum.count()/max_counter << " ns" << std::endl;
}

int main(int /*argc*/, char** /*argv*/){
    test_invert();
    test_sse();

    return 0;
}


// (C) Copyright Renaud Detry   2007-2015.
// Distributed under the GNU General Public License and under the
// BSD 3-Clause License (See accompanying file LICENSE.txt).

/** @file */

#ifdef NUKLEI_HAS_PARTIAL_VIEW

#define CGAL_EIGEN3_ENABLED

#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/AABB_polyhedron_triangle_primitive.h>
#include <CGAL/property_map.h>
#include <CGAL/IO/read_off_points.h>
#include <CGAL/IO/read_xyz_points.h>
#include <CGAL/IO/write_xyz_points.h>
#include <CGAL/IO/Polyhedron_iostream.h>

#include <CGAL/squared_distance_3.h>
#include <CGAL/Point_with_normal_3.h>

#endif

#include <nuklei/KernelCollection.h>
#include <nuklei/ObservationIO.h>

#include <boost/shared_ptr.hpp>

#include <nuklei/KernelCollection.h>

#ifdef NUKLEI_HAS_PARTIAL_VIEW

typedef CGAL::Simple_cartesian<double> K;
typedef K::Point_3 Point;
typedef K::Plane_3 Plane;
typedef K::Vector_3 Vector;
typedef K::Segment_3 Segment;
typedef K::Line_3 Line;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::AABB_polyhedron_triangle_primitive<K,Polyhedron> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
typedef Tree::Object_and_primitive_id Object_and_primitive_id;
typedef Tree::Primitive_id Primitive_id;

typedef CGAL::Point_with_normal_3<K> Point_with_normal;
typedef std::vector<Point_with_normal> PointList;

#endif

namespace nuklei {

  typedef std::vector< std::pair< Vector3, std::vector<int> > > viewcache_t;

#ifdef NUKLEI_HAS_PARTIAL_VIEW

  inline bool isVisible(const Vector3& wtarget,
                        const Vector3& wnormal,
                        const Vector3& wcamera,
                        const Polyhedron& poly,
                        const Tree& tree,
                        const coord_t& tolerance)
  {
    if (std::fabs(wnormal.SquaredLength()-1) < FLOATTOL)
    {
      Vector3 ctot = la::normalized(wtarget-wcamera);
      double dot = wnormal.Dot(ctot);
      if (std::acos(std::fabs(dot)) > (80./180*M_PI))
      {
        return false;
      }
    }

    Point camera(wcamera.X(), wcamera.Y(), wcamera.Z());
    Point target(wtarget.X(), wtarget.Y(), wtarget.Z());

    //double d = dot();
    Segment segment_query(camera,target);
    bool visible = true;

    std::list<Object_and_primitive_id> intersections;
    tree.all_intersections(segment_query, std::back_inserter(intersections));

    int self_intersect = 0;
    for (std::list<Object_and_primitive_id>::const_iterator intersection = intersections.begin();
         intersection != intersections.end(); ++intersection)
    {
      Object_and_primitive_id op = *intersection;
      CGAL::Object object = op.first;
      Point intersectionPoint;
      if(CGAL::assign(intersectionPoint,object))
      {
        double sq2 = squared_distance(intersectionPoint, target);
        if (sq2 < tolerance*tolerance) self_intersect++;
      }
      else
      {
        // This is very unlikely (p<<0.001)
        //NUKLEI_THROW("intersection is not a point!");
      }
    }

    int num_inter = intersections.size();
    if (self_intersect > 1)
      NUKLEI_LOG("Number of self-intersections (" << self_intersect << ") greater than 1");

    if (num_inter == 0)
      visible = true;
    else
    {
      if (num_inter - self_intersect > 0)
        visible = false;
      else
        visible = true;
    }
    if (num_inter > 1 && visible)
      NUKLEI_INFO("Strange visibility at" << target);

    return visible;

  }

  inline bool isVisible(const Vector3& wtarget,
                        const Vector3& wcamera,
                        const Polyhedron& poly,
                        const Tree& tree,
                        const coord_t& tolerance)
  {
    return isVisible(wtarget,
                     Vector3::ZERO,
                     wcamera,
                     poly,
                     tree,
                     tolerance);
  }

#endif

  bool KernelCollection::isVisibleFrom(const Vector3& p, const Vector3& viewpoint,
                                       const coord_t& tolerance) const
  {
    NUKLEI_TRACE_BEGIN();
#ifdef NUKLEI_HAS_PARTIAL_VIEW
    if (!deco_.has_key(MESH_KEY))
      NUKLEI_THROW("Undefined mesh. Call buildMesh() first.");
    if (!deco_.has_key(AABBTREE_KEY))
      NUKLEI_THROW("Undefined AABB tree. Call buildMesh() first.");

    return isVisible(p, viewpoint,
                     *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY),
                     *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY),
                     tolerance);
#else
    NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    NUKLEI_TRACE_END();
  }

  bool KernelCollection::isVisibleFrom(const kernel::r3xs2p& p, const Vector3& viewpoint,
                                       const coord_t& tolerance) const
  {
    NUKLEI_TRACE_BEGIN();
#ifdef NUKLEI_HAS_PARTIAL_VIEW
    if (!deco_.has_key(MESH_KEY))
      NUKLEI_THROW("Undefined mesh. Call buildMesh() first.");
    if (!deco_.has_key(AABBTREE_KEY))
      NUKLEI_THROW("Undefined AABB tree. Call buildMesh() first.");

    return isVisible(p.loc_, p.dir_, viewpoint,
                     *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY),
                     *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY),
                     tolerance);
#else
    NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    NUKLEI_TRACE_END();
  }

  template<typename C>
  C KernelCollection::partialView(const Vector3& viewpoint,
                                  const coord_t& tolerance,
                                  const bool useViewcache,
                                  const bool useRayToSurfacenormalAngle) const
  {
    NUKLEI_TRACE_BEGIN();

    C index_collection;

    if (!useViewcache)
    {
#ifdef NUKLEI_HAS_PARTIAL_VIEW
      if (!deco_.has_key(MESH_KEY))
        NUKLEI_THROW("Undefined mesh. Call buildMesh() first.");
      if (!deco_.has_key(AABBTREE_KEY))
        NUKLEI_THROW("Undefined AABB tree. Call buildMesh() first.");

      const Polyhedron& poly = *deco_.get< boost::shared_ptr<Polyhedron> >(MESH_KEY);
      const Tree& tree = *deco_.get< boost::shared_ptr<Tree> >(AABBTREE_KEY);

      for (const_iterator v = begin(); v != end(); ++v)
      {
        Vector3 p = v->getLoc();
        Vector3 normal = Vector3::ZERO;
        if (useRayToSurfacenormalAngle)
          normal = kernel::r3xs2p(*v).dir_;
        if (isVisible(p, normal, viewpoint, poly, tree, tolerance))
          index_collection.push_back(std::distance(begin(), v));
      }
#else
      NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    }
    else
    {
      if (!deco_.has_key(VIEWCACHE_KEY))
        NUKLEI_THROW("Undefined view cache. Call buildPartialViewCache() first.");

      const viewcache_t &viewIndex = *deco_.get< boost::shared_ptr<viewcache_t> >(VIEWCACHE_KEY);

      double minDist = 1e6;
      viewcache_t::const_iterator closest = as_const(viewIndex).begin();
      for (viewcache_t::const_iterator oo = as_const(viewIndex).begin(); oo != viewIndex.end(); ++oo)
      {
        double tmp = (viewpoint-oo->first).SquaredLength();
        if (tmp < minDist*minDist)
        {
          minDist = tmp;
          closest = oo;
        }
      }
      for (std::vector<int>::const_iterator i = closest->second.begin(); i != closest->second.end(); ++i)
        index_collection.push_back(*i);
    }
    return index_collection;
    NUKLEI_TRACE_END();
  }

  std::vector<int> KernelCollection::partialView(const Vector3& viewpoint,
                                                 const coord_t& tolerance,
                                                 const bool useViewcache,
                                                 const bool useRayToSurfacenormalAngle) const
  {
    NUKLEI_TRACE_BEGIN();
#ifdef NUKLEI_HAS_PARTIAL_VIEW
    return partialView< std::vector<int> >(viewpoint, tolerance, useViewcache, useRayToSurfacenormalAngle);
#else
    NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    NUKLEI_TRACE_END();
  }

  KernelCollection::const_partialview_iterator KernelCollection::partialViewBegin(const Vector3& viewpoint,
                                                                                const coord_t& tolerance,
                                                                                const bool useViewcache,
                                                                                const bool useRayToSurfacenormalAngle) const
  {
    NUKLEI_TRACE_BEGIN();
#ifdef NUKLEI_HAS_PARTIAL_VIEW

    typedef const_partialview_iterator::index_container
    index_container;
    typedef const_partialview_iterator::index_container_ptr
    index_container_ptr;
    typedef const_partialview_iterator::index_t
    index_t;

    index_container_ptr index_collection(new index_container);
    *index_collection = partialView< index_container >(viewpoint, tolerance, useViewcache, useRayToSurfacenormalAngle);

    return const_partialview_iterator(begin(), index_collection);
#else
    NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    NUKLEI_TRACE_END();
  }

  void KernelCollection::buildPartialViewCache(const double meshTol, const bool useRayToSurfacenormalAngle)
  {
    NUKLEI_TRACE_BEGIN();
#ifdef NUKLEI_HAS_PARTIAL_VIEW
    Vector3 mean = as_const(*this).moments()->getLoc();
    double stdev = as_const(*this).moments()->getLocH();

    std::vector< Vector3 > keys;
    for (int o = 0; o < 10000; ++o)
    {
      Vector3 key = Random::uniformDirection3d();
      keys.push_back(key);
    }

    {
      double minDist2 = .15;
      std::vector< Vector3 > tmp = keys;
      keys.clear();
      for (std::vector<Vector3>::const_iterator
           i = tmp.begin();
           i != tmp.end(); ++i)
      {
        bool cnt = false;
        Vector3 iLoc = (*i);
        for (std::vector<Vector3>::const_iterator
             j = keys.begin();
             j != keys.end(); ++j)
        {
          if ( (iLoc - *j).SquaredLength() < minDist2*minDist2 )
          {
            cnt = true;
            break;
          }
        }
        if (!cnt)
        {
          keys.push_back(iLoc);
        }
      }
    }

    boost::shared_ptr<viewcache_t> viewIndex(new viewcache_t());

    for (unsigned int o = 0; o < keys.size(); ++o)
    {
      Vector3 key = keys.at(o);
      Vector3 vp = mean + key*stdev*20;
      std::vector<int> vi = as_const(*this).partialView(vp, meshTol, false, useRayToSurfacenormalAngle);
#if 0
      // debug - delete when code is considered stable
      KernelCollection v;
      for (std::vector<int>::iterator i = vi.begin(); i != vi.end(); ++i)
        v.add(as_const(*this).at(*i));
      v.computeKernelStatistics();
      kernel::base::ptr k = v.randomKernel().create();
      k->setLoc(vp);
      v.add(*k);
      v.computeKernelStatistics();
#endif
      viewIndex->push_back(std::make_pair(key, vi));
    }

    if (deco_.has_key(VIEWCACHE_KEY)) deco_.erase(VIEWCACHE_KEY);
    deco_.insert(VIEWCACHE_KEY, viewIndex);

#if 0
    // debug - delete when code is considered stable

      for (viewcache_t::iterator o = viewIndex->begin(); o != viewIndex->end(); ++o)
      {
        double d = 1e6;
        KernelCollection near;

        for (viewcache_t::iterator oo = viewIndex->begin(); oo != viewIndex->end(); ++oo)
        {
          if (oo == o) continue;
          double dd = (o->first-oo->first).Length();
          if (dd < d) {
            d = dd;
            near.clear();
            for (std::vector<int>::iterator j = oo->second.begin(); j != oo->second.end(); ++j)
              near.add(as_const(*this).at(*j));
            near.computeKernelStatistics();
            if (near.size() == 0) continue;
            kernel::base::ptr k = near.randomKernel().create();
            k->setLoc(mean + oo->first*stdev*20);
            near.add(*k);
            near.computeKernelStatistics();
          }
        }
        for (KernelCollection::iterator i = near.begin(); i != near.end(); ++i)
        {
          ColorDescriptor cd;
          cd.setColor(RGBColor(1, 0, 0));
          i->setDescriptor(cd);
        }
        for (std::vector<int>::iterator j = o->second.begin(); j != o->second.end(); ++j)
        {
          near.add(as_const(*this).at(*j));
          near.back().setLoc(near.back().getLoc()+Vector3(0.001, 0, 0));
        }
        near.computeKernelStatistics();
        if (near.size() == 0) continue;
        kernel::base::ptr k = near.randomKernel().create();
        k->setLoc(mean + o->first*stdev*20);
        near.add(*k);
        near.computeKernelStatistics();
        writeObservations("/tmp/v/" + stringify(std::distance(viewIndex->begin(), o)), near, Observation::SERIAL);
      }
#endif

#else
    NUKLEI_THROW("This function requires the partial view build of Nuklei. See http://nuklei.sourceforge.net/doxygen/group__install.html");
#endif
    NUKLEI_TRACE_END();

  }

}


// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP

#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>

#include <cmath>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail
{

template <typename T>
struct distance_measure
{
    T measure;

    distance_measure()
        : measure(T())
    {}

    bool is_small() const { return true; }
    bool is_zero() const { return true; }
    bool is_positive() const { return false; }
    bool is_negative() const { return false; }
};

template <typename T>
struct distance_measure_floating
{
    T measure;

    distance_measure_floating()
        : measure(T())
    {}

    // Returns true if the distance measure is small.
    // This is an arbitrary boundary, to enable some behaviour
    // (for example include or exclude turns), which are checked later
    // with other conditions.
    bool is_small() const { return std::abs(measure) < 1.0e-3; }

    // Returns true if the distance measure is absolutely zero
    bool is_zero() const { return measure == 0.0; }

    // Returns true if the distance measure is positive. Distance measure
    // algorithm returns positive value if it is located on the left side.
    bool is_positive() const { return measure > 0.0; }

    // Returns true if the distance measure is negative. Distance measure
    // algorithm returns negative value if it is located on the right side.
    bool is_negative() const { return measure < 0.0; }
};

template <>
struct distance_measure<long double>
    : public distance_measure_floating<long double> {};

template <>
struct distance_measure<double>
    : public distance_measure_floating<double> {};

template <>
struct distance_measure<float>
    : public distance_measure_floating<float> {};

} // detail

namespace detail_dispatch
{

// TODO: this is effectively a strategy, but for internal usage.
// It might be moved to the strategies folder.

template <typename CalculationType, typename CsTag>
struct get_distance_measure
        : not_implemented<CsTag>
{};

template <typename CalculationType>
struct get_distance_measure<CalculationType, cartesian_tag>
{
    typedef detail::distance_measure<CalculationType> result_type;

    template <typename SegmentPoint, typename Point>
    static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
                             Point const& p)
    {
        typedef CalculationType ct;

        // Construct a line in general form (ax + by + c = 0),
        // (will be replaced by a general_form structure in next PR)
        ct const x1 = geometry::get<0>(p1);
        ct const y1 = geometry::get<1>(p1);
        ct const x2 = geometry::get<0>(p2);
        ct const y2 = geometry::get<1>(p2);
        ct const a = y1 - y2;
        ct const b = x2 - x1;
        ct const c = -a * x1 - b * y1;

        // Returns a distance measure
        // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation
        // dividing by sqrt(a*a+b*b) is not necessary for this distance measure,
        // it is not a real distance and purpose is to detect small differences
        // in collinearity
        result_type result;
        result.measure = a * geometry::get<0>(p) + b * geometry::get<1>(p) + c;

        return result;
    }
};

template <typename CalculationType>
struct get_distance_measure<CalculationType, spherical_tag>
{
    typedef detail::distance_measure<CalculationType> result_type;

    template <typename SegmentPoint, typename Point>
    static result_type apply(SegmentPoint const& , SegmentPoint const& ,
                             Point const& )
    {
        // TODO, optional
        result_type result;
        return result;
    }
};

template <typename CalculationType>
struct get_distance_measure<CalculationType, geographic_tag>
        : get_distance_measure<CalculationType, spherical_tag> {};

} // namespace detail_dispatch

namespace detail
{

// Returns a (often very tiny) value to indicate its side, and distance,
// 0 (absolutely 0, not even an epsilon) means collinear. Like side,
// a negative means that p is to the right of p1-p2. And a positive value
// means that p is to the left of p1-p2.

template <typename cs_tag, typename SegmentPoint, typename Point>
static distance_measure<typename select_coordinate_type<SegmentPoint, Point>::type>
get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p)
{
    return detail_dispatch::get_distance_measure
            <
                typename select_coordinate_type<SegmentPoint, Point>::type,
                cs_tag
            >::apply(p1, p2, p);

}

} // namespace detail
#endif // DOXYGEN_NO_DETAIL

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP


#pragma once

#include <vector>
#include <boost/optional.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include "GNAObject.hh"

class HistEdgesLinear: public GNAObject,
                       public TransformationBind<HistEdgesLinear> {
public:
    HistEdgesLinear(double k, double b) : m_k(k), m_b(b) { init(); }
    HistEdgesLinear(SingleOutput& out, double k, double b) : HistEdgesLinear(k, b) { set(out); }

    void set(SingleOutput& out){ out.single() >> transformations.front().inputs.front(); }

private:
    void init();
    void types(TypesFunctionArgs& fargs);
    void func(FunctionArgs& fargs);

    double m_k;
    double m_b;

    DataType m_dt_hist_input;
    DataType m_dt_hist_output;
};