source: trunk/test/distance_test.cc @ 1239

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

working on #223

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