public LUDecomposition(Matrix A, boolean autoPivot) {
    LU = A.copy();
    int m = LU.m, n = LU.n;

    pivsign = 1;
    piv = new int[m];
    for (int i = 0; i < m; i++) piv[i] = i;

    // Outer loop.
    for (int j = 0; j < n; j++) {

      if (n > 1000) System.out.printf("%d / %d\r", j, n);

      // Make a copy of the j-th column to localize references.
      Vec LUcolj = LU.getColumn(j);

      // Apply previous transformations.
      for (int i = 0; i < m; i++) {
        Vec LUrowi = LU.getRow(i);

        // Most of the time is spent in the following dot product.

        int kmax = Math.min(i, j);
        double s = LUrowi.dotProduct(LUcolj, 0, kmax - 1);

        LUcolj.plusEquals(i, -s);
        LUrowi.plusEquals(j, -s);
      }

      // Find pivot and exchange if necessary.
      int p = j;
      if (autoPivot) {
        for (int i = j + 1; i < m; i++) {
          if (Math.abs(LUcolj.get(i)) > Math.abs(LUcolj.get(p))) {
            p = i;
          }
        }
      }

      if (p != j) {
        LU.swapRows(p, j);
        int k = piv[p];
        piv[p] = piv[j];
        piv[j] = k;
        pivsign = -pivsign;
      }

      // Compute multipliers.
      if (j < n && j < m && LU.get(j, j) != 0.0) {
        double LUjj = LU.get(j, j);
        for (int i = j + 1; i < m; i++) {
          LU.timesEquals(i, j, 1.0 / LUjj);
        }
      }
    }
  }
  @Override
  public void mutablePairwiseDivide(Vec b) {
    if (this.length() != b.length())
      throw new ArithmeticException("Vectors must have the same length");
    clearCaches();

    for (int i = 0; i < used; i++) values[i] /= b.get(indexes[i]); // zeros stay zero
  }
示例#3
0
 public Tensor3 setRow(final int i, final int j, final Vec val) {
   if (val.dim() != dim3)
     throw new IllegalArgumentException(
         "val.dim() != dim3, val.dim() = " + val.dim() + ", dim3 = " + dim3);
   final int index = index(i, j, 0);
   for (int l = 0; l < dim3; l++) vec.set(index + l, val.get(l));
   return this;
 }
  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof Vec)) return false;
    Vec otherVec = (Vec) obj;

    if (this.length() != otherVec.length()) return false;

    int z = 0;
    for (int i = 0; i < length(); i++) {
      // Move through until we hit the next null element, comparing the other vec to zero
      while (z < used && indexes[z] > i) if (otherVec.get(i++) != 0) return false;

      // We made it! (or are at the end). Is our non zero value the same?
      if (z < used && indexes[z] == i) if (values[z++] != otherVec.get(i)) return false;
    }

    return true;
  }
  @Override
  public double pNormDist(double p, Vec y) {
    if (this.length() != y.length())
      throw new ArithmeticException("Vectors must be of the same length");

    double norm = 0;

    if (y instanceof SparseVector) {
      int p1 = 0, p2 = 0;
      SparseVector b = (SparseVector) y;

      while (p1 < this.used && p2 < b.used) {
        int a1 = indexes[p1], a2 = b.indexes[p2];
        if (a1 == a2) {
          norm += Math.pow(Math.abs(this.values[p1] - b.values[p2]), p);
          p1++;
          p2++;
        } else if (a1 > a2) norm += Math.pow(Math.abs(b.values[p2++]), p);
        else // a1 < a2, this vec has a value, other does not
        norm += Math.pow(Math.abs(this.values[p1++]), p);
      }
      // One of them is now empty.
      // So just sum up the rest of the elements
      while (p1 < this.used) norm += Math.pow(Math.abs(this.values[p1++]), p);
      while (p2 < b.used) norm += Math.pow(Math.abs(b.values[p2++]), p);
    } else {
      int z = 0;
      for (int i = 0; i < length(); i++) {
        // Move through until we hit the next null element, comparing the other vec to zero
        while (z < used && indexes[z] > i) norm += Math.pow(Math.abs(-y.get(i++)), p);

        // We made it! (or are at the end). Is our non zero value the same?
        if (z < used && indexes[z] == i) norm += Math.pow(Math.abs(values[z] - y.get(i)), p);
      }
    }
    return Math.pow(norm, 1.0 / p);
  }
  @Override
  public double dot(Vec v) {
    double dot = 0;

    if (v instanceof SparseVector) {
      SparseVector b = (SparseVector) v;
      int p1 = 0, p2 = 0;
      while (p1 < used && p2 < b.used) {
        int a1 = indexes[p1], a2 = b.indexes[p2];
        if (a1 == a2) dot += values[p1++] * b.values[p2++];
        else if (a1 > a2) p2++;
        else p1++;
      }
    } else // it is dense
    for (int i = 0; i < used; i++) dot += values[i] * v.get(indexes[i]);

    return dot;
  }
  @Override
  public void mutableAdd(double c, Vec v) {
    clearCaches();
    if (c == 0.0) return;
    if (v instanceof SparseVector) {
      SparseVector b = (SparseVector) v;
      int p1 = 0, p2 = 0;
      while (p1 < used && p2 < b.used) {
        int a1 = indexes[p1], a2 = b.indexes[p2];
        if (a1 == a2) {
          values[p1] += c * b.values[p2];
          p1++;
          p2++;
        } else if (a1 > a2) {
          // 0 + some value is that value, set it
          this.set(a2, c * b.values[p2]);
          /*
           * p2 must be increment becase were moving to the next value
           *
           * p1 must be be incremented becase a2 was less thenn the current index.
           * So the inseration occured before p1, so for indexes[p1] to == a1,
           * p1 must be incremented
           *
           */
          p1++;
          p2++;
        } else // a1 < a2, thats adding 0 to this vector, nothing to do.
        {
          p1++;
        }
      }

      // One of them is now empty.
      // If b is not empty, we must add b to this. If b is empty, we would be adding zeros to this
      // [so we do nothing]
      while (p2 < b.used)
        this.set(b.indexes[p2], c * b.values[p2++]); // TODO Can be done more efficently
    } else if (v.isSparse()) {
      if (v.nnz() == 0) return;
      int p1 = 0;
      Iterator<IndexValue> iter = v.getNonZeroIterator();
      IndexValue iv = iter.next();
      while (p1 < used && iv != null) {
        int a1 = indexes[p1];
        int a2 = iv.getIndex();

        if (a1 == a2) {
          values[p1++] += c * iv.getValue();
          if (iter.hasNext()) iv = iter.next();
          else break;
        } else if (a1 > a2) {
          this.set(a2, c * iv.getValue());
          p1++;
          if (iter.hasNext()) iv = iter.next();
          else break;
        } else p1++;
      }
    } else {
      // Else it is dense
      for (int i = 0; i < length(); i++) this.set(i, this.get(i) + c * v.get(i));
    }
  }