yat/utility/merge.h

Code
Comments
Other
Rev Date Author Line
1989 12 Jun 09 peter 1 #ifndef _theplu_yat_utility_merge_
3224 12 May 14 peter 2 #define _theplu_yat_utility_merge_
1989 12 Jun 09 peter 3
1989 12 Jun 09 peter 4 // $Id$
1989 12 Jun 09 peter 5
1989 12 Jun 09 peter 6 /*
3224 12 May 14 peter 7   Copyright (C) 2009, 2010, 2014 Peter Johansson
1989 12 Jun 09 peter 8
1989 12 Jun 09 peter 9   This file is part of the yat library, http://dev.thep.lu.se/yat
1989 12 Jun 09 peter 10
1989 12 Jun 09 peter 11   The yat library is free software; you can redistribute it and/or
1989 12 Jun 09 peter 12   modify it under the terms of the GNU General Public License as
1989 12 Jun 09 peter 13   published by the Free Software Foundation; either version 3 of the
1989 12 Jun 09 peter 14   License, or (at your option) any later version.
1989 12 Jun 09 peter 15
1989 12 Jun 09 peter 16   The yat library is distributed in the hope that it will be useful,
1989 12 Jun 09 peter 17   but WITHOUT ANY WARRANTY; without even the implied warranty of
1989 12 Jun 09 peter 18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1989 12 Jun 09 peter 19   General Public License for more details.
1989 12 Jun 09 peter 20
1989 12 Jun 09 peter 21   You should have received a copy of the GNU General Public License
1989 12 Jun 09 peter 22   along with yat. If not, see <http://www.gnu.org/licenses/>.
1989 12 Jun 09 peter 23 */
1989 12 Jun 09 peter 24
2262 26 May 10 peter 25 #include "concept_check.h"
1989 12 Jun 09 peter 26 #include "Matrix.h"
1993 12 Jun 09 peter 27 #include "MatrixWeighted.h"
1990 12 Jun 09 peter 28 #include "stl_utility.h"
1989 12 Jun 09 peter 29
1990 12 Jun 09 peter 30 #include "yat/statistics/Average.h"
1990 12 Jun 09 peter 31
2262 26 May 10 peter 32 #include <boost/concept_check.hpp>
1990 12 Jun 09 peter 33 #include <boost/iterator/permutation_iterator.hpp>
1990 12 Jun 09 peter 34
1990 12 Jun 09 peter 35 #include <algorithm>
1990 12 Jun 09 peter 36 #include <map>
1989 12 Jun 09 peter 37 #include <string>
1989 12 Jun 09 peter 38 #include <vector>
1989 12 Jun 09 peter 39
1989 12 Jun 09 peter 40 namespace theplu {
1989 12 Jun 09 peter 41 namespace yat {
1989 12 Jun 09 peter 42 namespace utility {
1989 12 Jun 09 peter 43
1989 12 Jun 09 peter 44   /**
1999 13 Jun 09 peter 45      \brief merge rows in a \ref concept_container_2d
1999 13 Jun 09 peter 46
1999 13 Jun 09 peter 47      When two (or several) elements in \a labels are found, the
1999 13 Jun 09 peter 48      corresponding rows in \a x are merged into one row vector. The
1999 13 Jun 09 peter 49      vector of \a labels are modified to reflect the rows in the
1999 13 Jun 09 peter 50      resulting container \a y. In this default implementation the
1999 13 Jun 09 peter 51      merge is calculated as the (weighted) arithmetic mean.
1999 13 Jun 09 peter 52
1999 13 Jun 09 peter 53      \a x must be a \ref concept_container_2d and it works for both
1999 13 Jun 09 peter 54      weighted and unweighted containers.
1999 13 Jun 09 peter 55
1999 13 Jun 09 peter 56      \param x input container to be merged.
1999 13 Jun 09 peter 57      \param labels telling which rows to merge.
1999 13 Jun 09 peter 58      \param y resulting merged container.
1999 13 Jun 09 peter 59
1999 13 Jun 09 peter 60      \note If \a x and \a y overlap in their underlying data
1999 13 Jun 09 peter 61      structures, the result is undefined.
2015 31 Jul 09 peter 62
2015 31 Jul 09 peter 63      \since New in yat 0.6
1989 12 Jun 09 peter 64   */
1989 12 Jun 09 peter 65   template<class Container2D>
3224 12 May 14 peter 66   void merge(const Container2D& x, std::vector<std::string>& labels, Matrix& y);
1989 12 Jun 09 peter 67
1993 12 Jun 09 peter 68
1989 12 Jun 09 peter 69   /**
1999 13 Jun 09 peter 70      \brief merge rows in a \ref concept_container_2d using a Functor
1999 13 Jun 09 peter 71
3224 12 May 14 peter 72      Same as merge(const Container2D&, std::vector<std::string>&,
1999 13 Jun 09 peter 73      Matrix&) but instead of calculating the merged element as the
1999 13 Jun 09 peter 74      (weighted) arithmetic mean, the merged element is calculated as
1999 13 Jun 09 peter 75      defined by \a func.
1999 13 Jun 09 peter 76
3224 12 May 14 peter 77      \param x input container to be merged.
3224 12 May 14 peter 78      \param labels telling which rows to merge.
3224 12 May 14 peter 79      \param y resulting merged container.
3224 12 May 14 peter 80      \param func defines how data values are calculated
3224 12 May 14 peter 81
3224 12 May 14 peter 82      \c Functor \a func has an \c operator()(Iterator first, Iterator
3224 12 May 14 peter 83      last) \c const that calculates the merged value from range
3224 12 May 14 peter 84      [first, last).
3224 12 May 14 peter 85
3224 12 May 14 peter 86      Type Requirements:
3224 12 May 14 peter 87      - \c Container2D is a \ref concept_container_2d
3224 12 May 14 peter 88      - \c Functor is a <a href=http://www.sgi.com/tech/stl/BinaryFunction.html>
3224 12 May 14 peter 89      Binary Function</a>.
3224 12 May 14 peter 90      - \c Container2D::const_column_iterator is convertible to
3224 12 May 14 peter 91        argument types of \c Functor.
3224 12 May 14 peter 92      - \c Return type of \c Functor is convertible to \c double
3224 12 May 14 peter 93
1999 13 Jun 09 peter 94      If Functor works on both unweighted and weighted iterators, merge
1999 13 Jun 09 peter 95      works on both unweighted and weighted Container2D.
2015 31 Jul 09 peter 96
3224 12 May 14 peter 97      \note If \a x and \a y overlap in their underlying data
3224 12 May 14 peter 98      structures, the result is undefined.
3224 12 May 14 peter 99
2015 31 Jul 09 peter 100      \since New in yat 0.6
1989 12 Jun 09 peter 101   */
1989 12 Jun 09 peter 102   template<class Container2D, class Functor>
1989 12 Jun 09 peter 103   void merge(const Container2D& x, std::vector<std::string>& labels, Matrix& y,
3224 12 May 14 peter 104              Functor func);
1989 12 Jun 09 peter 105
1993 12 Jun 09 peter 106   /**
1999 13 Jun 09 peter 107      \brief merge rows in a \ref concept_container_2d to a MatrixWeighted
1999 13 Jun 09 peter 108
1999 13 Jun 09 peter 109      When two (or several) elements in \a labels are found, the
1999 13 Jun 09 peter 110      corresponding rows in \a x are merged into one row vector. The
1999 13 Jun 09 peter 111      vector of \a labels are modified to reflect the rows in the
1999 13 Jun 09 peter 112      resulting container \a y.
1999 13 Jun 09 peter 113
1999 13 Jun 09 peter 114      The data value of each element is calculated as defined by \a
1999 13 Jun 09 peter 115      data_func and and the weight value is calculated as defined by \a
1999 13 Jun 09 peter 116      weight_func.
1999 13 Jun 09 peter 117
1999 13 Jun 09 peter 118      \a x must be a \ref concept_container_2d.  If Functor1 and
1999 13 Jun 09 peter 119      Functor2 work on both unweighted and weighted iterators, merge
1999 13 Jun 09 peter 120      works on both unweighted and weighted Container2D.
1999 13 Jun 09 peter 121
1999 13 Jun 09 peter 122      \param x input container to be merged.
1999 13 Jun 09 peter 123      \param labels telling which rows to merge.
1999 13 Jun 09 peter 124      \param y resulting merged container.
1999 13 Jun 09 peter 125      \param data_func defines how data values are calculated
1999 13 Jun 09 peter 126      \param weight_func defines how weight values are calculated
1999 13 Jun 09 peter 127
3224 12 May 14 peter 128      \c Functor1 and \c Functor2 have an \c operator()(Iterator first,
3224 12 May 14 peter 129      Iterator last) \c const that calculates the merged value and
3224 12 May 14 peter 130      weight, respectively, from range [first, last).
3224 12 May 14 peter 131
3224 12 May 14 peter 132      Type Requirements:
3224 12 May 14 peter 133      - \c Container2D is a \ref concept_container_2d
3224 12 May 14 peter 134      - \c Functor1 is a <a href=http://www.sgi.com/tech/stl/BinaryFunction.html>
3224 12 May 14 peter 135      Binary Function</a>.
3224 12 May 14 peter 136      - \c Functor2 is a <a href=http://www.sgi.com/tech/stl/BinaryFunction.html>
3224 12 May 14 peter 137      Binary Function</a>.
3224 12 May 14 peter 138      - \c Container2D::const_column_iterator is convertible to
3224 12 May 14 peter 139        argument types of \c Functor1 and \c Functor2.
3224 12 May 14 peter 140      - \c Return type of \c Functor1 is convertible to \c double
3224 12 May 14 peter 141      - \c Return type of \c Functor2 is convertible to \c double
3224 12 May 14 peter 142
3224 12 May 14 peter 143      If \c Functor1 and \c Functor2 work on both unweighted and
3224 12 May 14 peter 144      weighted iterators, merge works on both unweighted and weighted
3224 12 May 14 peter 145      Container2D.
3224 12 May 14 peter 146
1999 13 Jun 09 peter 147      \note If \a x and \a y overlap in their underlying data
1999 13 Jun 09 peter 148      structures, the result is undefined.
2015 31 Jul 09 peter 149
2015 31 Jul 09 peter 150      \since New in yat 0.6
1993 12 Jun 09 peter 151   */
1993 12 Jun 09 peter 152   template<class Container2D, class Functor1, class Functor2>
3224 12 May 14 peter 153   void merge(const Container2D& x, std::vector<std::string>& labels,
3224 12 May 14 peter 154              MatrixWeighted& y, Functor1 data_func, Functor2 weight_func);
1989 12 Jun 09 peter 155
1993 12 Jun 09 peter 156   namespace detail {
3224 12 May 14 peter 157
1993 12 Jun 09 peter 158     /**
1993 12 Jun 09 peter 159        assign x using func1 on range [first, last).
1989 12 Jun 09 peter 160
1993 12 Jun 09 peter 161        func2 is not used but exists solely to keep the signature
1993 12 Jun 09 peter 162        similar to assign(DataWeight&, ...)
1993 12 Jun 09 peter 163      */
1993 12 Jun 09 peter 164     template<typename Iterator, class Functor1, class Functor2>
1993 12 Jun 09 peter 165     void assign(double& x, Iterator first, Iterator last, Functor1 func1,
1993 12 Jun 09 peter 166                 Functor2 func2);
1993 12 Jun 09 peter 167
1993 12 Jun 09 peter 168     /**
1993 12 Jun 09 peter 169        assign x.data() using func1 on range [first, last).
1993 12 Jun 09 peter 170        assign x.weight() using func2 on range [first, last).
1993 12 Jun 09 peter 171
1993 12 Jun 09 peter 172      */
1993 12 Jun 09 peter 173     template<typename Iterator, class Functor1, class Functor2>
1993 12 Jun 09 peter 174     void assign(DataWeight& x, Iterator first, Iterator last, Functor1 func1,
1993 12 Jun 09 peter 175                 Functor2 func2);
1993 12 Jun 09 peter 176
3224 12 May 14 peter 177     void merge_labels(std::vector<std::string>&,
1993 12 Jun 09 peter 178                       std::map<std::string, std::vector<size_t> >&);
1993 12 Jun 09 peter 179
1993 12 Jun 09 peter 180
3224 12 May 14 peter 181     template<class Container2D, class MutableContainer2D,
1993 12 Jun 09 peter 182              class Functor1, class Functor2>
3224 12 May 14 peter 183     void merge(const Container2D& x,
3224 12 May 14 peter 184                std::map<std::string, std::vector<size_t> >& label2index,
1993 12 Jun 09 peter 185                MutableContainer2D& result, Functor1 func1, Functor2 func2);
1993 12 Jun 09 peter 186
1993 12 Jun 09 peter 187   } // end of private namespace detail
1993 12 Jun 09 peter 188
1993 12 Jun 09 peter 189
1993 12 Jun 09 peter 190   // template implementations //
1993 12 Jun 09 peter 191
1989 12 Jun 09 peter 192   template<class Container2D>
1989 12 Jun 09 peter 193   void merge(const Container2D& x, std::vector<std::string>& labels, Matrix& y)
1989 12 Jun 09 peter 194   {
2262 26 May 10 peter 195     BOOST_CONCEPT_ASSERT((utility::Container2D<Container2D>));
1990 12 Jun 09 peter 196     merge(x, labels, y, statistics::Average());
1990 12 Jun 09 peter 197   }
1990 12 Jun 09 peter 198
1990 12 Jun 09 peter 199   template<class Container2D, class Functor>
3224 12 May 14 peter 200   void merge(const Container2D& x, std::vector<std::string>& labels,
1990 12 Jun 09 peter 201              Matrix& result, Functor func)
1990 12 Jun 09 peter 202   {
2262 26 May 10 peter 203     BOOST_CONCEPT_ASSERT((utility::Container2D<Container2D>));
1993 12 Jun 09 peter 204     std::map<std::string, std::vector<size_t> > label2index;
1993 12 Jun 09 peter 205     detail::merge_labels(labels, label2index);
1993 12 Jun 09 peter 206     detail::merge(x, label2index, result, func, func);
1993 12 Jun 09 peter 207   }
1990 12 Jun 09 peter 208
1990 12 Jun 09 peter 209
1993 12 Jun 09 peter 210   template<class Container2D, class Functor1, class Functor2>
3224 12 May 14 peter 211   void merge(const Container2D& x, std::vector<std::string>& labels,
1993 12 Jun 09 peter 212              MatrixWeighted& result, Functor1 func1, Functor2 func2)
1993 12 Jun 09 peter 213   {
2262 26 May 10 peter 214     BOOST_CONCEPT_ASSERT((utility::Container2D<Container2D>));
1993 12 Jun 09 peter 215     std::map<std::string, std::vector<size_t> > label2index;
1993 12 Jun 09 peter 216     detail::merge_labels(labels, label2index);
1993 12 Jun 09 peter 217     detail::merge(x, label2index, result, func1, func2);
3224 12 May 14 peter 218   }
1989 12 Jun 09 peter 219
1993 12 Jun 09 peter 220   // implemantions of private functions
1993 12 Jun 09 peter 221
1993 12 Jun 09 peter 222   namespace detail {
1993 12 Jun 09 peter 223     template<typename Iterator, class Functor1, class Functor2>
1993 12 Jun 09 peter 224     void assign(double& x, Iterator first, Iterator last, Functor1 func1,
1993 12 Jun 09 peter 225                 Functor2 func)
1993 12 Jun 09 peter 226     {
1993 12 Jun 09 peter 227       x = func1(first, last);
1993 12 Jun 09 peter 228     }
1993 12 Jun 09 peter 229
1993 12 Jun 09 peter 230
1993 12 Jun 09 peter 231     template<typename Iterator, class Functor1, class Functor2>
1993 12 Jun 09 peter 232     void assign(DataWeight& x, Iterator first, Iterator last, Functor1 func1,
2252 16 May 10 peter 233                 Functor2 func2)
1993 12 Jun 09 peter 234     {
1993 12 Jun 09 peter 235       x.data() = func1(first, last);
1993 12 Jun 09 peter 236       x.weight() = func2(first, last);
1993 12 Jun 09 peter 237     }
1993 12 Jun 09 peter 238
1993 12 Jun 09 peter 239
3224 12 May 14 peter 240     void merge_labels(std::vector<std::string>& labels,
1993 12 Jun 09 peter 241                       std::map<std::string, std::vector<size_t> >& label2index)
1993 12 Jun 09 peter 242     {
1993 12 Jun 09 peter 243       inverse(labels.begin(), labels.end(), label2index);
1993 12 Jun 09 peter 244       labels.resize(label2index.size());
1993 12 Jun 09 peter 245       std::copy(pair_first_iterator(label2index.begin()),
1993 12 Jun 09 peter 246                 pair_first_iterator(label2index.end()),
1993 12 Jun 09 peter 247                 labels.begin());
1993 12 Jun 09 peter 248     }
1993 12 Jun 09 peter 249
1993 12 Jun 09 peter 250
3224 12 May 14 peter 251     template<class Container2D, class MutableContainer2D,
1993 12 Jun 09 peter 252              class Functor1, class Functor2>
3224 12 May 14 peter 253     void merge(const Container2D& x,
3224 12 May 14 peter 254                std::map<std::string, std::vector<size_t> >& label2index,
1993 12 Jun 09 peter 255                MutableContainer2D& result, Functor1 func1, Functor2 func2)
1993 12 Jun 09 peter 256     {
2372 12 Dec 10 peter 257       BOOST_CONCEPT_ASSERT((utility::Mutable_Container2D<MutableContainer2D>));
2372 12 Dec 10 peter 258       BOOST_CONCEPT_ASSERT((utility::Container2D<Container2D>));
1993 12 Jun 09 peter 259       result.resize(label2index.size(), x.columns());
1993 12 Jun 09 peter 260       typedef std::map<std::string, std::vector<size_t> > Map;
3224 12 May 14 peter 261       Map::const_iterator iter=label2index.begin();
1993 12 Jun 09 peter 262
1993 12 Jun 09 peter 263       for (size_t row=0; row<result.rows(); ++row) {
1993 12 Jun 09 peter 264         const std::vector<size_t>& index = iter->second;
1993 12 Jun 09 peter 265         for (size_t col=0; col<result.columns(); ++col) {
3225 12 May 14 peter 266           using boost::make_permutation_iterator;
3224 12 May 14 peter 267           assign(result(row,col),
3225 12 May 14 peter 268                  make_permutation_iterator(x.begin_column(col), index.begin()),
3225 12 May 14 peter 269                  make_permutation_iterator(x.end_column(col),  index.end()),
1993 12 Jun 09 peter 270                  func1, func2);
1993 12 Jun 09 peter 271         }
1993 12 Jun 09 peter 272         ++iter;
1993 12 Jun 09 peter 273       }
3224 12 May 14 peter 274     }
1993 12 Jun 09 peter 275
1993 12 Jun 09 peter 276   } // end of namespace detail
1993 12 Jun 09 peter 277
1989 12 Jun 09 peter 278 }}} // of namespace utility, yat, and theplu
1989 12 Jun 09 peter 279
1989 12 Jun 09 peter 280 #endif