示例#1
0
    def _forward(self):
        """Solves the lower triangular system Ly = b
    for y by forward substitution.

    If partial pivoting is used, solves the system
    Ly = Pb and if full pivoting is used, solves
    the system Ly = PbQ.
    """
        if self.b.ndim > 1:
            num_iters = self.b.shape[1]
            N = self.b.shape[0]
        else:
            num_iters = 1
            N = self.b.shape[0]

        self.y = np.zeros([N, num_iters])

        if self.pivoting is None:
            right_hand = self.b
        else:
            right_hand = np.dot(self.P, self.b)

        for k in range(num_iters):
            for i in range(N):
                acc = KahanSum()
                for j in range(i):
                    acc.add(self.L[i, j] * self.y[j, k])
                if self.b.ndim > 1:
                    self.y[i, k] = right_hand[i, k] - acc.cur_sum()
                else:
                    self.y[i, k] = right_hand[i] - acc.cur_sum()
示例#2
0
    def _backward(self):
        """Solve the upper triangular system Ux = y
    for x by back substitution.
    """
        if self.b.ndim > 1:
            num_iters = self.b.shape[1]
            N = self.b.shape[0]
        else:
            num_iters = 1
            N = self.b.shape[0]

        self.x = np.zeros([N, num_iters])

        for k in range(num_iters):
            for i in range(N - 1, -1, -1):
                acc = KahanSum()
                for j in range(N - 1, i, -1):
                    acc.add(self.U[i, j] * self.x[j, k])
                self.x[i, k] = (self.y[i, k] - acc.cur_sum()) / (
                    self.U[i, i] + 1e-10)  # prevent division by 0

        if self.b.ndim == 1:
            self.x = self.x.squeeze()

        if self.pivoting == 'full':
            self.x = np.dot(self.Q, self.x)
示例#3
0
  def _forward(self):
    """Forward substituion.

    Solves the lower triangular system `Ly = b` for y
    by forward substitution.
    """
    if self.b.ndim > 1:
      num_iters = self.b.shape[1]
      N = self.b.shape[0]
    else:
      num_iters = 1
      N = self.b.shape[0]

    self.y = np.zeros([N, num_iters])

    for k in range(num_iters):
      for i in range(N):
        acc = KahanSum()
        for j in range(i):
          acc.add(self.L[i, j]*self.y[j, k])
        if self.b.ndim > 1:
          self.y[i, k] = \
            (self.b[i, k] - acc.cur_sum()) / (self.L[i, i])
        else:
          self.y[i, k] = \
            (self.b[i] - acc.cur_sum()) / (self.L[i, i])
示例#4
0
  def decompose(self, ret=True):
    N = len(self.R)

    self.L = np.zeros_like(self.R)

    if self.crout:
      for i in range(N):
        for j in range(i+1):
          summer = KahanSum()
          for k in range(j):
            summer.add(self.L[i, k] * self.L[j, k])
          sum = summer.cur_sum()

          if (i == j):
            self.L[j, j] = np.sqrt(self.R[j, j] - sum)
          else:
            self.L[i, j] = (self.R[i, j] - sum) / (self.L[j, j])
      if ret:
        return self.L
    else:
      for i in range(N):
        self.pivot = self.R[i, i]

        # eliminate subsequent rows
        for j in range(i+1, N):
          for k in range(j, N):
            self.R[j, k] -= self.R[i, k] * \
                    (self.R[i, j] / self.pivot)

        # scale the current row
        for k in range(i, N):
          self.R[i, k] /= np.sqrt(self.pivot)

      if ret:
        return self.R.T
示例#5
0
  def _backward(self):
    """Backward substitution.

    Solves the upper triangular system `L^Tx = y` for x
    by back substitution.
    """
    if self.b.ndim > 1:
      num_iters = self.b.shape[1]
      N = self.b.shape[0]
    else:
      num_iters = 1
      N = self.b.shape[0]

    self.x = np.zeros([N, num_iters])

    for k in range(num_iters):
      for i in range(N-1, -1, -1):
        acc = KahanSum()
        for j in range(N-1, i, -1):
          acc.add(self.L.T[i, j]*self.x[j, k])
        self.x[i, k] = \
          (self.y[i, k] - acc.cur_sum()) / (self.L.T[i, i])

    if self.b.ndim == 1:
      self.x = self.x.squeeze()
示例#6
0
  def _backward(self):
    """Solve the upper triangular system Rx = y
    for x by back substitution, where `y = Q.Tb`.
    """
    M, N = self.R.shape
    K = min(M, N)
    self.y = np.dot(self.Q.T, self.b)

    if self.y.ndim == 1:
      self.y = np.reshape(self.y, [-1, 1])

    if self.b.ndim == 2:
      num_iters = self.b.shape[1]
    else:
      num_iters = 1

    self.x = np.zeros([N, num_iters])

    for k in range(num_iters):
      for i in range(K-1, -1, -1):
        acc = KahanSum()
        for j in range(K-1, i, -1):
          acc.add(self.R[i, j]*self.x[j, k])
        self.x[i, k] = (self.y[i, k] - acc.cur_sum()) / (self.R[i, i])

    if self.b.ndim == 1:
      self.x = self.x.squeeze()
示例#7
0
def inverse(A):
    """Computes the inverse of a square matrix A.

  Concretely, solves the linear system Ax = I
  where x is a square matrix rather than a vector.

  The system is solved using LU decomposition with
  partial pivoting.

  Args:
    A: a numpy array of shape (N, N).

  Returns:
    A numpy array of shape (N, N).
  """
    N = A.shape[0]

    P, L, U = LU(A, pivoting='partial').decompose()

    # transpose P since LU returns A = PLU
    P = P.T

    # solve Ly = P for y
    y = np.zeros_like(L)
    for i in range(N):
        for j in range(N):
            summer = KahanSum()
            for k in range(i):
                summer.add(L[i, k] * y[k, j])
            sum = summer.result()
            y[i, j] = (P[i, j] - sum) / (L[i, i])

    # solve Ux = y for x
    x = np.zeros_like(U)
    for i in range(N - 1, -1, -1):
        for j in range(N):
            summer = KahanSum()
            for k in range(N - 1, i, -1):
                summer.add(U[i, k] * x[k, j])
            sum = summer.result()
            x[i, j] = (y[i, j] - sum) / (U[i, i])

    return x