source: trunk/test/distance_test.cc @ 1247

Last change on this file since 1247 was 1247, checked in by Peter, 14 years ago

refs #223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.1 KB
Line 
1// $Id: distance_test.cc 1247 2008-03-17 14:54:10Z peter $
2
3/*
4  Copyright (C) 2007 Peter Johansson, Markus Ringnér
5
6  This file is part of the yat library, http://trac.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 2 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 this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
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/Matrix.h"
31#include "yat/utility/Vector.h"
32
33#include <cassert>
34#include <fstream>
35#include <iostream>
36#include <limits>
37#include <list>
38#include <vector>
39
40
41using namespace theplu::yat;
42
43void check_equality(double, double, test::Suite&, const std::string&, 
44                    u_int N=1);
45utility::Matrix data(void);
46
47template<class Distance>
48void test_distance(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
49
50template<class Distance>
51void test_duplicate(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
52
53template<class Distance>
54void test_rescaling(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
55
56template<class Distance>
57void test_unity_weights(Distance, theplu::yat::test::Suite&, 
58                        unsigned long int N=1);
59
60template<class Distance>
61void test_self_distance(Distance, theplu::yat::test::Suite&, 
62                        unsigned long int N=1);
63
64template<class Distance>
65void test_symmetry(Distance, theplu::yat::test::Suite&, unsigned long int N=1);
66
67template<class Distance>
68void test_zero_weight(Distance, theplu::yat::test::Suite&, 
69                      unsigned long int N=1);
70
71utility::Matrix weight(void);
72
73int main(int argc, char* argv[])
74{ 
75  theplu::yat::test::Suite suite(argc, argv);
76  suite.err() << "testing distance" << std::endl;
77 
78  utility::Vector a(3,1);
79  a(1) = 2;
80  utility::Vector b(3,0);
81  b(2) = 1;
82 
83  double tolerance=1e-4;
84  statistics::EuclideanDistance eucl_dist;
85  suite.err() << "testing EuclideanDistance" << std::endl;
86  test_distance(eucl_dist, suite, 100);
87  double dist=eucl_dist(a.begin(),a.end(),b.begin());
88  if(std::abs(dist-2.23607)>tolerance) {
89    suite.err() << "Error in unweighted Euclidean distance " << std::endl;
90    suite.add(false);
91  }
92 
93  statistics::PearsonDistance pear_dist;
94  suite.err() << "testing PearsonDistance" << std::endl;
95  test_distance(pear_dist, suite, 1000);
96  dist=pear_dist(a.begin(),a.end(),b.begin());
97  if(std::abs(dist-1.5)>tolerance) {
98    suite.err() << "Error in unweighted Pearson distance " << std::endl;
99    suite.add(false);
100  }
101 
102 
103  // Testing weighted versions
104  utility::Matrix m(2,3,1);
105  m(0,1)=2;
106  m(1,0)=0;
107  m(1,1)=0;
108  utility::Matrix w(2,3,1);
109  w(0,0)=0;
110  classifier::MatrixLookupWeighted mw(m,w);
111  classifier::DataLookupWeighted1D aw(mw,0,true);
112  classifier::DataLookupWeighted1D bw(mw,1,true);
113 
114  dist=eucl_dist(aw.begin(),aw.end(),bw.begin());
115 
116  if(std::abs(dist-sqrt(6))>tolerance) {
117    suite.err() << "Error in weighted Euclidean distance " << std::endl;
118    suite.add(false);
119  }
120 
121  dist=pear_dist(aw.begin(),aw.end(),bw.begin());
122 
123  if(std::abs(dist-2)>tolerance) {
124    suite.err() << "Error in weighted Pearson distance " << std::endl;
125    suite.add(false);
126  }
127 
128   
129  // Test with std::vectors
130  std::vector<double> sa(3,1);
131  sa[1] = 2;
132  std::vector<double> sb(3,0);
133  sb[2] = 1;
134 
135  dist=eucl_dist(sa.begin(),sa.end(),sb.begin()); 
136  if(std::abs(dist-2.23607)>tolerance) {
137    suite.err() << "Error in distance for std::vector " << std::endl;
138    suite.add(false);
139  }
140 
141  // Test for a std::list and a std::vector
142  std::list<double> la;
143  std::copy(sa.begin(),sa.end(),std::back_inserter<std::list<double> >(la));
144  dist=eucl_dist(la.begin(),la.end(),sb.begin());
145  if(std::abs(dist-2.23607)>tolerance) {
146    suite.err() << "Error in distance for std::list " << std::endl;
147    suite.add(false);
148  }
149 
150
151  return suite.return_value();
152}
153
154
155void check_equality(double dist1, double dist2, test::Suite& suite, 
156                    const std::string& msg, u_int N)
157{
158  if (!suite.equal(dist1, dist2, N)) {
159    suite.err() << "Error: " << msg << " failed.\n";
160    suite.add(false);
161  }
162}
163
164
165utility::Matrix data(void)
166{
167  utility::Matrix res(2,10);
168  for (size_t i = 0; i<res.columns(); ++i){
169    res(0,i) = i*i+1;
170    res(1,i) = 2*i+3;
171  }
172  return res;
173}
174
175template<class Distance>
176void test_distance(Distance dist, theplu::yat::test::Suite& suite,
177                   unsigned int long N)
178{
179  test_duplicate(dist, suite, N);
180  test_rescaling(dist, suite, N);
181  test_unity_weights(dist, suite, N);
182  test_self_distance(dist, suite, N);
183  test_symmetry(dist, suite, N);
184  test_zero_weight(dist, suite, N);
185}
186
187template<class Distance>
188void test_duplicate(Distance dist, theplu::yat::test::Suite& suite, 
189                    unsigned long int N)
190{
191  utility::Matrix x(data());
192  utility::Matrix x2(x.rows(), 2*x.columns());
193  for (size_t i=0; i<x.rows(); ++i){
194    std::copy(x.begin_row(i), x.end_row(i), x2.begin_row(i));
195    std::copy(x.begin_row(i), x.end_row(i), x2.begin_row(i)+x.columns());
196  }
197  utility::Matrix w(weight());
198  utility::Matrix w2(w.rows(), 2*w.columns());
199  for (size_t i=0; i<w.rows(); ++i){
200    std::copy(w.begin_row(i), w.end_row(i), w2.begin_row(i));
201    std::copy(w.begin_row(i), w.end_row(i), w2.begin_row(i)+w.columns());
202  }
203  classifier::MatrixLookupWeighted ml(x2, w2);
204  double dist1 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
205  for (size_t i=0; i<w.columns(); ++i)
206    w2(0,i)=0.0;
207  double dist2 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
208  check_equality(dist1, dist2, suite, "duplicate property", N);
209}
210
211template<class Distance>
212void test_rescaling(Distance dist, theplu::yat::test::Suite& suite, 
213                    unsigned long int N)
214{
215  utility::Matrix x=data();
216  utility::Matrix w=weight();
217  classifier::MatrixLookupWeighted ml(x,w);
218  double dist1 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
219  w *= 2.13;
220  double dist2 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
221  check_equality(dist1, dist2, suite, "rescaling", N);
222}
223
224template<class Distance>
225void test_unity_weights(Distance dist, theplu::yat::test::Suite& suite, 
226                        unsigned long int N)
227{
228  utility::Matrix x=data();
229  classifier::MatrixLookupWeighted ml(x);
230  double dist1 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
231  double dist2 = dist(x.begin_row(0), x.end_row(0), x.begin_row(1));
232  check_equality(dist1, dist2, suite, "unity weights", N);
233}
234
235template<class Distance>
236void test_self_distance(Distance dist, theplu::yat::test::Suite& suite, 
237                        unsigned long int N)
238{
239  utility::Matrix x = data();
240  double self = dist(x.begin(), x.end(), x.begin());
241  if (!(std::abs(self) <= N*std::numeric_limits<double>().epsilon()) ){
242    suite.err() << "error: self distance is " << self << "\n"
243                << "supposed to be zero.\n";
244    suite.add(false);
245  }
246}
247
248
249template<class Distance>
250void test_symmetry(Distance dist, theplu::yat::test::Suite& suite, 
251                   unsigned long int N)
252{
253  utility::Matrix x = data();
254  double distab = dist(x.begin_row(0), x.end_row(0), x.begin_row(1));
255  double distba = dist(x.begin_row(1), x.end_row(1), x.begin_row(0));
256  check_equality(distab, distba, suite, "symmetry test", N);
257}
258
259
260template<class Distance>
261void test_zero_weight(Distance dist, theplu::yat::test::Suite& suite, 
262                      unsigned long int N)
263{
264  utility::Matrix x=data();
265  utility::Matrix w=weight();
266  classifier::MatrixLookupWeighted ml(x,w);
267  w(0,0) = 0.0;
268  double dist1 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
269  w(0,0) = 100*std::numeric_limits<double>().epsilon();
270  double dist2 = dist(ml.begin_row(0), ml.end_row(0), ml.begin_row(1));
271  check_equality(dist1, dist2, suite, "zero weight", N);
272}
273
274utility::Matrix weight(void)
275{
276  utility::Matrix res(2,10);
277  for (size_t i = 0; i<res.columns(); ++i){
278    res(0,i) = 1.0/(1+i);
279    res(1,i) = 1.0-0.1*i;
280  }
281  return res;
282}
283
Note: See TracBrowser for help on using the repository browser.