source: trunk/test/distance_test.cc @ 1483

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

refs #396 - removing a constructor in MatrixLookupWeighted? - needed to re-organize tests in ncc_test to track down an error

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