SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ublas.hpp
Go to the documentation of this file.
1 /*
2 Copyright© 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef SIG_UTIL_BLAS_HPP
9 #define SIG_UTIL_BLAS_HPP
10 
11 #include "../helper/maybe.hpp"
12 #include "../helper/container_helper.hpp"
13 #include "../helper/helper_modules.hpp"
14 
15 #ifdef SIG_ENABLE_BOOST
16 
17 #include <boost/numeric/ublas/vector.hpp>
18 #include <boost/numeric/ublas/matrix.hpp>
19 #include <boost/numeric/ublas/lu.hpp>
20 #include <boost/numeric/ublas/triangular.hpp>
21 
23 
24 namespace sig
25 {
26 
27 template <class T>
28 using matrix_u = boost::numeric::ublas::matrix<T>;
29 /*
30 template <class T, class F = boost::numeric::ublas::row_major, class AR = boost::numeric::ublas::unbounded_array<T>>
31 class matrix_u : public boost::numeric::ublas::matrix<T, F, AR>
32 {
33  using Base = boost::numeric::ublas::matrix<T, F, AR>;
34 
35 public:
36  matrix_u(uint row, uint col, T const& val) : Base(row, col, val){}
37  matrix_u(uint row, uint col) : matrix_u(row, col, 0){}
38  matrix_u(uint row) : Base(row, 0){}
39  matrix_u() : Base(0){}
40 
41  template<class AE>
42  matrix_u(matrix_expression<AE> const& src) : boost::numeric::ublas::matrix<AE, F, AR<>>(src){}
43  template<class AE>
44  matrix_u(matrix_expression<AE>&& src) : boost::numeric::ublas::matrix<AE, F, AR>(std::move(src)){}
45 };
46 */
47 
48 template <class T>
49 using vector_u = boost::numeric::ublas::vector<T>;
50 /*
51 template <class T, class AR = boost::numeric::ublas::unbounded_array<T>>
52 class vector_u : public boost::numeric::ublas::vector<T, AR>
53 {
54  using Base = boost::numeric::ublas::vector<T, AR>;
55 
56  uint tail_;
57 public:
58  vector_u() : Base(), tail_(0){}
59  vector_u(uint size) : Base(size), tail_(0){}
60  vector_u(uint size, array_type const& data) : Base(size, data), tail_(data.size()){}
61  vector_u(array_type const& data) : Base(data), tail_(data.size()){}
62  vector_u(uint size, value_type const& init) : Base(size, init), tail_(size){}
63  template <class AE>
64  vector_u(vector_expression<AE> const& ae) : Base(ae), tail_(ae.size()){}
65 
66  vector_u(vector_u const& v) : Base(v), tail_(v.size()){}
67  vector_u(vector_u&& v) : Base(std::move(v)), tail_(v.size()){}
68 
69  vector_u& operator=(vector_u const& v){ return Base::operator=(v); }
70  template<class C>
71  vector_u& operator=(vector_container<C> const& v){ return Base::operator=(v); }
72  template<class AE>
73  vector_u& operator=(vector_expression<AE> const& ae){ return Base::operator=(ae); }
74 
75  void push_back(ParamType<T> v){
76  assert(tail_ < Base::size());
77 
78  Base::insert_element(tail_, v);
79  ++tail_;
80  }
81 };
82 
84 template<template<class, class> class C, class T, template<class, class> class AR, class A>
85 struct impl::sequence_container_traits<C<T, AR<T, A>>>
86 {
87  static const bool exist = true;
88 
89  using value_type = T;
90 
91  template<class U>
92  using rebind = vector_u<U, AR<U, typename A::template rebind<U>::other>>;
93 
94 
95  static vector_u<T, AR<T,A>> make(size_t n){ return vector_u<T, AR<T,A>>(n); } // default implementation
96 
97  static void add_element(vector_u<T, AR<T,A>>& c, T const& t)
98  {
99  c.push_back(t);
100  }
101 };
102 
103 template<class... Args>
104 struct impl::container_traits<boost::numeric::ublas::vector<Args...>> : public sequence_container_traits<boost::numeric::ublas::vector<Args...>>
105 {};
106 
107 template<class... Args>
108 struct impl::container_traits<vector_u<Args...>> : public sequence_container_traits<vector_u<Args...>>
109 {};
110 */
111 
112 
114 template <class V, class R = std::vector<typename V::value_type>>
115 auto from_vector_ublas(V const& vec) ->R
116 {
117  R dest = impl::container_traits<R>::make(vec.size());
118 
119  for (uint i = 0; i < vec.size(); ++i){
121  }
122 
123  return dest;
124 }
125 
127 template <class M, class R = std::vector<typename M::value_type>>
128 auto from_matrix_ublas(M const& mat, uint row) ->R
129 {
130  R dest = impl::container_traits<R>::make(mat.size2());
131 
132  for (uint i = 0; i < mat.size2(); ++i){
133  impl::container_traits<R>::add_element(dest, mat(row, i));
134  }
135 
136  return dest;
137 }
138 
140 template <class M, class R = std::vector<std::vector<typename M::value_type>>>
141 auto from_matrix_ublas(M const& mat) ->R
142 {
143  using C = typename impl::container_traits<R>::value_type;
144 
145  R dest = impl::container_traits<R>::make(mat.size1());
146 
147  for (uint i=0; i < mat.size1(); ++i){
148  C row = impl::container_traits<C>::make(mat.size2());
149 
150  for (uint j = 0; j < mat.size2(); ++j){
152  }
153  impl::container_traits<R>::add_element(dest, std::move(row));
154  }
155 
156  return dest;
157 }
158 
160 template <class C, class T = typename impl::container_traits<C>::value_type>
161 auto to_vector_ublas(C const& vec) ->vector_u<T>
162 {
163  vector_u<T> dest(vec.size());
164 
165  for (uint i=0; i<vec.size(); ++i){
166  dest(i) = vec[i];
167  }
168 
169  return dest;
170 }
171 
173 template <class CC, class T = typename impl::container_traits<typename impl::container_traits<CC>::value_type>::value_type>
174 auto to_matrix_ublas(CC const& mat) ->matrix_u<T>
175 {
176  using C = typename impl::container_traits<CC>::value_type;
177 
178  const uint size1 = mat.size();
179  const uint size2 = mat.begin()->size();
180  matrix_u<T> dest(size1, size2);
181 
182  for (uint i = 0; i < size1; ++i){
183  for (uint j = 0; j < size2; ++j){
184  dest(i, j) = mat[i][j];
185  }
186  }
187 
188  return dest;
189 }
190 
191 
193 
201 template <class T,
202  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
203 >
205  ->Maybe<matrix_u<RT>>
206 {
207  using namespace boost::numeric::ublas;
208 
209  permutation_matrix<> pm(mat.size1());
210 
211  if (lu_factorize(mat, pm) != 0) return Nothing(matrix_u<RT>());
212 
213  matrix<RT> result = identity_matrix<RT>(mat.size1());
214 
215  lu_substitute(mat, pm, result);
216 
217  return Just<matrix_u<RT>>(std::move(result));
218 }
219 
220 template <class T,
221  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
222 >
223 auto invert_matrix(matrix_u<T> const& mat)
224  ->Maybe<matrix_u<RT>>
225 {
226  matrix_u<RT> tmp(mat);
227 
228  return invert_matrix(std::move(tmp));
229 }
230 
231 
233 template <class T,
234  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
235 >
237  ->Maybe<vector_u<RT>>
238 {
239  using namespace boost::numeric::ublas;
240 
241  permutation_matrix<> pm(mat.size1());
242 
243  if (lu_factorize(mat, pm) != 0) return Nothing(vector_u<RT>());
244 
245  lu_substitute(mat, pm, vec);
246 
247  return Just<vector_u<RT>>(std::move(vec));
248 }
249 
250 template <class T,
251  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
252 >
253 auto matrix_vector_solve(matrix_u<T> const& mat, vector_u<T> const& vec)
254  ->Maybe<vector_u<RT>>
255 {
256  matrix_u<RT> tmp_m(mat);
257  vector_u<RT> tmp_v(vec);
258 
259  return matrix_vector_solve(std::move(tmp_m), std::move(tmp_v));
260 }
261 
262 template <class T,
263  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
264 >
266  ->Maybe<vector_u<RT>>
267 {
268  matrix_u<RT> tmp_m(mat);
269 
270  return matrix_vector_solve(std::move(tmp_m), std::move(vec));
271 }
272 
273 template <class T,
274  class RT = typename std::conditional<std::is_integral<T>::value, double, T>::type
275 >
277 ->Maybe<vector_u<RT>>
278 {
279  vector_u<RT> tmp_v(vec);
280 
281  return matrix_vector_solve(std::move(mat), std::move(tmp_v));
282 }
283 
284 
286 template <class F, class V>
287 auto map_v(F&& func, V&& vec)
288 {
289  using namespace boost::numeric::ublas;
290  using RT = decltype(impl::eval(std::forward<F>(func), std::forward<V>(vec)(0)));
291 
292  vector_u<RT> result(vec.size());
293 
294  for (uint i = 0, size = vec.size(); i < size; ++i){
295  result(i) = std::forward<F>(func)(std::forward<V>(vec)(i));
296  }
297 
298  return result;
299 }
300 
301 template <class F, class M>
302 auto map_m(F&& func, M&& mat)
303 {
304  using namespace boost::numeric::ublas;
305  using RT = decltype(impl::eval(std::forward<F>(func), std::forward<M>(mat)(0,0)));
306 
307  const uint size1 = mat.size1();
308  const uint size2 = mat.size2();
309 
310  matrix_u<RT> result(size1, size2);
311 
312  for (uint i = 0; i < size1; ++i){
313  for (uint j = 0; j < size2; ++j){
314  result(i, j) = std::forward<F>(func)(std::forward<M>(mat)(i, j));
315  }
316  }
317 
318  return result;
319 }
320 
322 template <class F, class V, class... Vs>
323 void for_each_v(F&& func, V& vec, Vs&&... vecs)
324 {
325  const uint length = sig::min(vec.size(), vecs.size()...);
326  iterative_assign(length, std::forward<F>(func), impl::begin(vec), impl::begin(std::forward<Vs>(vecs))...);
327 }
328 
330 template <class F, class M>
331 void for_each_m(F&& func, M& mat)
332 {
333  const uint size1 = mat.size1();
334  const uint size2 = mat.size2();
335 
336  for (uint i = 0; i < size1; ++i){
337  for (uint j = 0; j < size2; ++j){
338  std::forward<F>(func)(mat(i, j));
339  }
340  }
341 }
342 
344 template <class F, class M>
345 void for_diagonal(F&& func, M& mat)
346 {
347  using namespace boost::numeric::ublas;
348 
349  const uint size = min(mat.size1(), mat.size2());
350  matrix_vector_range<M> r(mat, range(0, size), range(0, size));
351 
352  for (auto it = r.begin(), end = r.end(); it != end; ++it){
353  std::forward<F>(func)(*it);
354  }
355 }
356 
357 template <class V,
358  typename std::enable_if<std::is_floating_point<typename V::value_type>::value>::type*& = enabler
359 >
360 bool normalize_dist_v(V& data)
361 {
362  double sum = std::accumulate(impl::begin(data), impl::end(data), 0.0);
363  for (auto& e : data) e /= sum;
364 
365  return true;
366 }
367 
368 template <class V>
369 auto normalize_dist_v(V const& data, int dummy = 0)
370 {
371  auto result = data;
372  normalize_dist_v(result);
373 
374  return result;
375 }
376 
377 }
378 #endif
379 
380 #endif
auto to_matrix_ublas(CC const &mat) -> matrix_u< T >
STLのvectorの2次元配列 から ublas::matrix へ変換
Definition: ublas.hpp:174
auto end(C &&c) -> std::move_iterator< typename RC::iterator >
void for_diagonal(F &&func, M &mat)
行列の対角要素の対して、代入演算を行う関数を適用する
Definition: ublas.hpp:345
void * enabler
auto Nothing() -> typename impl::SameIf< T, void, typename boost::none_t, Maybe< T >>::type
値コンストラクタ
Definition: maybe.hpp:67
auto matrix_vector_solve(matrix_u< T > &&mat, vector_u< T > &&vec) -> Maybe< vector_u< RT >>
連立方程式を解く
Definition: ublas.hpp:236
auto map_v(F &&func, V &&vec)
ベクトルの全要素に対して、値を返す関数を適用し、その結果のベクトルを返す
Definition: ublas.hpp:287
bool normalize_dist_v(V &data)
Definition: ublas.hpp:360
boost::numeric::ublas::matrix< T > matrix_u
Definition: ublas.hpp:28
void iterative_assign(uint loop, F &&func, Its...iterators)
auto from_matrix_ublas(M const &mat, uint row) -> R
ublas::matrix の指定行を STLのvectorへ変換
Definition: ublas.hpp:128
auto min(T v) -> T
auto map_m(F &&func, M &&mat)
Definition: ublas.hpp:302
auto invert_matrix(matrix_u< T > &&mat) -> Maybe< matrix_u< RT >>
逆行列を求める
Definition: ublas.hpp:204
auto eval(F &&f, Args &&...args) -> decltype(f(std::forward< Args >(args)...))
Definition: eval.hpp:37
void for_each_v(F &&func, V &vec, Vs &&...vecs)
ベクトルの全要素に対して、関数を適用する
Definition: ublas.hpp:323
auto from_vector_ublas(V const &vec) -> R
ublas::vector から STLのvectorへ変換
Definition: ublas.hpp:115
boost::numeric::ublas::vector< T > vector_u
Definition: ublas.hpp:49
void for_each_m(F &&func, M &mat)
行列の全要素に対して、代入演算を行う関数を適用する
Definition: ublas.hpp:331
Definition: array.hpp:15
auto to_vector_ublas(C const &vec) -> vector_u< T >
STLのvector から ublas::vector へ変換
Definition: ublas.hpp:161
auto sum(C const &data) -> typename impl::SameIf< R, void, typename impl::container_traits< C >::value_type, R >::type
総和
auto begin(C &&c) -> std::move_iterator< typename RC::iterator >