source: trunk/test/distance_test.cc @ 1582

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

refs #396 - fixing distance_test

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