Machine Learning Library
sparse_algorithm.h
Go to the documentation of this file.
1 /*
2  COPYRIGHT (C) 2003 APPLIED NEUROINFORMATIC GROUP - UNIVERSITY OF BIELEFELD.
3 
4  ALL RIGHTS RESERVED.
5 
6  REDISTRIBUTION AND USE IN SOURCE AND BINARY FORM, WITH OR WITHOUT
7  MODIFICATION, REQUIRE THE PERMISSION OF THE COPYRIGHT HOLDERS.
8 
9  COMMERCIAL USE WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT HOLDERS
10  IS FORBIDDEN
11 
12  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
13  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
16  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23 
24 
25 
26 #ifndef __SPARSE_ALGORITHM_H
27 #define __SPARSE_ALGORITHM_H
28 
29 #include <numeric>
30 
31 // specializations of the STL numerical algorithms for
32 // work with sparse iterators
33 
34 // BE CAREFUL: 'inner_product' expects its BinaryFunctions to have the
35 // properties of plus and multiplies with regard to an argument or an
36 // intermediate result being 0
37 
38 namespace std {
39 template<typename Iterator, typename Type, typename BinaryFunction1, typename BinaryFunction2>
40 Type inner_product(Iterator lhs, Iterator lhs_end,
41  keyed_iterator<Type> rhs, Type init,
42  BinaryFunction1 f1, BinaryFunction2 f2) {
43  Type result = init;
44  keyed_iterator<Type> rhs_end = rhs + rhs.size();
45 
46  while(rhs != rhs_end) {
47  result = f1(result, f2(lhs[rhs.key()], rhs.val()));
48  ++rhs;
49  }
50  return result;
51 }
52 
53 template<typename Iterator, typename Type, typename BinaryFunction1, typename BinaryFunction2>
55  Iterator rhs, Type init,
56  BinaryFunction1 f1, BinaryFunction2 f2) {
57  Type result = init;
58 
59  while (lhs != lhs_end) {
60  result = f1(result, f2(lhs.val(), rhs[lhs.key()]));
61  ++lhs;
62  }
63  return result;
64 }
65 
66 template<typename Type, typename BinaryFunction1, typename BinaryFunction2>
68  keyed_iterator<Type> rhs, Type init,
69  BinaryFunction1 f1, BinaryFunction2 f2)
70 {
71  Type result = init;
72  keyed_iterator<Type> rhs_end = rhs + rhs.size();
73 
74  while (lhs != lhs_end && rhs != rhs_end) {
75 
76  if (lhs.key() < rhs.key() && lhs != lhs_end) {
77  lhs++;
78  } else if (lhs.key() == rhs.key()) {
79  result = f1(result, f2(lhs.val(), rhs.val()));
80  lhs++;
81  rhs++;
82  } else if(lhs.key() > rhs.key()) {
83  rhs++;
84  }
85  }
86 
87  return result;
88 }
89 
90 } // namespace std
91 
92 
93 
94 template<typename Iterator, typename Type,
95  typename BinaryFunction1, typename BinaryFunction2>
96 Type inner_distance(Iterator lhs, Iterator lhs_end,
97  keyed_iterator<Type> rhs, Type init,
98  BinaryFunction1 f1, BinaryFunction2 f2) {
99  Type result = init;
100  keyed_iterator<Type> rhs_end = rhs + rhs.size();
101  int pos = 0;
102 
103  while(rhs != rhs_end) {
104  int rhs_pos = rhs.key();
105 
106  for(; pos < rhs_pos; ++pos, ++lhs) {
107  result = f1(result, f2(*lhs, static_cast<Type>(0)));
108  }
109  result = f1(result, f2(*lhs, rhs.val()));
110 
111  ++lhs;
112  ++rhs;
113  ++pos;
114  }
115 
116  // iterate over the rest
117  while(lhs != lhs_end) {
118  result = f1(result, f2(*lhs, static_cast<Type>(0)));
119  ++lhs;
120  }
121 
122  return result;
123 }
124 
125 template<typename Iterator, typename Type,
126  typename BinaryFunction1, typename BinaryFunction2>
128  Iterator rhs, Type init,
129  BinaryFunction1 f1, BinaryFunction2 f2)
130 {
131  Type result = init;
132  Iterator rhs_end = rhs + lhs.max();
133  int pos = 0;
134 
135  while(lhs != lhs_end) {
136  int lhs_pos = lhs.key();
137 
138  for(; pos < lhs_pos; ++pos, ++rhs) {
139  result = f1(result, f2(static_cast<Type>(0), *rhs));
140  }
141  result = f1(result, f2(lhs.val(), *rhs));
142 
143  ++lhs;
144  ++rhs;
145  ++pos;
146  }
147 
148  // when dense iterator has entries beyond last entry in
149  // sparse iterator
150  while(rhs != rhs_end) {
151  result = f1(result, f2(static_cast<Type>(0), *rhs));
152  ++rhs;
153  }
154 
155  return result;
156 }
157 
158 template<typename Type,
159  typename BinaryFunction1, typename BinaryFunction2>
161  keyed_iterator<Type> rhs, Type init,
162  BinaryFunction1 f1, BinaryFunction2 f2) {
163  Type result = init;
164  keyed_iterator<Type> rhs_end = rhs + rhs.size();
165 
166  while(lhs != lhs_end && rhs != rhs_end) {
167  if(lhs.key() < rhs.key()) {
168  result = f1(result, f2(lhs.val(), static_cast<Type>(0)));
169  ++lhs;
170  } else if(lhs.key() == rhs.key()) {
171  result = f1(result, f2(lhs.val(), rhs.val()));
172  ++lhs;
173  ++rhs;
174  } else if(lhs.key() > rhs.key()) {
175  result = f1(result, f2(static_cast<Type>(0), rhs.val()));
176  ++rhs;
177  }
178  }
179  // consume leftovers
180  while(lhs != lhs_end) {
181  result = f1(result, f2(lhs.val(), static_cast<Type>(0)));
182  ++lhs;
183  }
184  while(rhs != rhs_end) {
185  result = f1(result, f2(static_cast<Type>(0), rhs.val()));
186  ++rhs;
187  }
188 
189  return result;
190 }
191 
192 
193 // fall back for standard iterators
194 template<typename Iterator1, typename Iterator2, typename Type,
195  typename BinaryFunction1, typename BinaryFunction2>
196 Type inner_distance(Iterator1 lhs, Iterator1 lhs_end,
197  Iterator2 rhs, Type init,
198  BinaryFunction1 f1, BinaryFunction2 f2) {
199  return inner_product(lhs, lhs_end, rhs, init, f1, f2);
200 }
201 
202 
203 // CO COSINE DISTANCE
204 
205 template<typename Iterator, typename Type, typename BinaryFunction1, typename BinaryFunction2>
206 Type coCosine_distance(Iterator lhs, Iterator lhs_end,
207  keyed_iterator<Type> rhs, Type init,
208  BinaryFunction1 f1, BinaryFunction2 f2) {
209 
210  Type result = init;
211  Type lLen = init;
212  Type rLen = init;
213 
214  keyed_iterator<Type> rhs_end = rhs + rhs.size();
215 
216  while (rhs != rhs_end) {
217  result = f1(result, f2(lhs[rhs.key()], rhs.val()));
218  lLen = f1(lLen, f2(lhs[rhs.key()], rhs.val()));
219  rLen += rhs.val() * rhs.val();
220  rhs++;
221  }
222 
223  if (lLen * rLen > 0) result /= sqrt(lLen * rLen);
224  return result;
225 }
226 
227 template<typename Iterator, typename Type, typename BinaryFunction1, typename BinaryFunction2>
229  Iterator rhs, Type init,
230  BinaryFunction1 f1, BinaryFunction2 f2) {
231 
232  Type result = init;
233  Type lLen = 0;
234  Type rLen = 0;
235 
236  while (lhs != lhs_end) {
237  result = f1(result, f2(lhs.val(), rhs[lhs.key()]));
238  lLen += lhs.val() * lhs.val();
239  rLen += rhs[lhs.key()] * rhs[lhs.key()];
240  lhs++;
241  }
242 
243  if (lLen * rLen > 0) result /= sqrt(lLen * rLen);
244  return result;
245 }
246 
247 
248 template<typename Type, typename BinaryFunction1, typename BinaryFunction2>
250  keyed_iterator<Type> rhs, Type init,
251  BinaryFunction1 f1, BinaryFunction2 f2) {
252 
253  Type result = init;
254  Type lLen = 0;
255  Type rLen = 0;
256 
257  keyed_iterator<Type> rhs_end = rhs + rhs.size();
258 
259  while (lhs != lhs_end && rhs != rhs_end) {
260 
261  if (lhs.key() < rhs.key() && lhs != lhs_end) {
262  lhs++;
263  } else if (lhs.key() == rhs.key()) {
264  result = f1(result, f2(lhs.val(), rhs.val()));
265  lLen += lhs.val() * lhs.val();
266  rLen += rhs.val() * rhs.val();
267 
268  lhs++;
269  rhs++;
270  } else if(lhs.key() > rhs.key()) {
271  rhs++;
272  }
273  }
274 
275  if (lLen * rLen > 0) result /= sqrt(lLen * rLen);
276  return result;
277 }
278 
279 
280 // fall back for standard iterators
281 template<typename Iterator1, typename Iterator2, typename Type, typename BinaryFunction1, typename BinaryFunction2>
282 Type coCosine_distance(Iterator1 lhs, Iterator1 lhs_end,
283  Iterator2 rhs, Type init,
284  BinaryFunction1 f1, BinaryFunction2 f2) {
285 
286  Type result = init;
287  Type lLen = 0;
288  Type rLen = 0;
289 
290  while (lhs != lhs_end) {
291  result = f1(result, f2(*lhs, *rhs));
292  lLen += *lhs * *lhs;
293  rLen += *rhs * *rhs;
294  lhs++;
295  rhs++;
296  }
297 
298  if (lLen * rLen > 0) result /= sqrt(lLen * rLen);
299  return result;
300 }
301 
302 // ELEMENT_PRODUCT
303 
304 template<typename T1, typename BinaryFunction>
307  keyed_iterator<T1> out,
308  BinaryFunction f)
309 {
310  for(; l != l_end; ++l, ++out) {
311  while(r != r_end && r.key() < l.key()) {
312  ++r;
313  }
314  if(r != r_end && r.key() == l.key()) {
315  out.val() = f(l.val(), r.val());
316  } else {
317  out.val() = 0;
318  }
319  }
320 }
321 
322 template<typename Type, typename BinaryFunction, typename Iterator>
325  Iterator out, BinaryFunction f)
326 {
327  // because we might not hit every index, delete it first
328  memset(out, 0, l.max() * sizeof(Type));
329 
330  for(; l != l_end; ++l, ++r) {
331  while(r != r_end && r.key() < l.key()) {
332  ++r;
333  }
334  if(r != r_end && r.key() == l.key()) {
335  out[r.key()] = f(l.val(), r.val());
336  }
337  }
338 }
339 
340 
341 template<typename Iterator, typename Ti,
342  typename To, typename BinaryFunction>
343 void element_product(Iterator l, Iterator l_end,
345  keyed_iterator<To> out,
346  BinaryFunction f)
347 {
348  for(int i = 0; l != l_end; ++i, ++l) {
349  if(i == r.key()) {
350  out.val() = f(*l, r.val());
351  ++r;
352  ++out;
353  }
354  }
355 }
356 
357 template<typename Iterator, typename Type, typename BinaryFunction,
358  typename OutputIterator>
359 void element_product(Iterator l, Iterator l_end,
361  OutputIterator out, BinaryFunction f)
362 {
363  for(int i = 0; l != l_end; ++i, ++l, ++out) {
364  if(i == r.key()) {
365  *out = f(*l, r.val());
366  ++r;
367  } else {
368  *out = f(*l, 0);
369  }
370  }
371 
372 }
373 
374 template<typename Type, typename Iterator, typename BinaryFunction>
376  Iterator r, Iterator r_end,
377  keyed_iterator<Type> out, BinaryFunction f)
378 {
379  while(l != l_end) {
380  *out = make_pair(l.key(), f(l.val(), r[l.key()]));
381  ++l; ++out;
382  }
383 }
384 
385 template<typename Type, typename Iterator, typename BinaryFunction, typename OutputIterator>
387  Iterator r, Iterator r_end,
388  OutputIterator out, BinaryFunction f)
389 {
390  int index = 0;
391  while(r != r_end) {
392  if(index == l.key()) {
393  *out = f(l.val(), *r);
394  ++l;
395  }
396  ++out;
397  ++r;
398  ++index;
399  }
400 }
401 
402 
403 
404 template<typename Iterator1, typename Iterator2,
405  typename OutputIterator, typename BinaryFunction>
406 void element_product(Iterator1 l, Iterator1 l_end,
407  Iterator2 r, Iterator2 r_end,
408  OutputIterator out, BinaryFunction f)
409 {
410  while(l != l_end) {
411  *out = f(*l, *r);
412  ++l; ++r; ++out;
413  }
414 }
415 
416 /*template<typename Iterator, typename Type, typename BinaryFunction>
417  void element_product(Iterator l, Iterator l_end, Type val,
418  keyed_iterator<Type> out, BinaryFunction f)
419  {
420  for(; l != l_end; ++l, ++out) {
421  out.val() = f(*l, val);
422  }
423  }*/
424 
425 template<typename T1, typename BinaryFunction>
427  T1 val, keyed_iterator<T1> out, BinaryFunction f)
428 {
429  for(; l != l_end; ++l, ++out) {
430  out.val() = f(l.val(), val);
431  }
432 }
433 
434 template<typename Iterator, typename Type, typename BinaryFunction>
435 void element_product(Iterator l, Iterator l_end, Type val, Iterator out,
436  BinaryFunction f)
437 {
438  while(l != l_end) {
439  *out = f(*l, val);
440  ++l; ++ out;
441  }
442 }
443 
444 // ELEMENT_ADD
445 
446 template<typename Iterator, typename OutputIterator, typename BinaryFunction>
447 void element_add(Iterator l, Iterator l_end,
448  Iterator r, Iterator r_end,
449  OutputIterator out, BinaryFunction f)
450 {
451  while(l != l_end) {
452  *out = f(*l, *r);
453  ++l; ++r; ++out;
454  }
455 }
456 template<typename Type, typename OutputIterator, typename BinaryFunction>
459  OutputIterator out, BinaryFunction f)
460 {
461  memset(out, 0, l.max() * sizeof(Type));
462  while(l != l_end) {
463  out[l.key()] = l.val();
464  ++l;
465  }
466  while(r != r_end) {
467  out[r.key()] = f(out[r.key()], r.val());
468  ++r;
469  }
470 }
471 template<typename Iterator, typename Type,
472  typename OutputIterator, typename BinaryFunction>
473 void element_add(Iterator l, Iterator l_end,
475  OutputIterator out, BinaryFunction f)
476 {
477  OutputIterator start = out;
478 
479  while(l != l_end) {
480  *out = *l;
481  ++l; ++out;
482  }
483  while(r != r_end) {
484  start[r.key()] = f(start[r.key()], r.val());
485  ++r;
486  }
487 }
488 template<typename Iterator, typename Type,
489  typename OutputIterator, typename BinaryFunction>
491  Iterator r, Iterator r_end,
492  OutputIterator out, BinaryFunction f)
493 {
494  int pos = 0;
495 
496  while(r != r_end) {
497  if(pos == l.key()) {
498  *out = f(l.val(), *r);
499  ++l;
500  } else {
501  *out = f(static_cast<Type>(0), *r);
502  }
503  ++r; ++out; ++pos;
504  }
505 }
506 
507 // used for vector adaption ----------------------------------------
508 template<typename Type, typename BinaryFunction>
512  BinaryFunction f, float fEps1, float fEps2)
513 {
514  throw CException("Adaptation of sparse vectors is not supported.");
515 }
516 
517 template<typename Type, typename Iterator, typename BinaryFunction, typename OutputIterator>
519  Iterator r, Iterator r_end,
520  OutputIterator out, BinaryFunction f, float fEps1, float fEps2)
521 {
522  throw CException("Adaptation of sparse vectors is not supported.");
523 }
524 
525 template<typename Iterator, typename Type, typename BinaryFunction, typename OutputIterator>
526 void element_adapt(Iterator l, Iterator l_end,
528  OutputIterator out, BinaryFunction f, float fEps1, float fEps2)
529 {
530  OutputIterator start = out;
531 
532  if (fEps2 != 1) {
533  while (l != l_end) {
534  *out = fEps2 * *l;
535  ++l; ++out;
536  }
537  }
538 
539  while (r != r_end) {
540  start[r.key()] = f(start[r.key()], fEps1 * r.val());
541  ++r;
542  }
543 }
544 
545 template<typename Iterator1, typename Iterator2, typename OutputIterator, typename BinaryFunction>
546 void element_adapt(Iterator1 l, Iterator1 l_end,
547  Iterator2 r, Iterator2 r_end,
548  OutputIterator out, BinaryFunction f, float fEps1, float fEps2)
549 {
550  if (fEps2 == 1) {
551  while (l != l_end) {
552  *out = f(*l, fEps1 * *r);
553  ++l; ++out; ++r;
554  }
555  } else {
556  while (l != l_end) {
557  *out = f(fEps2 * *l, fEps1 * *r);
558  ++l; ++out; ++r;
559  }
560  }
561 }
562 
563 
564 template<typename Type>
566  Type operator()(const Type v1, const Type v2) const
567  {
568  return (v2 - v1)*(v2 - v1);
569  }
570 };
571 
572 /*
573  * Local variables:
574  * mode: c++
575  * End:
576  */
577 
578 #endif // #ifndef __SPARSE_ALGORITHM_H
int key() const
Definition: keyed_iterator.hpp:107
difference_type max() const
Definition: keyed_iterator.hpp:111
int size() const
Definition: keyed_iterator.hpp:110
Type coCosine_distance(Iterator lhs, Iterator lhs_end, keyed_iterator< Type > rhs, Type init, BinaryFunction1 f1, BinaryFunction2 f2)
Definition: sparse_algorithm.h:206
Definition: sparse_algorithm.h:565
void element_add(Iterator l, Iterator l_end, Iterator r, Iterator r_end, OutputIterator out, BinaryFunction f)
Definition: sparse_algorithm.h:447
void element_product(keyed_iterator< T1 > l, keyed_iterator< T1 > l_end, keyed_iterator< T1 > r, keyed_iterator< T1 > r_end, keyed_iterator< T1 > out, BinaryFunction f)
Definition: sparse_algorithm.h:305
Definition: CDenseVector.h:35
Type inner_distance(Iterator lhs, Iterator lhs_end, keyed_iterator< Type > rhs, Type init, BinaryFunction1 f1, BinaryFunction2 f2)
Definition: sparse_algorithm.h:96
Type operator()(const Type v1, const Type v2) const
Definition: sparse_algorithm.h:566
Type inner_product(keyed_iterator< Type > lhs, keyed_iterator< Type > lhs_end, keyed_iterator< Type > rhs, Type init, BinaryFunction1 f1, BinaryFunction2 f2)
Definition: sparse_algorithm.h:67
Type val() const
Definition: keyed_iterator.hpp:108
Type inner_product(Iterator lhs, Iterator lhs_end, keyed_iterator< Type > rhs, Type init, BinaryFunction1 f1, BinaryFunction2 f2)
Definition: sparse_algorithm.h:40
Definition: CException.h:40
void element_adapt(keyed_iterator< Type > l, keyed_iterator< Type > l_end, keyed_iterator< Type > r, keyed_iterator< Type > r_end, keyed_iterator< Type > out, BinaryFunction f, float fEps1, float fEps2)
Definition: sparse_algorithm.h:509