1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.linear;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
22 import org.apache.commons.math4.legacy.exception.MathArithmeticException;
23 import org.apache.commons.math4.legacy.exception.NotPositiveException;
24 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
25 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
26 import org.apache.commons.math4.core.jdkmath.JdkMath;
27 import org.apache.commons.math4.legacy.linear.OpenIntToDoubleHashMap.Iterator;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public class OpenMapRealVector extends SparseRealVector
43 implements Serializable {
44
45 public static final double DEFAULT_ZERO_TOLERANCE = 1.0e-12;
46
47 private static final long serialVersionUID = 8772222695580707260L;
48
49 private final OpenIntToDoubleHashMap entries;
50
51 private final int virtualSize;
52
53 private final double epsilon;
54
55
56
57
58
59
60
61
62
63 public OpenMapRealVector() {
64 this(0, DEFAULT_ZERO_TOLERANCE);
65 }
66
67
68
69
70
71
72 public OpenMapRealVector(int dimension) {
73 this(dimension, DEFAULT_ZERO_TOLERANCE);
74 }
75
76
77
78
79
80
81
82 public OpenMapRealVector(int dimension, double epsilon) {
83 virtualSize = dimension;
84 entries = new OpenIntToDoubleHashMap(0.0);
85 this.epsilon = epsilon;
86 }
87
88
89
90
91
92
93
94 protected OpenMapRealVector(OpenMapRealVector v, int resize) {
95 virtualSize = v.getDimension() + resize;
96 entries = new OpenIntToDoubleHashMap(v.entries);
97 epsilon = v.epsilon;
98 }
99
100
101
102
103
104
105
106 public OpenMapRealVector(int dimension, int expectedSize) {
107 this(dimension, expectedSize, DEFAULT_ZERO_TOLERANCE);
108 }
109
110
111
112
113
114
115
116
117
118 public OpenMapRealVector(int dimension, int expectedSize, double epsilon) {
119 virtualSize = dimension;
120 entries = new OpenIntToDoubleHashMap(expectedSize, 0.0);
121 this.epsilon = epsilon;
122 }
123
124
125
126
127
128
129
130 public OpenMapRealVector(double[] values) {
131 this(values, DEFAULT_ZERO_TOLERANCE);
132 }
133
134
135
136
137
138
139
140
141 public OpenMapRealVector(double[] values, double epsilon) {
142 virtualSize = values.length;
143 entries = new OpenIntToDoubleHashMap(0.0);
144 this.epsilon = epsilon;
145 for (int key = 0; key < values.length; key++) {
146 double value = values[key];
147 if (!isDefaultValue(value)) {
148 entries.put(key, value);
149 }
150 }
151 }
152
153
154
155
156
157
158
159 public OpenMapRealVector(Double[] values) {
160 this(values, DEFAULT_ZERO_TOLERANCE);
161 }
162
163
164
165
166
167
168
169
170 public OpenMapRealVector(Double[] values, double epsilon) {
171 virtualSize = values.length;
172 entries = new OpenIntToDoubleHashMap(0.0);
173 this.epsilon = epsilon;
174 for (int key = 0; key < values.length; key++) {
175 double value = values[key].doubleValue();
176 if (!isDefaultValue(value)) {
177 entries.put(key, value);
178 }
179 }
180 }
181
182
183
184
185
186
187 public OpenMapRealVector(OpenMapRealVector v) {
188 virtualSize = v.getDimension();
189 entries = new OpenIntToDoubleHashMap(v.getEntries());
190 epsilon = v.epsilon;
191 }
192
193
194
195
196
197
198 public OpenMapRealVector(RealVector v) {
199 virtualSize = v.getDimension();
200 entries = new OpenIntToDoubleHashMap(0.0);
201 epsilon = DEFAULT_ZERO_TOLERANCE;
202 for (int key = 0; key < virtualSize; key++) {
203 double value = v.getEntry(key);
204 if (!isDefaultValue(value)) {
205 entries.put(key, value);
206 }
207 }
208 }
209
210
211
212
213
214
215 private OpenIntToDoubleHashMap getEntries() {
216 return entries;
217 }
218
219
220
221
222
223
224
225
226
227 protected boolean isDefaultValue(double value) {
228 return JdkMath.abs(value) < epsilon;
229 }
230
231
232 @Override
233 public RealVector add(RealVector v)
234 throws DimensionMismatchException {
235 checkVectorDimensions(v.getDimension());
236 if (v instanceof OpenMapRealVector) {
237 return add((OpenMapRealVector) v);
238 } else {
239 return super.add(v);
240 }
241 }
242
243
244
245
246
247
248
249
250
251 public OpenMapRealVector add(OpenMapRealVector v)
252 throws DimensionMismatchException {
253 checkVectorDimensions(v.getDimension());
254 boolean copyThis = entries.size() > v.entries.size();
255 OpenMapRealVector res = copyThis ? this.copy() : v.copy();
256 Iterator iter = copyThis ? v.entries.iterator() : entries.iterator();
257 OpenIntToDoubleHashMap randomAccess = copyThis ? entries : v.entries;
258 while (iter.hasNext()) {
259 iter.advance();
260 int key = iter.key();
261 if (randomAccess.containsKey(key)) {
262 res.setEntry(key, randomAccess.get(key) + iter.value());
263 } else {
264 res.setEntry(key, iter.value());
265 }
266 }
267 return res;
268 }
269
270
271
272
273
274
275 public OpenMapRealVector append(OpenMapRealVector v) {
276 OpenMapRealVector res = new OpenMapRealVector(this, v.getDimension());
277 Iterator iter = v.entries.iterator();
278 while (iter.hasNext()) {
279 iter.advance();
280 res.setEntry(iter.key() + virtualSize, iter.value());
281 }
282 return res;
283 }
284
285
286 @Override
287 public OpenMapRealVector append(RealVector v) {
288 if (v instanceof OpenMapRealVector) {
289 return append((OpenMapRealVector) v);
290 } else {
291 final OpenMapRealVector res = new OpenMapRealVector(this, v.getDimension());
292 for (int i = 0; i < v.getDimension(); i++) {
293 res.setEntry(i + virtualSize, v.getEntry(i));
294 }
295 return res;
296 }
297 }
298
299
300 @Override
301 public OpenMapRealVector append(double d) {
302 OpenMapRealVector res = new OpenMapRealVector(this, 1);
303 res.setEntry(virtualSize, d);
304 return res;
305 }
306
307
308
309
310
311 @Override
312 public OpenMapRealVector copy() {
313 return new OpenMapRealVector(this);
314 }
315
316
317 @Override
318 public OpenMapRealVector ebeDivide(RealVector v)
319 throws DimensionMismatchException {
320 checkVectorDimensions(v.getDimension());
321 OpenMapRealVector res = new OpenMapRealVector(this);
322
323
324
325
326
327 final int n = getDimension();
328 for (int i = 0; i < n; i++) {
329 res.setEntry(i, this.getEntry(i) / v.getEntry(i));
330 }
331 return res;
332 }
333
334
335 @Override
336 public OpenMapRealVector ebeMultiply(RealVector v)
337 throws DimensionMismatchException {
338 checkVectorDimensions(v.getDimension());
339 OpenMapRealVector res = new OpenMapRealVector(this);
340 Iterator iter = entries.iterator();
341 while (iter.hasNext()) {
342 iter.advance();
343 res.setEntry(iter.key(), iter.value() * v.getEntry(iter.key()));
344 }
345 return res;
346 }
347
348
349 @Override
350 public OpenMapRealVector getSubVector(int index, int n)
351 throws NotPositiveException, OutOfRangeException {
352 checkIndex(index);
353 if (n < 0) {
354 throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
355 }
356 checkIndex(index + n - 1);
357 OpenMapRealVector res = new OpenMapRealVector(n);
358 int end = index + n;
359 Iterator iter = entries.iterator();
360 while (iter.hasNext()) {
361 iter.advance();
362 int key = iter.key();
363 if (key >= index && key < end) {
364 res.setEntry(key - index, iter.value());
365 }
366 }
367 return res;
368 }
369
370
371 @Override
372 public int getDimension() {
373 return virtualSize;
374 }
375
376
377
378
379
380
381
382
383 public double getDistance(OpenMapRealVector v)
384 throws DimensionMismatchException {
385 checkVectorDimensions(v.getDimension());
386 Iterator iter = entries.iterator();
387 double res = 0;
388 while (iter.hasNext()) {
389 iter.advance();
390 int key = iter.key();
391 double delta;
392 delta = iter.value() - v.getEntry(key);
393 res += delta * delta;
394 }
395 iter = v.getEntries().iterator();
396 while (iter.hasNext()) {
397 iter.advance();
398 int key = iter.key();
399 if (!entries.containsKey(key)) {
400 final double value = iter.value();
401 res += value * value;
402 }
403 }
404 return JdkMath.sqrt(res);
405 }
406
407
408 @Override
409 public double getDistance(RealVector v) throws DimensionMismatchException {
410 checkVectorDimensions(v.getDimension());
411 if (v instanceof OpenMapRealVector) {
412 return getDistance((OpenMapRealVector) v);
413 } else {
414 return super.getDistance(v);
415 }
416 }
417
418
419 @Override
420 public double getEntry(int index) throws OutOfRangeException {
421 checkIndex(index);
422 return entries.get(index);
423 }
424
425
426
427
428
429
430
431
432
433
434
435 public double getL1Distance(OpenMapRealVector v)
436 throws DimensionMismatchException {
437 checkVectorDimensions(v.getDimension());
438 double max = 0;
439 Iterator iter = entries.iterator();
440 while (iter.hasNext()) {
441 iter.advance();
442 double delta = JdkMath.abs(iter.value() - v.getEntry(iter.key()));
443 max += delta;
444 }
445 iter = v.getEntries().iterator();
446 while (iter.hasNext()) {
447 iter.advance();
448 int key = iter.key();
449 if (!entries.containsKey(key)) {
450 double delta = JdkMath.abs(iter.value());
451 max += JdkMath.abs(delta);
452 }
453 }
454 return max;
455 }
456
457
458 @Override
459 public double getL1Distance(RealVector v)
460 throws DimensionMismatchException {
461 checkVectorDimensions(v.getDimension());
462 if (v instanceof OpenMapRealVector) {
463 return getL1Distance((OpenMapRealVector) v);
464 } else {
465 return super.getL1Distance(v);
466 }
467 }
468
469
470
471
472
473
474
475
476 private double getLInfDistance(OpenMapRealVector v)
477 throws DimensionMismatchException {
478 checkVectorDimensions(v.getDimension());
479 double max = 0;
480 Iterator iter = entries.iterator();
481 while (iter.hasNext()) {
482 iter.advance();
483 double delta = JdkMath.abs(iter.value() - v.getEntry(iter.key()));
484 if (delta > max) {
485 max = delta;
486 }
487 }
488 iter = v.getEntries().iterator();
489 while (iter.hasNext()) {
490 iter.advance();
491 int key = iter.key();
492 if (!entries.containsKey(key) && iter.value() > max) {
493 max = iter.value();
494 }
495 }
496 return max;
497 }
498
499
500 @Override
501 public double getLInfDistance(RealVector v)
502 throws DimensionMismatchException {
503 checkVectorDimensions(v.getDimension());
504 if (v instanceof OpenMapRealVector) {
505 return getLInfDistance((OpenMapRealVector) v);
506 } else {
507 return super.getLInfDistance(v);
508 }
509 }
510
511
512 @Override
513 public boolean isInfinite() {
514 boolean infiniteFound = false;
515 Iterator iter = entries.iterator();
516 while (iter.hasNext()) {
517 iter.advance();
518 final double value = iter.value();
519 if (Double.isNaN(value)) {
520 return false;
521 }
522 if (Double.isInfinite(value)) {
523 infiniteFound = true;
524 }
525 }
526 return infiniteFound;
527 }
528
529
530 @Override
531 public boolean isNaN() {
532 Iterator iter = entries.iterator();
533 while (iter.hasNext()) {
534 iter.advance();
535 if (Double.isNaN(iter.value())) {
536 return true;
537 }
538 }
539 return false;
540 }
541
542
543 @Override
544 public OpenMapRealVector mapAdd(double d) {
545 return copy().mapAddToSelf(d);
546 }
547
548
549 @Override
550 public OpenMapRealVector mapAddToSelf(double d) {
551 for (int i = 0; i < virtualSize; i++) {
552 setEntry(i, getEntry(i) + d);
553 }
554 return this;
555 }
556
557
558 @Override
559 public void setEntry(int index, double value)
560 throws OutOfRangeException {
561 checkIndex(index);
562 if (!isDefaultValue(value)) {
563 entries.put(index, value);
564 } else if (entries.containsKey(index)) {
565 entries.remove(index);
566 }
567 }
568
569
570 @Override
571 public void setSubVector(int index, RealVector v)
572 throws OutOfRangeException {
573 checkIndex(index);
574 checkIndex(index + v.getDimension() - 1);
575 for (int i = 0; i < v.getDimension(); i++) {
576 setEntry(i + index, v.getEntry(i));
577 }
578 }
579
580
581 @Override
582 public void set(double value) {
583 for (int i = 0; i < virtualSize; i++) {
584 setEntry(i, value);
585 }
586 }
587
588
589
590
591
592
593
594
595 public OpenMapRealVector subtract(OpenMapRealVector v)
596 throws DimensionMismatchException {
597 checkVectorDimensions(v.getDimension());
598 OpenMapRealVector res = copy();
599 Iterator iter = v.getEntries().iterator();
600 while (iter.hasNext()) {
601 iter.advance();
602 int key = iter.key();
603 if (entries.containsKey(key)) {
604 res.setEntry(key, entries.get(key) - iter.value());
605 } else {
606 res.setEntry(key, -iter.value());
607 }
608 }
609 return res;
610 }
611
612
613 @Override
614 public RealVector subtract(RealVector v)
615 throws DimensionMismatchException {
616 checkVectorDimensions(v.getDimension());
617 if (v instanceof OpenMapRealVector) {
618 return subtract((OpenMapRealVector) v);
619 } else {
620 return super.subtract(v);
621 }
622 }
623
624
625 @Override
626 public OpenMapRealVector unitVector() throws MathArithmeticException {
627 OpenMapRealVector res = copy();
628 res.unitize();
629 return res;
630 }
631
632
633 @Override
634 public void unitize() throws MathArithmeticException {
635 double norm = getNorm();
636 if (isDefaultValue(norm)) {
637 throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
638 }
639 Iterator iter = entries.iterator();
640 while (iter.hasNext()) {
641 iter.advance();
642 entries.put(iter.key(), iter.value() / norm);
643 }
644 }
645
646
647 @Override
648 public double[] toArray() {
649 double[] res = new double[virtualSize];
650 Iterator iter = entries.iterator();
651 while (iter.hasNext()) {
652 iter.advance();
653 res[iter.key()] = iter.value();
654 }
655 return res;
656 }
657
658
659
660
661
662
663
664 @Override
665 public int hashCode() {
666 final int prime = 31;
667 int result = 1;
668 long temp;
669 temp = Double.doubleToLongBits(epsilon);
670 result = prime * result + (int) (temp ^ (temp >>> 32));
671 result = prime * result + virtualSize;
672 Iterator iter = entries.iterator();
673 while (iter.hasNext()) {
674 iter.advance();
675 temp = Double.doubleToLongBits(iter.value());
676 result = prime * result + (int) (temp ^ (temp >>32));
677 }
678 return result;
679 }
680
681
682
683
684
685
686
687 @Override
688 public boolean equals(Object obj) {
689 if (this == obj) {
690 return true;
691 }
692 if (!(obj instanceof OpenMapRealVector)) {
693 return false;
694 }
695 OpenMapRealVector other = (OpenMapRealVector) obj;
696 if (virtualSize != other.virtualSize) {
697 return false;
698 }
699 if (Double.doubleToLongBits(epsilon) !=
700 Double.doubleToLongBits(other.epsilon)) {
701 return false;
702 }
703 Iterator iter = entries.iterator();
704 while (iter.hasNext()) {
705 iter.advance();
706 double test = other.getEntry(iter.key());
707 if (Double.doubleToLongBits(test) != Double.doubleToLongBits(iter.value())) {
708 return false;
709 }
710 }
711 iter = other.getEntries().iterator();
712 while (iter.hasNext()) {
713 iter.advance();
714 double test = iter.value();
715 if (Double.doubleToLongBits(test) != Double.doubleToLongBits(getEntry(iter.key()))) {
716 return false;
717 }
718 }
719 return true;
720 }
721
722
723
724
725
726
727 public double getSparsity() {
728 return (double)entries.size()/(double)getDimension();
729 }
730
731
732 @Override
733 public java.util.Iterator<Entry> sparseIterator() {
734 return new OpenMapSparseIterator();
735 }
736
737
738
739
740
741
742 protected class OpenMapEntry extends Entry {
743
744 private final Iterator iter;
745
746
747
748
749
750
751 protected OpenMapEntry(Iterator iter) {
752 this.iter = iter;
753 }
754
755
756 @Override
757 public double getValue() {
758 return iter.value();
759 }
760
761
762 @Override
763 public void setValue(double value) {
764 entries.put(iter.key(), value);
765 }
766
767
768 @Override
769 public int getIndex() {
770 return iter.key();
771 }
772 }
773
774
775
776
777
778
779 protected class OpenMapSparseIterator implements java.util.Iterator<Entry> {
780
781 private final Iterator iter;
782
783 private final Entry current;
784
785
786 protected OpenMapSparseIterator() {
787 iter = entries.iterator();
788 current = new OpenMapEntry(iter);
789 }
790
791
792 @Override
793 public boolean hasNext() {
794 return iter.hasNext();
795 }
796
797
798 @Override
799 public Entry next() {
800 iter.advance();
801 return current;
802 }
803
804
805 @Override
806 public void remove() {
807 throw new UnsupportedOperationException("Not supported");
808 }
809 }
810 }