2012-05-23 14:56:01 +01:00
|
|
|
#ifndef HORUS_UTIL_H
|
|
|
|
#define HORUS_UTIL_H
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
#include <cassert>
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
|
|
|
#include <set>
|
|
|
|
#include <queue>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include "Horus.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
2012-05-24 16:14:13 +01:00
|
|
|
namespace {
|
|
|
|
const double NEG_INF = -numeric_limits<double>::infinity();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-05-23 14:56:01 +01:00
|
|
|
namespace Util {
|
|
|
|
|
|
|
|
template <typename T> void addToVector (vector<T>&, const vector<T>&);
|
|
|
|
|
|
|
|
template <typename T> void addToSet (set<T>&, const vector<T>&);
|
|
|
|
|
|
|
|
template <typename T> void addToQueue (queue<T>&, const vector<T>&);
|
|
|
|
|
|
|
|
template <typename T> bool contains (const vector<T>&, const T&);
|
|
|
|
|
|
|
|
template <typename T> bool contains (const set<T>&, const T&);
|
|
|
|
|
|
|
|
template <typename K, typename V> bool contains (
|
|
|
|
const unordered_map<K, V>&, const K&);
|
|
|
|
|
2012-05-24 22:55:20 +01:00
|
|
|
template <typename T> size_t indexOf (const vector<T>&, const T&);
|
2012-05-23 14:56:01 +01:00
|
|
|
|
2012-05-28 21:09:56 +01:00
|
|
|
template <class Operation>
|
|
|
|
void apply_n_times (Params& v1, const Params& v2, unsigned repetitions, Operation);
|
|
|
|
|
2012-05-24 16:14:13 +01:00
|
|
|
template <typename T> void log (vector<T>&);
|
|
|
|
|
|
|
|
template <typename T> void exp (vector<T>&);
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
template <typename T> string elementsToString (
|
|
|
|
const vector<T>& v, string sep = " ");
|
|
|
|
|
|
|
|
template <typename T> std::string toString (const T&);
|
|
|
|
|
|
|
|
template <> std::string toString (const bool&);
|
|
|
|
|
2012-05-23 14:56:01 +01:00
|
|
|
double logSum (double, double);
|
|
|
|
|
2012-05-24 14:55:30 +01:00
|
|
|
unsigned maxUnsigned (void);
|
|
|
|
|
|
|
|
unsigned stringToUnsigned (string);
|
2012-05-23 14:56:01 +01:00
|
|
|
|
2012-05-24 14:55:30 +01:00
|
|
|
double stringToDouble (string);
|
2012-05-23 14:56:01 +01:00
|
|
|
|
|
|
|
double factorial (unsigned);
|
|
|
|
|
|
|
|
double logFactorial (unsigned);
|
|
|
|
|
|
|
|
unsigned nrCombinations (unsigned, unsigned);
|
|
|
|
|
2012-05-24 22:55:20 +01:00
|
|
|
size_t sizeExpected (const Ranges&);
|
2012-05-23 14:56:01 +01:00
|
|
|
|
2012-05-24 16:14:13 +01:00
|
|
|
unsigned nrDigits (int);
|
2012-05-23 14:56:01 +01:00
|
|
|
|
|
|
|
bool isInteger (const string&);
|
|
|
|
|
|
|
|
string parametersToString (const Params&, unsigned = Constants::PRECISION);
|
|
|
|
|
|
|
|
vector<string> getStateLines (const Vars&);
|
|
|
|
|
|
|
|
bool setHorusFlag (string key, string value);
|
|
|
|
|
|
|
|
void printHeader (string, std::ostream& os = std::cout);
|
|
|
|
|
|
|
|
void printSubHeader (string, std::ostream& os = std::cout);
|
|
|
|
|
|
|
|
void printAsteriskLine (std::ostream& os = std::cout);
|
|
|
|
|
|
|
|
void printDashedLine (std::ostream& os = std::cout);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> void
|
|
|
|
Util::addToVector (vector<T>& v, const vector<T>& elements)
|
|
|
|
{
|
|
|
|
v.insert (v.end(), elements.begin(), elements.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> void
|
|
|
|
Util::addToSet (set<T>& s, const vector<T>& elements)
|
|
|
|
{
|
|
|
|
s.insert (elements.begin(), elements.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> void
|
|
|
|
Util::addToQueue (queue<T>& q, const vector<T>& elements)
|
|
|
|
{
|
2012-05-24 22:55:20 +01:00
|
|
|
for (size_t i = 0; i < elements.size(); i++) {
|
2012-05-23 14:56:01 +01:00
|
|
|
q.push (elements[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> bool
|
|
|
|
Util::contains (const vector<T>& v, const T& e)
|
|
|
|
{
|
|
|
|
return std::find (v.begin(), v.end(), e) != v.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> bool
|
|
|
|
Util::contains (const set<T>& s, const T& e)
|
|
|
|
{
|
|
|
|
return s.find (e) != s.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename K, typename V> bool
|
|
|
|
Util::contains (const unordered_map<K, V>& m, const K& k)
|
|
|
|
{
|
|
|
|
return m.find (k) != m.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-24 22:55:20 +01:00
|
|
|
template <typename T> size_t
|
2012-05-23 14:56:01 +01:00
|
|
|
Util::indexOf (const vector<T>& v, const T& e)
|
|
|
|
{
|
2012-05-24 22:55:20 +01:00
|
|
|
return std::distance (v.begin(),
|
|
|
|
std::find (v.begin(), v.end(), e));
|
2012-05-23 14:56:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-28 21:09:56 +01:00
|
|
|
template <class Operation> void
|
|
|
|
Util::apply_n_times (Params& v1, const Params& v2, unsigned repetitions,
|
|
|
|
Operation unary_op)
|
|
|
|
{
|
|
|
|
Params::iterator first = v1.begin();
|
|
|
|
Params::const_iterator last = v1.end();
|
|
|
|
Params::const_iterator first2 = v2.begin();
|
|
|
|
Params::const_iterator last2 = v2.end();
|
|
|
|
while (first != last) {
|
|
|
|
for (first2 = v2.begin(); first2 != last2; ++first2) {
|
|
|
|
std::transform (first, first + repetitions, first,
|
|
|
|
std::bind1st (unary_op, *first2));
|
|
|
|
first += repetitions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
template <typename T> void
|
|
|
|
Util::log (vector<T>& v)
|
2012-05-23 14:56:01 +01:00
|
|
|
{
|
2012-05-28 21:09:56 +01:00
|
|
|
std::transform (v.begin(), v.end(), v.begin(), ::log);
|
2012-05-23 14:56:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
template <typename T> void
|
|
|
|
Util::exp (vector<T>& v)
|
2012-05-23 14:56:01 +01:00
|
|
|
{
|
2012-05-28 21:09:56 +01:00
|
|
|
std::transform (v.begin(), v.end(), v.begin(), ::exp);
|
2012-05-23 14:56:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
|
|
|
|
template <typename T> string
|
|
|
|
Util::elementsToString (const vector<T>& v, string sep)
|
2012-05-24 16:14:13 +01:00
|
|
|
{
|
2012-05-28 16:57:45 +01:00
|
|
|
stringstream ss;
|
|
|
|
for (size_t i = 0; i < v.size(); i++) {
|
|
|
|
ss << ((i != 0) ? sep : "") << v[i];
|
|
|
|
}
|
|
|
|
return ss.str();
|
2012-05-24 16:14:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
template <typename T> std::string
|
|
|
|
Util::toString (const T& t)
|
2012-05-24 16:14:13 +01:00
|
|
|
{
|
2012-05-28 16:57:45 +01:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << t;
|
|
|
|
return ss.str();
|
2012-05-24 16:14:13 +01:00
|
|
|
}
|
|
|
|
|
2012-05-23 14:56:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
inline double
|
|
|
|
Util::logSum (double x, double y)
|
|
|
|
{
|
|
|
|
// std::log (std::exp (x) + std::exp (y)) can overflow!
|
|
|
|
assert (std::isnan (x) == false);
|
|
|
|
assert (std::isnan (y) == false);
|
|
|
|
if (x == NEG_INF) {
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
if (y == NEG_INF) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
// if one value is much smaller than the other,
|
|
|
|
// keep the larger value
|
|
|
|
const double tol = 460.517; // log (1e200)
|
|
|
|
if (x < y - tol) {
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
if (y < x - tol) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
assert (std::isnan (x - y) == false);
|
|
|
|
const double exp_diff = std::exp (x - y);
|
|
|
|
if (std::isfinite (exp_diff) == false) {
|
|
|
|
// difference is too large
|
|
|
|
return x > y ? x : y;
|
|
|
|
}
|
|
|
|
// otherwise return the sum
|
|
|
|
return y + std::log (static_cast<double>(1.0) + exp_diff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-24 14:55:30 +01:00
|
|
|
inline unsigned
|
|
|
|
Util::maxUnsigned (void)
|
2012-05-23 14:56:01 +01:00
|
|
|
{
|
2012-05-24 14:55:30 +01:00
|
|
|
return numeric_limits<unsigned>::max();
|
2012-05-23 14:56:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace LogAware {
|
|
|
|
|
2012-05-24 16:14:13 +01:00
|
|
|
inline double one() { return Globals::logDomain ? 0.0 : 1.0; }
|
|
|
|
inline double zero() { return Globals::logDomain ? NEG_INF : 0.0; }
|
|
|
|
inline double addIdenty() { return Globals::logDomain ? NEG_INF : 0.0; }
|
|
|
|
inline double multIdenty() { return Globals::logDomain ? 0.0 : 1.0; }
|
|
|
|
inline double withEvidence() { return Globals::logDomain ? 0.0 : 1.0; }
|
|
|
|
inline double noEvidence() { return Globals::logDomain ? NEG_INF : 0.0; }
|
|
|
|
inline double log (double v) { return Globals::logDomain ? ::log (v) : v; }
|
|
|
|
inline double exp (double v) { return Globals::logDomain ? ::exp (v) : v; }
|
2012-05-23 14:56:01 +01:00
|
|
|
|
|
|
|
void normalize (Params&);
|
|
|
|
|
|
|
|
double getL1Distance (const Params&, const Params&);
|
|
|
|
|
|
|
|
double getMaxNorm (const Params&, const Params&);
|
|
|
|
|
|
|
|
double pow (double, unsigned);
|
|
|
|
|
|
|
|
double pow (double, double);
|
|
|
|
|
|
|
|
void pow (Params&, unsigned);
|
|
|
|
|
|
|
|
void pow (Params&, double);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2012-05-28 16:57:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator+=(std::vector<T>& v, double val)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind1st (plus<double>(), val));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator-=(std::vector<T>& v, double val)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind1st (minus<double>(), val));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator*=(std::vector<T>& v, double val)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind1st (multiplies<double>(), val));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator/=(std::vector<T>& v, double val)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind1st (divides<double>(), val));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator+=(std::vector<T>& a, const std::vector<T>& b)
|
|
|
|
{
|
|
|
|
assert (a.size() == b.size());
|
|
|
|
std::transform (a.begin(), a.end(), b.begin(), a.begin(),
|
|
|
|
plus<double>());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator-=(std::vector<T>& a, const std::vector<T>& b)
|
|
|
|
{
|
|
|
|
assert (a.size() == b.size());
|
|
|
|
std::transform (a.begin(), a.end(), b.begin(), a.begin(),
|
|
|
|
minus<double>());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator*=(std::vector<T>& a, const std::vector<T>& b)
|
|
|
|
{
|
|
|
|
assert (a.size() == b.size());
|
|
|
|
std::transform (a.begin(), a.end(), b.begin(), a.begin(),
|
|
|
|
multiplies<double>());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator/=(std::vector<T>& a, const std::vector<T>& b)
|
|
|
|
{
|
|
|
|
assert (a.size() == b.size());
|
|
|
|
std::transform (a.begin(), a.end(), b.begin(), a.begin(),
|
|
|
|
divides<double>());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator^=(std::vector<T>& v, double exp)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind2nd (ptr_fun<double, double, double> (std::pow), exp));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void operator^=(std::vector<T>& v, int iexp)
|
|
|
|
{
|
|
|
|
std::transform (v.begin(), v.end(), v.begin(),
|
|
|
|
std::bind2nd (ptr_fun<double, int, double> (std::pow), iexp));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
std::ostream& operator << (std::ostream& os, const vector<T>& v)
|
|
|
|
{
|
|
|
|
os << "[" ;
|
|
|
|
os << Util::elementsToString (v, ", ");
|
|
|
|
os << "]" ;
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2012-05-23 14:56:01 +01:00
|
|
|
#endif // HORUS_UTIL_H
|
|
|
|
|