001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.linear; 018 019 import java.io.Serializable; 020 021 import org.apache.commons.math.MathRuntimeException; 022 import org.apache.commons.math.util.OpenIntToDoubleHashMap; 023 import org.apache.commons.math.util.OpenIntToDoubleHashMap.Iterator; 024 025 /** 026 * This class implements the {@link RealVector} interface with a {@link OpenIntToDoubleHashMap} backing store. 027 * @version $Revision: 800111 $ $Date: 2009-08-02 13:23:05 -0400 (Sun, 02 Aug 2009) $ 028 * @since 2.0 029 */ 030 public class OpenMapRealVector implements SparseRealVector, Serializable { 031 032 /** Serializable version identifier. */ 033 private static final long serialVersionUID = 8772222695580707260L; 034 035 /** Default Tolerance for having a value considered zero. */ 036 public static final double DEFAULT_ZERO_TOLERANCE = 1.0e-12; 037 038 /** Entries of the vector. */ 039 private final OpenIntToDoubleHashMap entries; 040 041 /** Dimension of the vector. */ 042 private final int virtualSize; 043 044 /** Tolerance for having a value considered zero. */ 045 private double epsilon; 046 047 /** 048 * Build a 0-length vector. 049 * <p>Zero-length vectors may be used to initialized construction of vectors 050 * by data gathering. We start with zero-length and use either the {@link 051 * #OpenMapRealVector(OpenMapRealVector, int)} constructor 052 * or one of the <code>append</code> method ({@link #append(double)}, {@link 053 * #append(double[])}, {@link #append(RealVector)}) to gather data 054 * into this vector.</p> 055 */ 056 public OpenMapRealVector() { 057 this(0, DEFAULT_ZERO_TOLERANCE); 058 } 059 060 /** 061 * Construct a (dimension)-length vector of zeros. 062 * @param dimension size of the vector 063 */ 064 public OpenMapRealVector(int dimension) { 065 this(dimension, DEFAULT_ZERO_TOLERANCE); 066 } 067 068 /** 069 * Construct a (dimension)-length vector of zeros, specifying zero tolerance. 070 * @param dimension Size of the vector 071 * @param epsilon The tolerance for having a value considered zero 072 */ 073 public OpenMapRealVector(int dimension, double epsilon) { 074 virtualSize = dimension; 075 entries = new OpenIntToDoubleHashMap(0.0); 076 this.epsilon = epsilon; 077 } 078 079 /** 080 * Build a resized vector, for use with append. 081 * @param v The original vector 082 * @param resize The amount to resize it 083 */ 084 protected OpenMapRealVector(OpenMapRealVector v, int resize) { 085 virtualSize = v.getDimension() + resize; 086 entries = new OpenIntToDoubleHashMap(v.entries); 087 epsilon = v.getEpsilon(); 088 } 089 090 /** 091 * Build a vector with known the sparseness (for advanced use only). 092 * @param dimension The size of the vector 093 * @param expectedSize The expected number of non-zero entries 094 */ 095 public OpenMapRealVector(int dimension, int expectedSize) { 096 this(dimension, expectedSize, DEFAULT_ZERO_TOLERANCE); 097 } 098 099 /** 100 * Build a vector with known the sparseness and zero tolerance setting (for advanced use only). 101 * @param dimension The size of the vector 102 * @param expectedSize The expected number of non-zero entries 103 * @param epsilon The tolerance for having a value considered zero 104 */ 105 public OpenMapRealVector(int dimension, int expectedSize, double epsilon) { 106 virtualSize = dimension; 107 entries = new OpenIntToDoubleHashMap(expectedSize, 0.0); 108 this.epsilon = epsilon; 109 } 110 111 /** 112 * Create from a double array. 113 * Only non-zero entries will be stored 114 * @param values The set of values to create from 115 */ 116 public OpenMapRealVector(double[] values) { 117 this(values, DEFAULT_ZERO_TOLERANCE); 118 } 119 120 /** 121 * Create from a double array, specifying zero tolerance. 122 * Only non-zero entries will be stored 123 * @param values The set of values to create from 124 * @param epsilon The tolerance for having a value considered zero 125 */ 126 public OpenMapRealVector(double[] values, double epsilon) { 127 virtualSize = values.length; 128 entries = new OpenIntToDoubleHashMap(0.0); 129 this.epsilon = epsilon; 130 for (int key = 0; key < values.length; key++) { 131 double value = values[key]; 132 if (!isZero(value)) { 133 entries.put(key, value); 134 } 135 } 136 } 137 138 /** 139 * Create from a Double array. 140 * Only non-zero entries will be stored 141 * @param values The set of values to create from 142 */ 143 public OpenMapRealVector(Double[] values) { 144 this(values, DEFAULT_ZERO_TOLERANCE); 145 } 146 147 /** 148 * Create from a Double array. 149 * Only non-zero entries will be stored 150 * @param values The set of values to create from 151 * @param epsilon The tolerance for having a value considered zero 152 */ 153 public OpenMapRealVector(Double[] values, double epsilon) { 154 virtualSize = values.length; 155 entries = new OpenIntToDoubleHashMap(0.0); 156 this.epsilon = epsilon; 157 for (int key = 0; key < values.length; key++) { 158 double value = values[key].doubleValue(); 159 if (!isZero(value)) { 160 entries.put(key, value); 161 } 162 } 163 } 164 165 /** 166 * Copy constructor. 167 * @param v The instance to copy from 168 */ 169 public OpenMapRealVector(OpenMapRealVector v) { 170 virtualSize = v.getDimension(); 171 entries = new OpenIntToDoubleHashMap(v.getEntries()); 172 epsilon = v.getEpsilon(); 173 } 174 175 /** 176 * Generic copy constructor. 177 * @param v The instance to copy from 178 */ 179 public OpenMapRealVector(RealVector v) { 180 virtualSize = v.getDimension(); 181 entries = new OpenIntToDoubleHashMap(0.0); 182 epsilon = DEFAULT_ZERO_TOLERANCE; 183 for (int key = 0; key < virtualSize; key++) { 184 double value = v.getEntry(key); 185 if (!isZero(value)) { 186 entries.put(key, value); 187 } 188 } 189 } 190 191 /** 192 * Get the entries of this instance. 193 * @return entries of this instance 194 */ 195 private OpenIntToDoubleHashMap getEntries() { 196 return entries; 197 } 198 199 /** 200 * Determine if this value is zero. 201 * @param value The value to test 202 * @return <code>true</code> if this value is zero, <code>false</code> otherwise 203 */ 204 protected boolean isZero(double value) { 205 return value > -epsilon && value < epsilon; 206 } 207 208 /** 209 * Get the tolerance for having a value considered zero. 210 * @return The test range for testing if a value is zero 211 */ 212 public double getEpsilon() { 213 return epsilon; 214 } 215 216 /** 217 * Set the tolerance for having a value considered zero. 218 * @param epsilon The test range for testing if a value is zero 219 */ 220 public void setEpsilon(double epsilon) { 221 this.epsilon = epsilon; 222 } 223 224 /** {@inheritDoc} */ 225 public OpenMapRealVector add(RealVector v) throws IllegalArgumentException { 226 checkVectorDimensions(v.getDimension()); 227 if (v instanceof OpenMapRealVector) { 228 return add((OpenMapRealVector) v); 229 } 230 return add(v.getData()); 231 } 232 233 /** 234 * Optimized method to add two OpenMapRealVectors. 235 * @param v Vector to add with 236 * @return The sum of <code>this</code> with <code>v</code> 237 * @throws IllegalArgumentException If the dimensions don't match 238 */ 239 public OpenMapRealVector add(OpenMapRealVector v) throws IllegalArgumentException{ 240 checkVectorDimensions(v.getDimension()); 241 OpenMapRealVector res = copy(); 242 Iterator iter = v.getEntries().iterator(); 243 while (iter.hasNext()) { 244 iter.advance(); 245 int key = iter.key(); 246 if (entries.containsKey(key)) { 247 res.setEntry(key, entries.get(key) + iter.value()); 248 } else { 249 res.setEntry(key, iter.value()); 250 } 251 } 252 return res; 253 } 254 255 /** {@inheritDoc} */ 256 public OpenMapRealVector add(double[] v) throws IllegalArgumentException { 257 checkVectorDimensions(v.length); 258 OpenMapRealVector res = new OpenMapRealVector(getDimension()); 259 for (int i = 0; i < v.length; i++) { 260 res.setEntry(i, v[i] + getEntry(i)); 261 } 262 return res; 263 } 264 265 /** 266 * Optimized method to append a OpenMapRealVector. 267 * @param v vector to append 268 * @return The result of appending <code>v</code> to self 269 */ 270 public OpenMapRealVector append(OpenMapRealVector v) { 271 OpenMapRealVector res = new OpenMapRealVector(this, v.getDimension()); 272 Iterator iter = v.entries.iterator(); 273 while (iter.hasNext()) { 274 iter.advance(); 275 res.setEntry(iter.key() + virtualSize, iter.value()); 276 } 277 return res; 278 } 279 280 /** {@inheritDoc} */ 281 public OpenMapRealVector append(RealVector v) { 282 if (v instanceof OpenMapRealVector) { 283 return append((OpenMapRealVector) v); 284 } 285 return append(v.getData()); 286 } 287 288 /** {@inheritDoc} */ 289 public OpenMapRealVector append(double d) { 290 OpenMapRealVector res = new OpenMapRealVector(this, 1); 291 res.setEntry(virtualSize, d); 292 return res; 293 } 294 295 /** {@inheritDoc} */ 296 public OpenMapRealVector append(double[] a) { 297 OpenMapRealVector res = new OpenMapRealVector(this, a.length); 298 for (int i = 0; i < a.length; i++) { 299 res.setEntry(i + virtualSize, a[i]); 300 } 301 return res; 302 } 303 304 /** {@inheritDoc} */ 305 public OpenMapRealVector copy() { 306 return new OpenMapRealVector(this); 307 } 308 309 /** {@inheritDoc} */ 310 public double dotProduct(RealVector v) throws IllegalArgumentException { 311 checkVectorDimensions(v.getDimension()); 312 double res = 0; 313 Iterator iter = entries.iterator(); 314 while (iter.hasNext()) { 315 iter.advance(); 316 res += v.getEntry(iter.key()) * iter.value(); 317 } 318 return res; 319 } 320 321 /** {@inheritDoc} */ 322 public double dotProduct(double[] v) throws IllegalArgumentException { 323 checkVectorDimensions(v.length); 324 double res = 0; 325 Iterator iter = entries.iterator(); 326 while (iter.hasNext()) { 327 int idx = iter.key(); 328 double value = 0; 329 if (idx < v.length) { 330 value = v[idx]; 331 } 332 res += value * iter.value(); 333 } 334 return res; 335 } 336 337 /** {@inheritDoc} */ 338 public OpenMapRealVector ebeDivide(RealVector v) throws IllegalArgumentException { 339 checkVectorDimensions(v.getDimension()); 340 OpenMapRealVector res = new OpenMapRealVector(this); 341 Iterator iter = res.entries.iterator(); 342 while (iter.hasNext()) { 343 iter.advance(); 344 res.setEntry(iter.key(), iter.value() / v.getEntry(iter.key())); 345 } 346 return res; 347 } 348 349 /** {@inheritDoc} */ 350 public OpenMapRealVector ebeDivide(double[] v) throws IllegalArgumentException { 351 checkVectorDimensions(v.length); 352 OpenMapRealVector res = new OpenMapRealVector(this); 353 Iterator iter = res.entries.iterator(); 354 while (iter.hasNext()) { 355 iter.advance(); 356 res.setEntry(iter.key(), iter.value() / v[iter.key()]); 357 } 358 return res; 359 } 360 361 /** {@inheritDoc} */ 362 public OpenMapRealVector ebeMultiply(RealVector v) throws IllegalArgumentException { 363 checkVectorDimensions(v.getDimension()); 364 OpenMapRealVector res = new OpenMapRealVector(this); 365 Iterator iter = res.entries.iterator(); 366 while (iter.hasNext()) { 367 iter.advance(); 368 res.setEntry(iter.key(), iter.value() * v.getEntry(iter.key())); 369 } 370 return res; 371 } 372 373 /** {@inheritDoc} */ 374 public OpenMapRealVector ebeMultiply(double[] v) throws IllegalArgumentException { 375 checkVectorDimensions(v.length); 376 OpenMapRealVector res = new OpenMapRealVector(this); 377 Iterator iter = res.entries.iterator(); 378 while (iter.hasNext()) { 379 iter.advance(); 380 res.setEntry(iter.key(), iter.value() * v[iter.key()]); 381 } 382 return res; 383 } 384 385 /** {@inheritDoc} */ 386 public OpenMapRealVector getSubVector(int index, int n) throws MatrixIndexException { 387 checkIndex(index); 388 checkIndex(index + n - 1); 389 OpenMapRealVector res = new OpenMapRealVector(n); 390 int end = index + n; 391 Iterator iter = entries.iterator(); 392 while (iter.hasNext()) { 393 iter.advance(); 394 int key = iter.key(); 395 if (key >= index && key < end) { 396 res.setEntry(key - index, iter.value()); 397 } 398 } 399 return res; 400 } 401 402 /** {@inheritDoc} */ 403 public double[] getData() { 404 double[] res = new double[virtualSize]; 405 Iterator iter = entries.iterator(); 406 while (iter.hasNext()) { 407 iter.advance(); 408 res[iter.key()] = iter.value(); 409 } 410 return res; 411 } 412 413 /** {@inheritDoc} */ 414 public int getDimension() { 415 return virtualSize; 416 } 417 418 /** 419 * Optimized method to compute distance. 420 * @param v The vector to compute distance to 421 * @return The distance from <code>this</code> and <code>v</code> 422 * @throws IllegalArgumentException If the dimensions don't match 423 */ 424 public double getDistance(OpenMapRealVector v) throws IllegalArgumentException { 425 Iterator iter = entries.iterator(); 426 double res = 0; 427 while (iter.hasNext()) { 428 iter.advance(); 429 int key = iter.key(); 430 double delta; 431 delta = iter.value() - v.getEntry(key); 432 res += delta * delta; 433 } 434 iter = v.getEntries().iterator(); 435 while (iter.hasNext()) { 436 iter.advance(); 437 int key = iter.key(); 438 if (!entries.containsKey(key)) { 439 final double value = iter.value(); 440 res += value * value; 441 } 442 } 443 return Math.sqrt(res); 444 } 445 446 /** {@inheritDoc} */ 447 public double getDistance(RealVector v) throws IllegalArgumentException { 448 checkVectorDimensions(v.getDimension()); 449 if (v instanceof OpenMapRealVector) { 450 return getDistance((OpenMapRealVector) v); 451 } 452 return getDistance(v.getData()); 453 } 454 455 /** {@inheritDoc} */ 456 public double getDistance(double[] v) throws IllegalArgumentException { 457 checkVectorDimensions(v.length); 458 double res = 0; 459 for (int i = 0; i < v.length; i++) { 460 double delta = entries.get(i) - v[i]; 461 res += delta * delta; 462 } 463 return Math.sqrt(res); 464 } 465 466 /** {@inheritDoc} */ 467 public double getEntry(int index) throws MatrixIndexException { 468 checkIndex(index); 469 return entries.get(index); 470 } 471 472 /** 473 * Distance between two vectors. 474 * <p>This method computes the distance consistent with 475 * L<sub>1</sub> norm, i.e. the sum of the absolute values of 476 * elements differences.</p> 477 * @param v vector to which distance is requested 478 * @return distance between two vectors. 479 */ 480 public double getL1Distance(OpenMapRealVector v) { 481 double max = 0; 482 Iterator iter = entries.iterator(); 483 while (iter.hasNext()) { 484 iter.advance(); 485 double delta = Math.abs(iter.value() - v.getEntry(iter.key())); 486 max += delta; 487 } 488 iter = v.getEntries().iterator(); 489 while (iter.hasNext()) { 490 iter.advance(); 491 int key = iter.key(); 492 if (!entries.containsKey(key)) { 493 double delta = Math.abs(iter.value()); 494 max += Math.abs(delta); 495 } 496 } 497 return max; 498 } 499 500 /** {@inheritDoc} */ 501 public double getL1Distance(RealVector v) throws IllegalArgumentException { 502 checkVectorDimensions(v.getDimension()); 503 if (v instanceof OpenMapRealVector) { 504 return getL1Distance((OpenMapRealVector) v); 505 } 506 return getL1Distance(v.getData()); 507 } 508 509 /** {@inheritDoc} */ 510 public double getL1Distance(double[] v) throws IllegalArgumentException { 511 checkVectorDimensions(v.length); 512 double max = 0; 513 for (int i = 0; i < v.length; i++) { 514 double delta = Math.abs(getEntry(i) - v[i]); 515 max += delta; 516 } 517 return max; 518 } 519 520 /** {@inheritDoc} */ 521 public double getL1Norm() { 522 double res = 0; 523 Iterator iter = entries.iterator(); 524 while (iter.hasNext()) { 525 iter.advance(); 526 res += Math.abs(iter.value()); 527 } 528 return res; 529 } 530 531 /** 532 * Optimized method to compute LInfDistance. 533 * @param v The vector to compute from 534 * @return the LInfDistance 535 */ 536 private double getLInfDistance(OpenMapRealVector v) { 537 double max = 0; 538 Iterator iter = entries.iterator(); 539 while (iter.hasNext()) { 540 iter.advance(); 541 double delta = Math.abs(iter.value() - v.getEntry(iter.key())); 542 if (delta > max) { 543 max = delta; 544 } 545 } 546 iter = v.getEntries().iterator(); 547 while (iter.hasNext()) { 548 iter.advance(); 549 int key = iter.key(); 550 if (!entries.containsKey(key)) { 551 if (iter.value() > max) { 552 max = iter.value(); 553 } 554 } 555 } 556 return max; 557 } 558 559 /** {@inheritDoc} */ 560 public double getLInfDistance(RealVector v) throws IllegalArgumentException { 561 checkVectorDimensions(v.getDimension()); 562 if (v instanceof OpenMapRealVector) { 563 return getLInfDistance((OpenMapRealVector) v); 564 } 565 return getLInfDistance(v.getData()); 566 } 567 568 /** {@inheritDoc} */ 569 public double getLInfDistance(double[] v) throws IllegalArgumentException { 570 checkVectorDimensions(v.length); 571 double max = 0; 572 for (int i = 0; i < v.length; i++) { 573 double delta = Math.abs(getEntry(i) - v[i]); 574 if (delta > max) { 575 max = delta; 576 } 577 } 578 return max; 579 } 580 581 /** {@inheritDoc} */ 582 public double getLInfNorm() { 583 double max = 0; 584 Iterator iter = entries.iterator(); 585 while (iter.hasNext()) { 586 iter.advance(); 587 max += iter.value(); 588 } 589 return max; 590 } 591 592 /** {@inheritDoc} */ 593 public double getNorm() { 594 double res = 0; 595 Iterator iter = entries.iterator(); 596 while (iter.hasNext()) { 597 iter.advance(); 598 res += iter.value() * iter.value(); 599 } 600 return Math.sqrt(res); 601 } 602 603 /** {@inheritDoc} */ 604 public boolean isInfinite() { 605 boolean infiniteFound = false; 606 Iterator iter = entries.iterator(); 607 while (iter.hasNext()) { 608 iter.advance(); 609 final double value = iter.value(); 610 if (Double.isNaN(value)) { 611 return false; 612 } 613 if (Double.isInfinite(value)) { 614 infiniteFound = true; 615 } 616 } 617 return infiniteFound; 618 } 619 620 /** {@inheritDoc} */ 621 public boolean isNaN() { 622 Iterator iter = entries.iterator(); 623 while (iter.hasNext()) { 624 iter.advance(); 625 if (Double.isNaN(iter.value())) { 626 return true; 627 } 628 } 629 return false; 630 } 631 632 /** {@inheritDoc} */ 633 public OpenMapRealVector mapAbs() { 634 return copy().mapAbsToSelf(); 635 } 636 637 /** {@inheritDoc} */ 638 public OpenMapRealVector mapAbsToSelf() { 639 Iterator iter = entries.iterator(); 640 while (iter.hasNext()) { 641 iter.advance(); 642 entries.put(iter.key(), Math.abs(iter.value())); 643 } 644 return this; 645 } 646 647 /** {@inheritDoc} */ 648 public OpenMapRealVector mapAcos() { 649 return copy().mapAcosToSelf(); 650 } 651 652 /** {@inheritDoc} */ 653 public OpenMapRealVector mapAcosToSelf() { 654 for (int i = 0; i < virtualSize; i++) { 655 setEntry(i, Math.acos(getEntry(i))); 656 } 657 return this; 658 } 659 660 /** {@inheritDoc} */ 661 public OpenMapRealVector mapAdd(double d) { 662 return copy().mapAddToSelf(d); 663 } 664 665 /** {@inheritDoc} */ 666 public OpenMapRealVector mapAddToSelf(double d) { 667 for (int i = 0; i < virtualSize; i++) { 668 setEntry(i, getEntry(i) + d); 669 } 670 return this; 671 } 672 673 /** {@inheritDoc} */ 674 public OpenMapRealVector mapAsin() { 675 return copy().mapAsinToSelf(); 676 } 677 678 /** {@inheritDoc} */ 679 public OpenMapRealVector mapAsinToSelf() { 680 Iterator iter = entries.iterator(); 681 while (iter.hasNext()) { 682 iter.advance(); 683 entries.put(iter.key(), Math.asin(iter.value())); 684 } 685 return this; 686 } 687 688 /** {@inheritDoc} */ 689 public OpenMapRealVector mapAtan() { 690 return copy().mapAtanToSelf(); 691 } 692 693 /** {@inheritDoc} */ 694 public OpenMapRealVector mapAtanToSelf() { 695 Iterator iter = entries.iterator(); 696 while (iter.hasNext()) { 697 iter.advance(); 698 entries.put(iter.key(), Math.atan(iter.value())); 699 } 700 return this; 701 } 702 703 /** {@inheritDoc} */ 704 public OpenMapRealVector mapCbrt() { 705 return copy().mapCbrtToSelf(); 706 } 707 708 /** {@inheritDoc} */ 709 public OpenMapRealVector mapCbrtToSelf() { 710 Iterator iter = entries.iterator(); 711 while (iter.hasNext()) { 712 iter.advance(); 713 entries.put(iter.key(), Math.cbrt(iter.value())); 714 } 715 return this; 716 } 717 718 /** {@inheritDoc} */ 719 public OpenMapRealVector mapCeil() { 720 return copy().mapCeilToSelf(); 721 } 722 723 /** {@inheritDoc} */ 724 public OpenMapRealVector mapCeilToSelf() { 725 Iterator iter = entries.iterator(); 726 while (iter.hasNext()) { 727 iter.advance(); 728 entries.put(iter.key(), Math.ceil(iter.value())); 729 } 730 return this; 731 } 732 733 /** {@inheritDoc} */ 734 public OpenMapRealVector mapCos() { 735 return copy().mapCosToSelf(); 736 } 737 738 /** {@inheritDoc} */ 739 public OpenMapRealVector mapCosToSelf() { 740 for (int i = 0; i < virtualSize; i++) { 741 setEntry(i, Math.cos(getEntry(i))); 742 } 743 return this; 744 } 745 746 /** {@inheritDoc} */ 747 public OpenMapRealVector mapCosh() { 748 return copy().mapCoshToSelf(); 749 } 750 751 /** {@inheritDoc} */ 752 public OpenMapRealVector mapCoshToSelf() { 753 for (int i = 0; i < virtualSize; i++) { 754 setEntry(i, Math.cosh(getEntry(i))); 755 } 756 return this; 757 } 758 759 /** {@inheritDoc} */ 760 public OpenMapRealVector mapDivide(double d) { 761 return copy().mapDivideToSelf(d); 762 } 763 764 /** {@inheritDoc} */ 765 public OpenMapRealVector mapDivideToSelf(double d) { 766 Iterator iter = entries.iterator(); 767 while (iter.hasNext()) { 768 iter.advance(); 769 entries.put(iter.key(), iter.value() / d); 770 } 771 return this; 772 } 773 774 /** {@inheritDoc} */ 775 public OpenMapRealVector mapExp() { 776 return copy().mapExpToSelf(); 777 } 778 779 /** {@inheritDoc} */ 780 public OpenMapRealVector mapExpToSelf() { 781 for (int i = 0; i < virtualSize; i++) { 782 entries.put(i, Math.exp(entries.get(i))); 783 } 784 return this; 785 } 786 787 /** {@inheritDoc} */ 788 public OpenMapRealVector mapExpm1() { 789 return copy().mapExpm1ToSelf(); 790 } 791 792 /** {@inheritDoc} */ 793 public OpenMapRealVector mapExpm1ToSelf() { 794 Iterator iter = entries.iterator(); 795 while (iter.hasNext()) { 796 iter.advance(); 797 entries.put(iter.key(), Math.expm1(iter.value())); 798 } 799 return this; 800 } 801 802 /** {@inheritDoc} */ 803 public OpenMapRealVector mapFloor() { 804 return copy().mapFloorToSelf(); 805 } 806 807 /** {@inheritDoc} */ 808 public OpenMapRealVector mapFloorToSelf() { 809 Iterator iter = entries.iterator(); 810 while (iter.hasNext()) { 811 iter.advance(); 812 entries.put(iter.key(), Math.floor(iter.value())); 813 } 814 return this; 815 } 816 817 /** {@inheritDoc} */ 818 public OpenMapRealVector mapInv() { 819 return copy().mapInvToSelf(); 820 } 821 822 /** {@inheritDoc} */ 823 public OpenMapRealVector mapInvToSelf() { 824 for (int i = 0; i < virtualSize; i++) { 825 setEntry(i, 1.0/getEntry(i)); 826 } 827 return this; 828 } 829 830 /** {@inheritDoc} */ 831 public OpenMapRealVector mapLog() { 832 return copy().mapLogToSelf(); 833 } 834 835 /** {@inheritDoc} */ 836 public OpenMapRealVector mapLog10() { 837 return copy().mapLog10ToSelf(); 838 } 839 840 /** {@inheritDoc} */ 841 public OpenMapRealVector mapLog10ToSelf() { 842 for (int i = 0; i < virtualSize; i++) { 843 setEntry(i, Math.log10(getEntry(i))); 844 } 845 return this; 846 } 847 848 /** {@inheritDoc} */ 849 public OpenMapRealVector mapLog1p() { 850 return copy().mapLog1pToSelf(); 851 } 852 853 /** {@inheritDoc} */ 854 public OpenMapRealVector mapLog1pToSelf() { 855 Iterator iter = entries.iterator(); 856 while (iter.hasNext()) { 857 iter.advance(); 858 entries.put(iter.key(), Math.log1p(iter.value())); 859 } 860 return this; 861 } 862 863 /** {@inheritDoc} */ 864 public OpenMapRealVector mapLogToSelf() { 865 for (int i = 0; i < virtualSize; i++) { 866 setEntry(i, Math.log(getEntry(i))); 867 } 868 return this; 869 } 870 871 /** {@inheritDoc} */ 872 public OpenMapRealVector mapMultiply(double d) { 873 return copy().mapMultiplyToSelf(d); 874 } 875 876 /** {@inheritDoc} */ 877 public OpenMapRealVector mapMultiplyToSelf(double d) { 878 Iterator iter = entries.iterator(); 879 while (iter.hasNext()) { 880 iter.advance(); 881 entries.put(iter.key(), iter.value() * d); 882 } 883 return this; 884 } 885 /** {@inheritDoc} */ 886 public OpenMapRealVector mapPow(double d) { 887 return copy().mapPowToSelf(d); 888 } 889 890 /** {@inheritDoc} */ 891 public OpenMapRealVector mapPowToSelf(double d) { 892 Iterator iter = entries.iterator(); 893 while (iter.hasNext()) { 894 iter.advance(); 895 entries.put(iter.key(), Math.pow(iter.value(), d)); 896 } 897 return this; 898 } 899 900 /** {@inheritDoc} */ 901 public OpenMapRealVector mapRint() { 902 return copy().mapRintToSelf(); 903 } 904 905 /** {@inheritDoc} */ 906 public OpenMapRealVector mapRintToSelf() { 907 Iterator iter = entries.iterator(); 908 while (iter.hasNext()) { 909 iter.advance(); 910 entries.put(iter.key(), Math.rint(iter.value())); 911 } 912 return this; 913 } 914 915 /** {@inheritDoc} */ 916 public OpenMapRealVector mapSignum() { 917 return copy().mapSignumToSelf(); 918 } 919 920 /** {@inheritDoc} */ 921 public OpenMapRealVector mapSignumToSelf() { 922 Iterator iter = entries.iterator(); 923 while (iter.hasNext()) { 924 iter.advance(); 925 entries.put(iter.key(), Math.signum(iter.value())); 926 } 927 return this; 928 } 929 930 /** {@inheritDoc} */ 931 public OpenMapRealVector mapSin() { 932 return copy().mapSinToSelf(); 933 } 934 935 /** {@inheritDoc} */ 936 public OpenMapRealVector mapSinToSelf() { 937 Iterator iter = entries.iterator(); 938 while (iter.hasNext()) { 939 iter.advance(); 940 entries.put(iter.key(), Math.sin(iter.value())); 941 } 942 return this; 943 } 944 945 /** {@inheritDoc} */ 946 public OpenMapRealVector mapSinh() { 947 return copy().mapSinhToSelf(); 948 } 949 950 /** {@inheritDoc} */ 951 public OpenMapRealVector mapSinhToSelf() { 952 953 Iterator iter = entries.iterator(); 954 while (iter.hasNext()) { 955 iter.advance(); 956 entries.put(iter.key(), Math.sinh(iter.value())); 957 } 958 return this; 959 } 960 961 /** {@inheritDoc} */ 962 public OpenMapRealVector mapSqrt() { 963 return copy().mapSqrtToSelf(); 964 } 965 966 /** {@inheritDoc} */ 967 public OpenMapRealVector mapSqrtToSelf() { 968 Iterator iter = entries.iterator(); 969 while (iter.hasNext()) { 970 iter.advance(); 971 entries.put(iter.key(), Math.sqrt(iter.value())); 972 } 973 return this; 974 } 975 976 /** {@inheritDoc} */ 977 public OpenMapRealVector mapSubtract(double d) { 978 return copy().mapSubtractToSelf(d); 979 } 980 981 /** {@inheritDoc} */ 982 public OpenMapRealVector mapSubtractToSelf(double d) { 983 return mapAddToSelf(-d); 984 } 985 986 /** {@inheritDoc} */ 987 public OpenMapRealVector mapTan() { 988 return copy().mapTanToSelf(); 989 } 990 991 /** {@inheritDoc} */ 992 public OpenMapRealVector mapTanToSelf() { 993 Iterator iter = entries.iterator(); 994 while (iter.hasNext()) { 995 iter.advance(); 996 entries.put(iter.key(), Math.tan(iter.value())); 997 } 998 return this; 999 } 1000 1001 /** {@inheritDoc} */ 1002 public OpenMapRealVector mapTanh() { 1003 return copy().mapTanhToSelf(); 1004 } 1005 1006 /** {@inheritDoc} */ 1007 public OpenMapRealVector mapTanhToSelf() { 1008 Iterator iter = entries.iterator(); 1009 while (iter.hasNext()) { 1010 iter.advance(); 1011 entries.put(iter.key(), Math.tanh(iter.value())); 1012 } 1013 return this; 1014 } 1015 1016 /** {@inheritDoc} */ 1017 public OpenMapRealVector mapUlp() { 1018 return copy().mapUlpToSelf(); 1019 } 1020 1021 /** {@inheritDoc} */ 1022 public OpenMapRealVector mapUlpToSelf() { 1023 Iterator iter = entries.iterator(); 1024 while (iter.hasNext()) { 1025 iter.advance(); 1026 entries.put(iter.key(), Math.ulp(iter.value())); 1027 } 1028 return this; 1029 } 1030 1031 /** 1032 * Optimized method to compute the outer product. 1033 * @param v The vector to comput the outer product on 1034 * @return The outer product of <code>this</code> and <code>v</code> 1035 * @throws IllegalArgumentException If the dimensions don't match 1036 */ 1037 public OpenMapRealMatrix outerproduct(OpenMapRealVector v) throws IllegalArgumentException{ 1038 checkVectorDimensions(v.getDimension()); 1039 OpenMapRealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize); 1040 Iterator iter = entries.iterator(); 1041 while (iter.hasNext()) { 1042 iter.advance(); 1043 Iterator iter2 = v.getEntries().iterator(); 1044 while (iter2.hasNext()) { 1045 iter2.advance(); 1046 res.setEntry(iter.key(), iter2.key(), iter.value()*iter2.value()); 1047 } 1048 } 1049 return res; 1050 } 1051 1052 /** {@inheritDoc} */ 1053 public RealMatrix outerProduct(RealVector v) 1054 throws IllegalArgumentException { 1055 checkVectorDimensions(v.getDimension()); 1056 if (v instanceof OpenMapRealVector) { 1057 return outerproduct((OpenMapRealVector)v); 1058 } 1059 RealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize); 1060 Iterator iter = entries.iterator(); 1061 while (iter.hasNext()) { 1062 iter.advance(); 1063 int row = iter.key(); 1064 for (int col = 0; col < virtualSize; col++) { 1065 res.setEntry(row, col, iter.value()*v.getEntry(col)); 1066 } 1067 } 1068 return res; 1069 } 1070 1071 /** {@inheritDoc} */ 1072 public RealMatrix outerProduct(double[] v) throws IllegalArgumentException { 1073 checkVectorDimensions(v.length); 1074 RealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize); 1075 Iterator iter = entries.iterator(); 1076 while (iter.hasNext()) { 1077 iter.advance(); 1078 int row = iter.key(); 1079 double value = iter.value(); 1080 for (int col = 0; col < virtualSize; col++) { 1081 res.setEntry(row, col, value * v[col]); 1082 } 1083 } 1084 return res; 1085 } 1086 1087 /** {@inheritDoc} */ 1088 public RealVector projection(RealVector v) throws IllegalArgumentException { 1089 checkVectorDimensions(v.getDimension()); 1090 return v.mapMultiply(dotProduct(v) / v.dotProduct(v)); 1091 } 1092 1093 /** {@inheritDoc} */ 1094 public OpenMapRealVector projection(double[] v) throws IllegalArgumentException { 1095 checkVectorDimensions(v.length); 1096 return (OpenMapRealVector) projection(new OpenMapRealVector(v)); 1097 } 1098 1099 /** {@inheritDoc} */ 1100 public void setEntry(int index, double value) throws MatrixIndexException { 1101 checkIndex(index); 1102 if (!isZero(value)) { 1103 entries.put(index, value); 1104 } else if (entries.containsKey(index)) { 1105 entries.remove(index); 1106 } 1107 } 1108 1109 /** {@inheritDoc} */ 1110 public void setSubVector(int index, RealVector v) throws MatrixIndexException { 1111 checkIndex(index); 1112 checkIndex(index + v.getDimension() - 1); 1113 setSubVector(index, v.getData()); 1114 } 1115 1116 /** {@inheritDoc} */ 1117 public void setSubVector(int index, double[] v) throws MatrixIndexException { 1118 checkIndex(index); 1119 checkIndex(index + v.length - 1); 1120 for (int i = 0; i < v.length; i++) { 1121 setEntry(i + index, v[i]); 1122 } 1123 } 1124 1125 /** {@inheritDoc} */ 1126 public void set(double value) { 1127 for (int i = 0; i < virtualSize; i++) { 1128 setEntry(i, value); 1129 } 1130 } 1131 1132 /** 1133 * Optimized method to subtract OpenMapRealVectors. 1134 * @param v The vector to subtract from <code>this</code> 1135 * @return The difference of <code>this</code> and <code>v</code> 1136 * @throws IllegalArgumentException If the dimensions don't match 1137 */ 1138 public OpenMapRealVector subtract(OpenMapRealVector v) throws IllegalArgumentException{ 1139 checkVectorDimensions(v.getDimension()); 1140 OpenMapRealVector res = copy(); 1141 Iterator iter = v.getEntries().iterator(); 1142 while (iter.hasNext()) { 1143 iter.advance(); 1144 int key = iter.key(); 1145 if (entries.containsKey(key)) { 1146 res.setEntry(key, entries.get(key) - iter.value()); 1147 } else { 1148 res.setEntry(key, -iter.value()); 1149 } 1150 } 1151 return res; 1152 } 1153 1154 /** {@inheritDoc} */ 1155 public OpenMapRealVector subtract(RealVector v) throws IllegalArgumentException { 1156 checkVectorDimensions(v.getDimension()); 1157 if (v instanceof OpenMapRealVector) { 1158 return subtract((OpenMapRealVector) v); 1159 } 1160 return subtract(v.getData()); 1161 } 1162 1163 /** {@inheritDoc} */ 1164 public OpenMapRealVector subtract(double[] v) throws IllegalArgumentException { 1165 checkVectorDimensions(v.length); 1166 OpenMapRealVector res = new OpenMapRealVector(this); 1167 for (int i = 0; i < v.length; i++) { 1168 if (entries.containsKey(i)) { 1169 res.setEntry(i, entries.get(i) - v[i]); 1170 } else { 1171 res.setEntry(i, -v[i]); 1172 } 1173 } 1174 return res; 1175 } 1176 1177 1178 /** {@inheritDoc} */ 1179 public OpenMapRealVector unitVector() { 1180 OpenMapRealVector res = copy(); 1181 res.unitize(); 1182 return res; 1183 } 1184 1185 /** {@inheritDoc} */ 1186 public void unitize() { 1187 double norm = getNorm(); 1188 if (isZero(norm)) { 1189 throw MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector"); 1190 } 1191 Iterator iter = entries.iterator(); 1192 while (iter.hasNext()) { 1193 iter.advance(); 1194 entries.put(iter.key(), iter.value() / norm); 1195 } 1196 1197 } 1198 1199 /** 1200 * Check if an index is valid. 1201 * 1202 * @param index 1203 * index to check 1204 * @exception MatrixIndexException 1205 * if index is not valid 1206 */ 1207 private void checkIndex(final int index) throws MatrixIndexException { 1208 if (index < 0 || index >= getDimension()) { 1209 throw new MatrixIndexException( 1210 "index {0} out of allowed range [{1}, {2}]", 1211 index, 0, getDimension() - 1); 1212 } 1213 } 1214 1215 /** 1216 * Check if instance dimension is equal to some expected value. 1217 * 1218 * @param n 1219 * expected dimension. 1220 * @exception IllegalArgumentException 1221 * if the dimension is inconsistent with vector size 1222 */ 1223 protected void checkVectorDimensions(int n) throws IllegalArgumentException { 1224 if (getDimension() != n) { 1225 throw MathRuntimeException.createIllegalArgumentException( 1226 "vector length mismatch: got {0} but expected {1}", 1227 getDimension(), n); 1228 } 1229 } 1230 1231 /** {@inheritDoc} */ 1232 public double[] toArray() { 1233 return getData(); 1234 } 1235 1236 /** {@inheritDoc} 1237 * <p> Implementation Note: This works on exact values, and as a result 1238 * it is possible for {@code a.subtract(b)} to be the zero vector, while 1239 * {@code a.hashCode() != b.hashCode()}.</p> 1240 */ 1241 @Override 1242 public int hashCode() { 1243 final int prime = 31; 1244 int result = 1; 1245 long temp; 1246 temp = Double.doubleToLongBits(epsilon); 1247 result = prime * result + (int) (temp ^ (temp >>> 32)); 1248 result = prime * result + virtualSize; 1249 Iterator iter = entries.iterator(); 1250 while (iter.hasNext()) { 1251 iter.advance(); 1252 temp = Double.doubleToLongBits(iter.value()); 1253 result = prime * result + (int) (temp ^ (temp >>32)); 1254 } 1255 return result; 1256 } 1257 1258 /** 1259 * <p> Implementation Note: This performs an exact comparison, and as a result 1260 * it is possible for {@code a.subtract(b}} to be the zero vector, while 1261 * {@code a.equals(b) == false}.</p> 1262 * {@inheritDoc} 1263 */ 1264 @Override 1265 public boolean equals(Object obj) { 1266 if (this == obj) { 1267 return true; 1268 } 1269 if (obj == null) { 1270 return false; 1271 } 1272 if (!(obj instanceof OpenMapRealVector)) { 1273 return false; 1274 } 1275 OpenMapRealVector other = (OpenMapRealVector) obj; 1276 if (virtualSize != other.virtualSize) { 1277 return false; 1278 } 1279 if (Double.doubleToLongBits(epsilon) != 1280 Double.doubleToLongBits(other.epsilon)) { 1281 return false; 1282 } 1283 Iterator iter = entries.iterator(); 1284 while (iter.hasNext()) { 1285 iter.advance(); 1286 double test = other.getEntry(iter.key()); 1287 if (Double.doubleToLongBits(test) != Double.doubleToLongBits(iter.value())) { 1288 return false; 1289 } 1290 } 1291 iter = other.getEntries().iterator(); 1292 while (iter.hasNext()) { 1293 iter.advance(); 1294 double test = iter.value(); 1295 if (Double.doubleToLongBits(test) != Double.doubleToLongBits(getEntry(iter.key()))) { 1296 return false; 1297 } 1298 } 1299 return true; 1300 } 1301 1302 /** 1303 * 1304 * @return the percentage of none zero elements as a decimal percent. 1305 */ 1306 public double getSparcity() { 1307 return (double)entries.size()/(double)getDimension(); 1308 } 1309 1310 }