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

Last change on this file since 2015 was 2015, checked in by Peter, 13 years ago

adding missing \since flags

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