source: trunk/yat/utility/merge.h @ 2372

Last change on this file since 2372 was 2372, checked in by Peter, 12 years ago

adding concept checks merge

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