Commit 29dcc482 authored by Damien Leroux's avatar Damien Leroux
Browse files

Work in progress. POP computation not satisfying yet.

parent dd689f2f
data type f2 backcross
data type f2
3 7
*M1 ABA
*M2 ADC
......
#ifndef _MCQTL_ALGEBRAIC_GENOTYPE_H_
#define _MCQTL_ALGEBRAIC_GENOTYPE_H_
#ifndef _SPEL_ALGEBRAIC_GENOTYPE_H_
#define _SPEL_ALGEBRAIC_GENOTYPE_H_
#include "fast_polynom.h"
#include "markov_population.h"
......
#include <x2c/x2c.h>
#define EIGEN_NO_DEPRECATED_WARNING
#include <cctype>
#include <locale>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include "outbred.h"
#include "chrono.h"
#include "input.h"
#include "settings.h"
#include "banner.h"
#include "model.h"
template <typename T1, typename T2>
std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p) { return os << p.first << ':' << p.second; }
template <typename T1, typename T2>
std::ostream& operator << (std::ostream& os, const std::map<T1, T2>& m)
{
auto i = m.begin(), j = m.end();
os << '{';
if (i != j) {
os << (*i);
for (++i; i != j; ++i) {
os << ' ' << (*i);
}
}
return os << '}';
}
#include "computations.h"
#ifndef _MCQTL_BANNER_H_
#define _MCQTL_BANNER_H_
#ifndef _SPEL_BANNER_H_
#define _SPEL_BANNER_H_
/*#define VERSION_MAJOR "0"*/
/*#define VERSION_MINOR "1"*/
......
#ifndef _MCQTL_CACHE_H_
#define _MCQTL_CACHE_H_
#ifndef _SPEL_CACHE_H_
#define _SPEL_CACHE_H_
/*#include "cache/call_tuple.h"*/
#include <iostream>
struct md5_digest;
namespace cache {
template <typename V> struct value;
......@@ -9,6 +12,23 @@ namespace cache {
template <typename V> struct collection;
template <typename C, typename T, typename... D> struct computed_value;
template <typename V> struct computed_collection;
template <typename X>
struct is_value {
static const X& _();
template <typename V> static std::true_type check(const value<V>&);
static std::false_type check(...);
static const bool value = decltype(check(_()))::value;
};
struct with_output_func {
virtual ~with_output_func() {}
virtual std::ostream& output(std::ostream& os) const = 0;
virtual md5_digest& to_md5(md5_digest&) const = 0;
virtual size_t hash() const = 0;
/*virtual cache_input& from_cache(cache_input&) = 0;*/
/*virtual cache_output& to_cache(cache_output&) = 0;*/
};
}
#include "cache/md5.h"
......
#ifndef _MCQTL_3RD_PARTY_TUPLE_CALL_CODE_H_
#define _MCQTL_3RD_PARTY_TUPLE_CALL_CODE_H_
#ifndef _SPEL_3RD_PARTY_TUPLE_CALL_CODE_H_
#define _SPEL_3RD_PARTY_TUPLE_CALL_CODE_H_
/* from http://stackoverflow.com/a/10766422 */
......
#ifndef _MCQTL_CACHE_CARTESIAN_PRODUCT_H_
#define _MCQTL_CACHE_CARTESIAN_PRODUCT_H_
#ifndef _SPEL_CACHE_CARTESIAN_PRODUCT_H_
#define _SPEL_CACHE_CARTESIAN_PRODUCT_H_
namespace cache {
......@@ -45,22 +45,45 @@ template <typename Item>
}
};
struct cartesian_product_at_end_exception : std::exception {};
template <typename... ITEMS>
struct cartesian_product {
typedef typename make_sequence<sizeof...(ITEMS)>::type indices;
template <typename X> struct to_bool { typedef bool type; };
std::tuple<iterator_context<ITEMS>...> iter;
typedef std::tuple<iterator_context<ITEMS>...> iter_type;
iter_type iter;
bool at_end;
cartesian_product() : iter(), at_end(true) {}
cartesian_product(const ITEMS&... x)
: iter(x...), at_end(false)
{}
{ _debug_types(); }
cartesian_product(const std::tuple<ITEMS...>& x)
: iter(x), at_end(false)
{}
{ _debug_types(); }
cartesian_product(const cartesian_product<ITEMS...>& cp)
: iter(cp.iter), at_end(cp.at_end)
{}
{ _debug_types(); }
template <int I, int N>
struct _debug_types_impl {
typedef typename std::tuple_element<I, std::tuple<ITEMS...>>::type etype;
typedef typename std::tuple_element<I, iter_type>::type::iterator::value_type itype;
void operator () () {
/*MSG_DEBUG('#' << I << ": " << typeid(etype).name() << " / " << typeid(itype).name());*/
_debug_types_impl<I + 1, N>()();
}
};
template <int N>
struct _debug_types_impl<N, N> {
void operator () () {}
};
void _debug_types() const
{
_debug_types_impl<0, sizeof...(ITEMS)>()();
}
cartesian_product<ITEMS...>& operator = (const cartesian_product& cp)
{
......@@ -97,7 +120,7 @@ template <typename... ITEMS>
/*return getter::process(iter);*/
return _get<indices>::get(iter);
}
throw 0;
throw cartesian_product_at_end_exception();
}
struct iterator {
......@@ -120,8 +143,8 @@ template <typename... ITEMS>
return ret;
}
iterator begin() { std::cout << "BEGIN" << std::endl; return {*this}; }
iterator end() { std::cout << "END" << std::endl; return {{}}; }
iterator begin() { return {*this}; }
iterator end() { return {{}}; }
};
/*template <typename... E>*/
......
#ifndef _MCQTL_CACHE_FACTORY_H_
#define _MCQTL_CACHE_FACTORY_H_
#ifndef _SPEL_CACHE_FACTORY_H_
#define _SPEL_CACHE_FACTORY_H_
#include <vector>
#include <memory>
......@@ -16,9 +16,43 @@
#include "cartesian_product.h"
#include "file.h"
template <typename T>
using only_if_derives_from_wof = typename std::enable_if<std::is_base_of<cache::with_output_func, T>::value, T>::type;
namespace std {
template <typename... Elem>
struct hash<std::tuple<Elem...>> {
typedef std::tuple<Elem...> TupleType;
template <int I, int N>
struct hash_elem {
size_t operator () (const TupleType& t) const
{
/*std::hash<typename std::tuple_element<I, TupleType>::type> h;*/
return std::get<I>(t).hash() ^ hash_elem<I + 1, N>()(t);
}
};
template <int N>
struct hash_elem<N, N> {
size_t operator () (const TupleType& t) const
{
return 0;
}
};
size_t operator () (const TupleType& t) const
{
return hash_elem<0, sizeof...(Elem)>()(t);
}
};
/*template <typename T>*/
/*struct hash<only_if_derives_from_wof<T>> : hash<cache::with_output_func> {};*/
}
#define DEFAULT_CACHE_DIR "tmp/"
msg_handler_t::lock_type msg_handler_t::mutex;
/*msg_handler_t::lock_type msg_handler_t::mutex;*/
namespace cache {
namespace predicate {
......@@ -68,8 +102,8 @@ template <>
struct launch_impl<true> {
static std::launch& policy()
{
/*static std::launch _ = std::launch::async | std::launch::deferred;*/
static std::launch _ = std::launch::deferred;
static std::launch _ = std::launch::async | std::launch::deferred;
/*static std::launch _ = std::launch::deferred;*/
return _;
}
......@@ -101,7 +135,7 @@ template <>
static Type access(computed_type<Type>& ct) { return ct; }
};
typedef launch_impl<false> launch;
typedef launch_impl<true> launch;
template <typename Type>
using computed_type = launch::computed_type<Type>;
......@@ -112,6 +146,7 @@ struct async_computed_value : value<computed_type<Type>> {
/*virtual Type do_compute(const Dependencies&...) = 0;*/
typedef typename make_sequence<sizeof...(Dependencies)>::type indices;
using value<computed_type<Type>>::output;
typedef async_computed_value<Class, Type, Dependencies...> task_type;
std::tuple<Dependencies...> dependencies;
Type val_cache;
......@@ -133,7 +168,7 @@ struct async_computed_value : value<computed_type<Type>> {
async_computed_value(const async_computed_value<Class, Type, Dependencies...>&) = delete;
async_computed_value(async_computed_value<Class, Type, Dependencies...>&&) = delete;
virtual ~async_computed_value() { /*DEBUG("destroying task " << dependencies);*/ }
virtual ~async_computed_value() { /*MSG_DEBUG("destroying task " << dependencies);*/ }
std::string cache_filename() const
{
......@@ -151,16 +186,18 @@ struct async_computed_value : value<computed_type<Type>> {
return f.str();
}
void _fetch()
void _fetch() const
{
if (!fetched) {
fetched = true;
val_cache = launch::access(val);
task_type* mut = const_cast<task_type*>(this);
if (!mut->fetched) {
mut->fetched = true;
mut->val_cache = launch::access(mut->val);
}
}
Type v() { _fetch(); return val_cache; }
operator Type () { _fetch(); return val_cache; }
const Type& v() const { _fetch(); return val_cache; }
operator const Type& () const { _fetch(); return val_cache; }
operator Type& () { _fetch(); return val_cache; }
void move(Type& dest) { _fetch(); dest = val_cache; }
......@@ -177,20 +214,17 @@ private:
file_stat fs(path);
if (fs.exists) {
if (!fs.readable) {
ERROR("File " << path << " is not readable.", "Check permissions for file " << path);
MSG_ERROR("File " << path << " is not readable.", "Check permissions for file " << path);
unlink(path.c_str());
} else if (load(path, ret)) {
/*INFO(dependencies << " Reloading data from path " << path);*/
INFO("Reloading data from path " << path);
/*MSG_INFO("Reloading data from path " << path);*/
return ret;
} else {
/*INFO(dependencies << " Cache invalid. Computing data and caching in " << path);*/
INFO("Cache invalid. Computing data and caching in " << path);
/*MSG_INFO("Cache invalid. Computing data and caching in " << path);*/
compute_and_save(path, ret);
}
} else {
/*INFO(dependencies << " Computing data and caching in " << path);*/
INFO("Computing data and caching in " << path);
/*MSG_INFO("Computing data and caching in " << path);*/
compute_and_save(path, ret);
}
return ret;
......@@ -206,28 +240,14 @@ private:
bool load(const std::string& filename, Type& v)
{
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
std::ifstream ifs(filename);
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
cache_input ar(ifs);
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
#if 1
std::string check;
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
ar & check;
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
if (check != dependencies_digest()) {
#else
std::tuple<Dependencies...> check;
ar & check;
if (check != dependencies) {
#endif
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
return false;
}
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
ar & v;
DEBUG(__FILE__ << ':' << __LINE__ << '\t' << __func__);
return true;
}
......@@ -254,7 +274,7 @@ private:
{
return Class::do_compute(t...);
/*Class* tmp = reinterpret_cast<Class*>(this);*/
/*DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);*/
/*MSG_DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);*/
/*return tmp->do_compute(t...);*/
}
......@@ -263,9 +283,9 @@ private:
{
return Class::do_compute(std::get<Indices>(t)...);
/*Class* tmp = reinterpret_cast<Class*>(this);*/
/*DEBUG("type of *this = " << typeid(*this).name());*/
/*DEBUG("type of Class = " << typeid(Class).name());*/
/*DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);*/
/*MSG_DEBUG("type of *this = " << typeid(*this).name());*/
/*MSG_DEBUG("type of Class = " << typeid(Class).name());*/
/*MSG_DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);*/
/*return tmp->do_compute(std::get<Indices>(t)...);*/
}
......@@ -313,21 +333,26 @@ private:
tuple_digest_<0, sizeof...(Dependencies)>::append(s, dependencies);
}
typedef std::unordered_map<std::tuple<Dependencies...>, std::shared_ptr<Class>> registry_t;
typedef std::unordered_map<std::tuple<Dependencies...>, task_type*> registry_t;
public:
#if 0
#if 1
static registry_t& registry() { static registry_t _; return _; }
static std::shared_ptr<Class> get(const std::tuple<Dependencies...>& t)
static task_type* get(const std::tuple<Dependencies...>& t)
{
std::shared_ptr<Class>& ret = registry()[t];
task_type*& ret = registry()[t];
if (!ret) {
ret = new Class(t);
ret = new task_type(t);
}
return ret;
}
static task_type* get(const Dependencies&... t)
{
return get(std::make_tuple(t...));
}
static void clear_registry() { registry().clear(); }
#else
static Class* get(std::tuple<Dependencies...>&& t)
......@@ -363,19 +388,18 @@ struct computed_value : value<Type> {
typedef async_computed_value<Class, Type, Dependencies...> task_type;
using value<Type>::output;
using value<Type>::val;
std::shared_ptr<task_type> task;
bool fetched;
task_type* task;
computed_value(Dependencies&&... d)
: value<Type>(), task(new task_type(d...))
: value<Type>(), task(task_type::get(d...))
{}
computed_value(const Dependencies&... d)
: value<Type>(), task(new task_type(d...))
: value<Type>(), task(task_type::get(d...))
{}
computed_value(std::tuple<Dependencies...>&& t)
: value<Type>(), task(new task_type(t))
: value<Type>(), task(task_type::get(t))
{}
computed_value(const std::tuple<Dependencies...>& t)
: value<Type>(), task(new task_type(t))
: value<Type>(), task(task_type::get(t))
{}
computed_value(const computed_value<Class, Type, Dependencies...>& cv)
: value<Type>(cv.val), task(cv.task)
......@@ -384,40 +408,48 @@ struct computed_value : value<Type> {
: value<Type>(cv.val), task(cv.task)
{}
template <typename... DerDep>
computed_value(const std::tuple<DerDep...>& ddt)
: value<Type>(), task(task_type::get(std::tuple<Dependencies...>(ddt)))
{}
template <typename... DerDep>
computed_value(const DerDep&... dd)
: value<Type>(), task(task_type::get(((const Dependencies&)dd)...))
{}
computed_value() : value<Type>(), task() {}
void __init(const std::tuple<Dependencies...>& d)
{
task = new task_type(d);
task = task_type::get(d);
}
Class& operator = (const Class& c)
Class& operator = (const computed_value<Class, Type, Dependencies...>& c)
{
if (task) {
delete task;
}
/*if (task) {*/
/*delete task;*/
/*}*/
task = c.task;
return *static_cast<Class*>(this);
}
Class& operator = (Class&& c)
Class& operator = (computed_value<Class, Type, Dependencies...>&& c)
{
if (task) {
delete task;
}
/*if (task) {*/
/*delete task;*/
/*}*/
task = std::move(c.task);
return *static_cast<Class*>(this);
}
operator Type () const
operator const Type& () const
{
return *task;
}
Type v() const
{
return *task;
}
/*Type& v() const { return *task; }*/
const Type& v() const { return *task; }
static const bool composite = false;
......@@ -434,6 +466,38 @@ struct computed_value : value<Type> {
{
return task->to_md5(md5);
}
virtual
size_t hash() const
{
std::hash<dependencies_type> h;
return h(task->dependencies);
}
bool operator == (const Class& v) const
{
return task == v.task;
}
struct iterator {
/*typedef computed_value<Class, Type, Dependencies...> value_type;*/
typedef const Class value_type;
/*computed_value<Class, Type, Dependencies...> val;*/
const Class* val;
bool end;
iterator(const value_type& v) : val(&v) {}
iterator() : val(), end(true) {}
iterator(const iterator& i) : val(i.val) {}
const value_type& operator * () const { return *val; }
iterator& operator ++ () { val = NULL; return *this; }
iterator& operator ++ (int) { val = NULL; return *this; }
bool operator != (const iterator& i) const { return val != i.val; }
bool operator == (const iterator& i) const { return val == i.val; }
iterator& operator = (const iterator& i) { val = i.val; return *this; }
};
iterator begin() const { return {*this}; }
iterator end() const { return {}; }
typedef iterator const_iterator;
};
......@@ -479,8 +543,8 @@ struct make_task_helper<true, TASK_CLASS, Elems...> {
cartesian_product<Elems...> cp(t);
do {
/*ret.emplace_back(TASK_CLASS::get(*cp));*/
/*DEBUG("make_task " << (*cp));*/
ret.emplace_back(TASK_CLASS(*cp));
/*MSG_DEBUG("make_task " << (*cp));*/
ret.emplace_back(*cp);
} while (cp.next());
return ret;
}
......@@ -498,7 +562,7 @@ template <typename TASK_CLASS, typename... Elems>
auto make_task(const std::tuple<Elems...>& t)
-> typename detect_composite<TASK_CLASS, Elems...>::type
{
/*DEBUG("make_task with " << t);*/
/*MSG_DEBUG("make_task with " << t);*/
return make_task_helper<detect_composite<TASK_CLASS, Elems...>::composite, TASK_CLASS, Elems...>::make(t);
}
......@@ -506,10 +570,22 @@ template <typename TASK_CLASS, typename... Elems>
auto make_task(std::tuple<Elems...>&& t)
-> typename detect_composite<TASK_CLASS, Elems...>::type
{
/*DEBUG("make_task with " << t);*/
/*MSG_DEBUG("make_task with " << t);*/
return make_task_helper<detect_composite<TASK_CLASS, Elems...>::composite, TASK_CLASS, Elems...>::make(std::move(t));
}
template <typename TASK_CLASS, typename... Elems>
auto make_task_composite(const std::tuple<Elems...>& t)
-> decltype(make_task_helper<true, TASK_CLASS, Elems...>::make)
{
return make_task_helper<true, TASK_CLASS, Elems...>::make(t);
}
template <typename TASK_CLASS, typename... Elems>
std::vector<TASK_CLASS> make_task_composite(std::tuple<Elems...>&& t)
{
return make_task_helper<true, TASK_CLASS, Elems...>::make(std::forward<std::tuple<Elems...>>(t));
}
template <typename Class>
struct computed_collection : collection<std::vector<Class>> {
......@@ -522,6 +598,7 @@ struct computed_collection : collection<std::vector<Class>> {
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: collection<std::vector<Class>>{value_cache}
{
/*value_cache = make_task_composite<Class>(t);*/
value_cache = make_task<Class>(t);
}
......@@ -530,6 +607,7 @@ struct computed_collection : collection<std::vector<Class>> {
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: collection<std::vector<Class>>{value_cache}
{
/*value_cache = make_task_composite<Class>(std::make_tuple(deps...));*/
value_cache = make_task<Class>(std::make_tuple(deps...));
}
......@@ -538,105 +616,42 @@ struct computed_collection : collection<std::vector<Class>> {
return value_cache;
}
size_t size() { return value_cache.size(); }
size_t size() const { return value_cache.size(); }
Class& operator [] (size_t i) { return value_cache[i]; }
const Class& operator [] (size_t i) const { return value_cache[i]; }
static const bool composite = true;
};
#if 0
template <typename Class>
struct computed_collection : collection<std::vector<Class>> {
/*template <typename DepTuple> struct expand_tuple;*/
/*template <typename... Dependencies>*/
/*struct expand_tuple<std::tuple<Dependencies...>> {*/
/*typedef async_computed_value<computed_collection<Class>, std::vector<Class>, Dependencies...>*/
/*};*/
/*using value<std::vector<Class>>::val;*/
typedef std::vector<Class> value_type;