source: trunk/test/distance_test.cc @ 2202

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

merging release 0.6 into trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1// $Id: distance_test.cc 2202 2010-02-21 18:39:13Z peter $
2
3/*
4  Copyright (C) 2007 Jari Häkkinen, Markus Ringnér
5  Copyright (C) 2008 Jari Häkkinen, Peter Johansson, Markus Ringnér
6  Copyright (C) 2009, 2010 Peter Johansson
7
8  This file is part of the yat library, http://dev.thep.lu.se/yat
9
10  The yat library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 3 of the
13  License, or (at your option) any later version.
14
15  The yat library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with yat. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "Suite.h"
25
26#include "yat/classifier/DataLookupWeighted1D.h"
27#include "yat/classifier/MatrixLookupWeighted.h"
28#include "yat/statistics/EuclideanDistance.h"
29#include "yat/statistics/PearsonDistance.h"
30#include "yat/utility/DataIterator.h"
31#include "yat/utility/Matrix.h"
32#include "yat/utility/MatrixWeighted.h"
33#include "yat/utility/Vector.h"
34#include "yat/utility/WeightIterator.h"
35
36#include <boost/concept_archetype.hpp>
37
38#include <cassert>
39#include <fstream>
40#include <iostream>
41#include <limits>
42#include <list>
43#include <vector>
44
45
46using namespace theplu::yat;
47
48void check_equality(double, double, test::Suite&, const std::string&, 
49                    unsigned long int N=1);
50utility::Matrix data(void);
51utility::MatrixWeighted data_weighted(void);
52
53template<class Distance>
54void test_distance(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
55
56template<class Distance>
57void test_duplicate(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
58
59template<class Distance>
60void test_rescaling(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
61
62template<class Distance>
63void test_unity_weights(Distance, theplu::yat::test::Suite&, 
64                        unsigned long int N=1);
65
66template<class Distance>
67void test_self_distance(Distance, theplu::yat::test::Suite&, 
68                        unsigned long int N=1);
69
70template<class Distance>
71void test_symmetry(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
72
73template<class Distance>
74void test_zero_weight(Distance, theplu::yat::test::Suite&, 
75                      unsigned long int N=1);
76
77utility::Matrix weight(void);
78
79int main(int argc, char* argv[])
80{ 
81  theplu::yat::test::Suite suite(argc, argv);
82  suite.err() << "testing distance" << std::endl;
83 
84  utility::Vector a(3,1);
85  a(1) = 2;
86  utility::Vector b(3,0);
87  b(2) = 1;
88 
89  statistics::EuclideanDistance eucl_dist;
90  suite.err() << "testing EuclideanDistance" << std::endl;
91  test_distance(eucl_dist, suite, 100);
92  double dist=eucl_dist(a.begin(),a.end(),b.begin());
93  if (!suite.equal_fix(dist, 2.23606797749978988178, 1e-16)) {
94    suite.err() << "Error in unweighted Euclidean distance " << std::endl;
95    suite.add(false);
96  }
97 
98  statistics::PearsonDistance pear_dist;
99  suite.err() << "testing PearsonDistance" << std::endl;
100  test_distance(pear_dist, suite, 1000);
101  dist=pear_dist(a.begin(),a.end(),b.begin());
102  if (!suite.equal(dist, 1.5)) {
103    suite.err() << "Error in unweighted Pearson distance " << std::endl;
104    suite.add(false);
105  }
106 
107 
108  // Testing weighted versions
109  utility::Matrix m(2,3,1);
110  m(0,1)=2;
111  m(1,0)=0;
112  m(1,1)=0;
113  utility::MatrixWeighted m_w(m);
114  m_w(0,0).weight()=0;
115  classifier::MatrixLookupWeighted mw(m_w);
116  classifier::DataLookupWeighted1D aw(mw,0,true);
117  classifier::DataLookupWeighted1D bw(mw,1,true);
118 
119  dist=eucl_dist(aw.begin(),aw.end(),bw.begin());
120 
121  if (!suite.equal_sqrt(dist, sqrt(6))) {
122    suite.err() << "Error in weighted Euclidean distance " << std::endl;
123    suite.add(false);
124  }
125 
126  dist=pear_dist(aw.begin(),aw.end(),bw.begin());
127 
128  if (!suite.equal(dist, 2)) {
129    suite.err() << "Error in weighted Pearson distance " << std::endl;
130    suite.add(false);
131  }
132 
133   
134  // Test with std::vectors
135  std::vector<double> sa(3,1);
136  sa[1] = 2;
137  std::vector<double> sb(3,0);
138  sb[2] = 1;
139 
140  double tolerance=1e-4;
141  dist=eucl_dist(sa.begin(),sa.end(),sb.begin()); 
142  if(!suite.equal_fix(dist, 2.23607,tolerance)) {
143    suite.err() << "Error in distance for std::vector " << std::endl;
144    suite.add(false);
145  }
146 
147  // Test for a std::list and a std::vector
148  std::list<double> la;
149  std::copy(sa.begin(),sa.end(),std::back_inserter<std::list<double> >(la));
150  dist=eucl_dist(la.begin(),la.end(),sb.begin());
151  if(!suite.equal_fix(dist, 2.23607, tolerance) ) {
152    suite.err() << "Error in distance for std::list " << std::endl;
153    suite.add(false);
154  }
155 
156
157  return suite.return_value();
158}
159
160
161void check_equality(double dist1, double dist2, test::Suite& suite, 
162                    const std::string& msg, unsigned long int N)
163{
164  if (!suite.equal(dist1, dist2, N)) {
165    suite.err() << "Error: " << msg << " failed.\n";
166    suite.add(false);
167  }
168}
169
170
171utility::Matrix data(void)
172{
173  utility::Matrix res(2,10);
174  for (size_t i = 0; i<res.columns(); ++i){
175    res(0,i) = i*i+1;
176    res(1,i) = 2*i+3;
177  }
178  return res;
179}
180
181utility::MatrixWeighted data_weighted(void)
182{
183  utility::Matrix x = data();
184  utility::Matrix w = weight();
185  utility::MatrixWeighted res(x.rows(), x.columns());
186  std::copy(x.begin(), x.end(), utility::data_iterator(res.begin()));
187  std::copy(w.begin(), w.end(), utility::weight_iterator(res.begin()));
188  return res;
189}
190
191template<class Distance>
192void test_distance(Distance dist, theplu::yat::test::Suite& suite,
193                   unsigned int long N)
194{
195  test_duplicate(dist, suite, N);
196  test_rescaling(dist, suite, N);
197  test_unity_weights(dist, suite, N);
198  test_self_distance(dist, suite, N);
199  test_symmetry(dist, suite, N);
200  test_zero_weight(dist, suite, N);
201
202  // do not run compiler test
203  if (false) {
204    boost::forward_iterator_archetype<double> iter;
205    boost::forward_iterator_archetype<utility::DataWeight> witer;
206    dist(iter, iter, iter);
207    dist(iter, iter, witer);
208    dist(witer, witer, iter);
209    dist(witer, witer, witer);
210  }
211}
212
213template<class Distance>
214void test_duplicate(Distance dist, theplu::yat::test::Suite& suite, 
215                    unsigned long int N)
216{
217  utility::MatrixWeighted x(data_weighted());
218  utility::MatrixWeighted mw(x.rows(), 2*x.columns());
219  for (size_t i=0; i<x.rows(); ++i){
220    std::copy(x.begin_row(i), x.end_row(i), mw.begin_row(i));
221    std::copy(x.begin_row(i), x.end_row(i), mw.begin_row(i)+x.columns());
222  }
223  double dist1 = dist(mw.begin_row(0), mw.end_row(0), mw.begin_row(1));
224  for (size_t i=0; i<x.columns(); ++i)
225    mw(0,i).weight()=0.0;
226  double dist2 = dist(mw.begin_row(0), mw.end_row(0), mw.begin_row(1));
227  check_equality(dist1, dist2, suite, "duplicate property", N);
228}
229
230template<class Distance>
231void test_rescaling(Distance dist, theplu::yat::test::Suite& suite, 
232                    unsigned long int N)
233{
234  utility::MatrixWeighted wx=data_weighted();
235  double dist1 = dist(wx.begin_row(0), wx.end_row(0), wx.begin_row(1));
236  // rescale weights
237  for (size_t i=0; i<wx.rows(); ++i)
238    for (size_t j=0; j<wx.columns(); ++j)
239      wx(i,j).weight() *= 2.13;
240  double dist2 = dist(wx.begin_row(0), wx.end_row(0), wx.begin_row(1));
241  check_equality(dist1, dist2, suite, "rescaling", N);
242}
243
244template<class Distance>
245void test_unity_weights(Distance dist, theplu::yat::test::Suite& suite, 
246                        unsigned long int N)
247{
248  utility::Matrix x=data();
249  utility::MatrixWeighted mw(x);
250  double dist1 = dist(mw.begin_row(0), mw.end_row(0), mw.begin_row(1));
251  double dist2 = dist(x.begin_row(0), x.end_row(0), x.begin_row(1));
252  check_equality(dist1, dist2, suite, "unity weights", N);
253}
254
255template<class Distance>
256void test_self_distance(Distance dist, theplu::yat::test::Suite& suite, 
257                        unsigned long int N)
258{
259  utility::Matrix x = data();
260  double self = dist(x.begin(), x.end(), x.begin());
261  if (!suite.equal_fix(self,0, N*std::numeric_limits<double>().epsilon()) ) {
262    suite.err() << "error: self distance is " << self << "\n"
263                << "supposed to be zero.\n";
264    suite.add(false);
265  }
266}
267
268
269template<class Distance>
270void test_symmetry(Distance dist, theplu::yat::test::Suite& suite, 
271                   unsigned long int N)
272{
273  utility::Matrix x = data();
274  double distab = dist(x.begin_row(0), x.end_row(0), x.begin_row(1));
275  double distba = dist(x.begin_row(1), x.end_row(1), x.begin_row(0));
276  check_equality(distab, distba, suite, "symmetry test", N);
277}
278
279
280template<class Distance>
281void test_zero_weight(Distance dist, theplu::yat::test::Suite& suite, 
282                      unsigned long int N)
283{
284  utility::MatrixWeighted wx=data_weighted();
285  wx(0,0).weight() = 0.0;
286  double dist1 = dist(wx.begin_row(0), wx.end_row(0), wx.begin_row(1));
287  wx(0,0).weight() = 100*std::numeric_limits<double>().epsilon();
288  double dist2 = dist(wx.begin_row(0), wx.end_row(0), wx.begin_row(1));
289  check_equality(dist1, dist2, suite, "zero weight", N);
290}
291
292utility::Matrix weight(void)
293{
294  utility::Matrix res(2,10);
295  for (size_t i = 0; i<res.columns(); ++i){
296    res(0,i) = 1.0/(1+i);
297    res(1,i) = 1.0-0.1*i;
298  }
299  return res;
300}
301
Note: See TracBrowser for help on using the repository browser.