// This file is part of QuadProg++: a C++ library implementing
// the algorithm of Goldfarb and Idnani for the solution of a (convex)
// Quadratic Programming problem by means of an active-set dual method.
// Copyright (C) 2007-2009 Luca Di Gaspero.
// Copyright (C) 2009 Eric Moyer.
//
// QuadProg++ is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// QuadProg++ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with QuadProg++. If not, see .
#ifndef _ARRAY_HH
#define _ARRAY_HH
#include
#include
#include
#include
#include
#include
namespace QuadProgPP{
enum MType { DIAG };
template
class Vector
{
public:
Vector();
Vector(const unsigned int n);
Vector(const T& a, const unsigned int n); //initialize to constant value
Vector(const T* a, const unsigned int n); // Initialize to array
Vector(const Vector &rhs); // copy constructor
~Vector(); // destructor
inline void set(const T* a, const unsigned int n);
Vector extract(const std::set& indexes) const;
inline T& operator[](const unsigned int& i); //i-th element
inline const T& operator[](const unsigned int& i) const;
inline unsigned int size() const;
inline void resize(const unsigned int n);
inline void resize(const T& a, const unsigned int n);
Vector& operator=(const Vector& rhs); //assignment
Vector& operator=(const T& a); //assign a to every element
inline Vector& operator+=(const Vector& rhs);
inline Vector& operator-=(const Vector& rhs);
inline Vector& operator*=(const Vector& rhs);
inline Vector& operator/=(const Vector& rhs);
inline Vector& operator^=(const Vector& rhs);
inline Vector& operator+=(const T& a);
inline Vector& operator-=(const T& a);
inline Vector& operator*=(const T& a);
inline Vector& operator/=(const T& a);
inline Vector& operator^=(const T& a);
private:
unsigned int n; // size of array. upper index is n-1
T* v; // storage for data
};
template
Vector::Vector()
: n(0), v(0)
{}
template
Vector::Vector(const unsigned int n)
: v(new T[n])
{
this->n = n;
}
template
Vector::Vector(const T& a, const unsigned int n)
: v(new T[n])
{
this->n = n;
for (unsigned int i = 0; i < n; i++)
v[i] = a;
}
template
Vector::Vector(const T* a, const unsigned int n)
: v(new T[n])
{
this->n = n;
for (unsigned int i = 0; i < n; i++)
v[i] = *a++;
}
template
Vector::Vector(const Vector& rhs)
: v(new T[rhs.n])
{
this->n = rhs.n;
for (unsigned int i = 0; i < n; i++)
v[i] = rhs[i];
}
template
Vector::~Vector()
{
if (v != 0)
delete[] (v);
}
template
void Vector::resize(const unsigned int n)
{
if (n == this->n)
return;
if (v != 0)
delete[] (v);
v = new T[n];
this->n = n;
}
template
void Vector::resize(const T& a, const unsigned int n)
{
resize(n);
for (unsigned int i = 0; i < n; i++)
v[i] = a;
}
template
inline Vector& Vector::operator=(const Vector& rhs)
// postcondition: normal assignment via copying has been performed;
// if vector and rhs were different sizes, vector
// has been resized to match the size of rhs
{
if (this != &rhs)
{
resize(rhs.n);
for (unsigned int i = 0; i < n; i++)
v[i] = rhs[i];
}
return *this;
}
template
inline Vector & Vector::operator=(const T& a) //assign a to every element
{
for (unsigned int i = 0; i < n; i++)
v[i] = a;
return *this;
}
template
inline T & Vector::operator[](const unsigned int& i) //subscripting
{
return v[i];
}
template
inline const T& Vector::operator[](const unsigned int& i) const //subscripting
{
return v[i];
}
template
inline unsigned int Vector::size() const
{
return n;
}
template
inline void Vector::set(const T* a, unsigned int n)
{
resize(n);
for (unsigned int i = 0; i < n; i++)
v[i] = a[i];
}
template
inline Vector Vector::extract(const std::set& indexes) const
{
Vector tmp(indexes.size());
unsigned int i = 0;
for (std::set::const_iterator el = indexes.begin(); el != indexes.end(); el++)
{
if (*el >= n)
throw std::logic_error("Error extracting subvector: the indexes are out of vector bounds");
tmp[i++] = v[*el];
}
return tmp;
}
template
inline Vector& Vector::operator+=(const Vector& rhs)
{
if (this->size() != rhs.size())
throw std::logic_error("Operator+=: vectors have different sizes");
for (unsigned int i = 0; i < n; i++)
v[i] += rhs[i];
return *this;
}
template
inline Vector& Vector::operator+=(const T& a)
{
for (unsigned int i = 0; i < n; i++)
v[i] += a;
return *this;
}
template
inline Vector operator+(const Vector& rhs)
{
return rhs;
}
template
inline Vector operator+(const Vector& lhs, const Vector& rhs)
{
if (lhs.size() != rhs.size())
throw std::logic_error("Operator+: vectors have different sizes");
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] + rhs[i];
return tmp;
}
template
inline Vector operator+(const Vector& lhs, const T& a)
{
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] + a;
return tmp;
}
template
inline Vector operator+(const T& a, const Vector& rhs)
{
Vector tmp(rhs.size());
for (unsigned int i = 0; i < rhs.size(); i++)
tmp[i] = a + rhs[i];
return tmp;
}
template
inline Vector& Vector::operator-=(const Vector& rhs)
{
if (this->size() != rhs.size())
throw std::logic_error("Operator-=: vectors have different sizes");
for (unsigned int i = 0; i < n; i++)
v[i] -= rhs[i];
return *this;
}
template
inline Vector& Vector::operator-=(const T& a)
{
for (unsigned int i = 0; i < n; i++)
v[i] -= a;
return *this;
}
template
inline Vector operator-(const Vector& rhs)
{
return (T)(-1) * rhs;
}
template
inline Vector operator-(const Vector& lhs, const Vector& rhs)
{
if (lhs.size() != rhs.size())
throw std::logic_error("Operator-: vectors have different sizes");
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] - rhs[i];
return tmp;
}
template
inline Vector operator-(const Vector& lhs, const T& a)
{
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] - a;
return tmp;
}
template
inline Vector operator-(const T& a, const Vector& rhs)
{
Vector tmp(rhs.size());
for (unsigned int i = 0; i < rhs.size(); i++)
tmp[i] = a - rhs[i];
return tmp;
}
template
inline Vector& Vector::operator*=(const Vector& rhs)
{
if (this->size() != rhs.size())
throw std::logic_error("Operator*=: vectors have different sizes");
for (unsigned int i = 0; i < n; i++)
v[i] *= rhs[i];
return *this;
}
template
inline Vector& Vector::operator*=(const T& a)
{
for (unsigned int i = 0; i < n; i++)
v[i] *= a;
return *this;
}
template
inline Vector operator*(const Vector& lhs, const Vector& rhs)
{
if (lhs.size() != rhs.size())
throw std::logic_error("Operator*: vectors have different sizes");
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] * rhs[i];
return tmp;
}
template
inline Vector operator*(const Vector& lhs, const T& a)
{
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] * a;
return tmp;
}
template
inline Vector operator*(const T& a, const Vector& rhs)
{
Vector tmp(rhs.size());
for (unsigned int i = 0; i < rhs.size(); i++)
tmp[i] = a * rhs[i];
return tmp;
}
template
inline Vector& Vector::operator/=(const Vector& rhs)
{
if (this->size() != rhs.size())
throw std::logic_error("Operator/=: vectors have different sizes");
for (unsigned int i = 0; i < n; i++)
v[i] /= rhs[i];
return *this;
}
template
inline Vector& Vector::operator/=(const T& a)
{
for (unsigned int i = 0; i < n; i++)
v[i] /= a;
return *this;
}
template
inline Vector operator/(const Vector& lhs, const Vector& rhs)
{
if (lhs.size() != rhs.size())
throw std::logic_error("Operator/: vectors have different sizes");
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] / rhs[i];
return tmp;
}
template
inline Vector operator/(const Vector& lhs, const T& a)
{
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = lhs[i] / a;
return tmp;
}
template
inline Vector operator/(const T& a, const Vector& rhs)
{
Vector tmp(rhs.size());
for (unsigned int i = 0; i < rhs.size(); i++)
tmp[i] = a / rhs[i];
return tmp;
}
template
inline Vector operator^(const Vector& lhs, const Vector& rhs)
{
if (lhs.size() != rhs.size())
throw std::logic_error("Operator^: vectors have different sizes");
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = pow(lhs[i], rhs[i]);
return tmp;
}
template
inline Vector operator^(const Vector& lhs, const T& a)
{
Vector tmp(lhs.size());
for (unsigned int i = 0; i < lhs.size(); i++)
tmp[i] = pow(lhs[i], a);
return tmp;
}
template
inline Vector operator^(const T& a, const Vector& rhs)
{
Vector tmp(rhs.size());
for (unsigned int i = 0; i < rhs.size(); i++)
tmp[i] = pow(a, rhs[i]);
return tmp;
}
template
inline Vector& Vector::operator^=(const Vector& rhs)
{
if (this->size() != rhs.size())
throw std::logic_error("Operator^=: vectors have different sizes");
for (unsigned int i = 0; i < n; i++)
v[i] = pow(v[i], rhs[i]);
return *this;
}
template
inline Vector& Vector::operator^=(const T& a)
{
for (unsigned int i = 0; i < n; i++)
v[i] = pow(v[i], a);
return *this;
}
template
inline bool operator==(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] != w[i])
return false;
return true;
}
template
inline bool operator!=(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] != w[i])
return true;
return false;
}
template
inline bool operator<(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] >= w[i])
return false;
return true;
}
template
inline bool operator<=(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] > w[i])
return false;
return true;
}
template
inline bool operator>(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] <= w[i])
return false;
return true;
}
template
inline bool operator>=(const Vector& v, const Vector& w)
{
if (v.size() != w.size())
throw std::logic_error("Vectors of different size are not confrontable");
for (unsigned i = 0; i < v.size(); i++)
if (v[i] < w[i])
return false;
return true;
}
/**
Input/Output
*/
template
inline std::ostream& operator<<(std::ostream& os, const Vector& v)
{
os << std::endl << v.size() << std::endl;
for (unsigned int i = 0; i < v.size() - 1; i++)
os << std::setw(20) << std::setprecision(16) << v[i] << ", ";
os << std::setw(20) << std::setprecision(16) << v[v.size() - 1] << std::endl;
return os;
}
template
std::istream& operator>>(std::istream& is, Vector& v)
{
int elements;
char comma;
is >> elements;
v.resize(elements);
for (unsigned int i = 0; i < elements; i++)
is >> v[i] >> comma;
return is;
}
/**
Index utilities
*/
std::set seq(unsigned int s, unsigned int e);
std::set singleton(unsigned int i);
template
class CanonicalBaseVector : public Vector
{
public:
CanonicalBaseVector(unsigned int i, unsigned int n);
inline void reset(unsigned int i);
private:
unsigned int e;
};
template
CanonicalBaseVector::CanonicalBaseVector(unsigned int i, unsigned int n)
: Vector((T)0, n), e(i)
{ (*this)[e] = (T)1; }
template
inline void CanonicalBaseVector::reset(unsigned int i)
{
(*this)[e] = (T)0;
e = i;
(*this)[e] = (T)1;
}
#include
template
inline T sum(const Vector& v)
{
T tmp = (T)0;
for (unsigned int i = 0; i < v.size(); i++)
tmp += v[i];
return tmp;
}
template
inline T prod(const Vector& v)
{
T tmp = (T)1;
for (unsigned int i = 0; i < v.size(); i++)
tmp *= v[i];
return tmp;
}
template
inline T mean(const Vector& v)
{
T sum = (T)0;
for (unsigned int i = 0; i < v.size(); i++)
sum += v[i];
return sum / v.size();
}
template
inline T median(const Vector& v)
{
Vector tmp = sort(v);
if (v.size() % 2 == 1) // it is an odd-sized vector
return tmp[v.size() / 2];
else
return 0.5 * (tmp[v.size() / 2 - 1] + tmp[v.size() / 2]);
}
template
inline T stdev(const Vector& v, bool sample_correction = false)
{
return sqrt(var(v, sample_correction));
}
template
inline T var(const Vector& v, bool sample_correction = false)
{
T sum = (T)0, ssum = (T)0;
unsigned int n = v.size();
for (unsigned int i = 0; i < n; i++)
{
sum += v[i];
ssum += (v[i] * v[i]);
}
if (!sample_correction)
return (ssum / n) - (sum / n) * (sum / n);
else
return n * ((ssum / n) - (sum / n) * (sum / n)) / (n - 1);
}
template
inline T max(const Vector& v)
{
T value = v[0];
for (unsigned int i = 1; i < v.size(); i++)
value = std::max(v[i], value);
return value;
}
template
inline T min(const Vector& v)
{
T value = v[0];
for (unsigned int i = 1; i < v.size(); i++)
value = std::min(v[i], value);
return value;
}
template
inline unsigned int index_max(const Vector& v)
{
unsigned int max = 0;
for (unsigned int i = 1; i < v.size(); i++)
if (v[i] > v[max])
max = i;
return max;
}
template
inline unsigned int index_min(const Vector& v)
{
unsigned int min = 0;
for (unsigned int i = 1; i < v.size(); i++)
if (v[i] < v[min])
min = i;
return min;
}
template
inline T dot_prod(const Vector& a, const Vector& b)
{
T sum = (T)0;
if (a.size() != b.size())
throw std::logic_error("Dotprod error: the vectors are not the same size");
for (unsigned int i = 0; i < a.size(); i++)
sum += a[i] * b[i];
return sum;
}
/**
Single element mathematical functions
*/
template
inline Vector exp(const Vector& v)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = exp(v[i]);
return tmp;
}
template
inline Vector log(const Vector& v)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = log(v[i]);
return tmp;
}
template
inline Vector sqrt(const Vector& v)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = sqrt(v[i]);
return tmp;
}
template
inline Vector pow(const Vector& v, double a)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = pow(v[i], a);
return tmp;
}
template
inline Vector abs(const Vector& v)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = (T)fabs(v[i]);
return tmp;
}
template
inline Vector sign(const Vector& v)
{
Vector tmp(v.size());
for (unsigned int i = 0; i < v.size(); i++)
tmp[i] = v[i] > 0 ? +1 : v[i] == 0 ? 0 : -1;
return tmp;
}
template
inline unsigned int partition(Vector& v, unsigned int begin, unsigned int end)
{
unsigned int i = begin + 1, j = begin + 1;
T pivot = v[begin];
while (j <= end)
{
if (v[j] < pivot) {
std::swap(v[i], v[j]);
i++;
}
j++;
}
v[begin] = v[i - 1];
v[i - 1] = pivot;
return i - 2;
}
template
inline void quicksort(Vector