예제 #1
0
 def block_simplify(self):
     """Try to combine scalar terms and remove additive identities,
     recursively. A fuller explanation is found in block_transform.block_simplify.
     """
     from block_util import isscalar
     from block_transform import block_simplify
     A = block_simplify(self.A)
     B = block_simplify(self.B)
     if isscalar(A) and A == 0:
         return B
     if isscalar(B) and B == 0:
         return A
     return A + B
예제 #2
0
    def block_collapse(self):
        """Create a block_mat of block_adds from a block_add of block_mats. See block_transform.block_collapse."""
        from block_mat import block_mat
        from block_util import isscalar
        from block_transform import block_collapse, block_simplify

        A = block_collapse(self.A)
        B = block_collapse(self.B)

        # The self.__class__(A,B) used below works for both block_sub and
        # block_add, and any scalar terms are combined by the final call to
        # block_simplify().
        if isinstance(A, block_mat) and isinstance(B, block_mat):
            m, n = A.blocks.shape
            C = block_mat(m, n)
            for row in range(m):
                for col in range(n):
                    C[row, col] = self.__class__(A[row, col], B[row, col])
        elif isinstance(A, block_mat) and isscalar(B):
            m, n = A.blocks.shape
            C = block_mat(m, n)
            for row in range(m):
                for col in range(n):
                    C[row, col] = self.__class__(
                        A[row, col], B) if row == col else A[row, col]
        elif isinstance(B, block_mat) and isscalar(A):
            m, n = B.blocks.shape
            C = block_mat(m, n)
            for row in range(m):
                for col in range(n):
                    C[row, col] = self.__class__(
                        A, B[row, col]) if row == col else B[row, col]
        else:
            C = self.__class__(A, B)
        return block_simplify(C)
예제 #3
0
 def block_simplify(self):
     """Try to convert identities to scalars, recursively. A fuller
     explanation is found in block_transform.block_simplify.
     """
     from block_util import isscalar
     from block_transform import block_simplify
     m, n = self.blocks.shape
     res = block_mat(m, n)
     # Recursive call
     for i in range(m):
         for j in range(n):
             res[i, j] = block_simplify(self[i, j])
     # Check if result after recursive conversion is the (scaled) identity
     v0 = res.blocks[0, 0]
     if m != n:
         return res
     for i in range(m):
         for j in range(n):
             block = res.blocks[i, j]
             if not isscalar(block):
                 return res
             if i == j:
                 if block != v0:
                     return res
             else:
                 if block != 0:
                     return res
     return v0
예제 #4
0
 def block_simplify(self):
     """Try to simplify the transpose, recursively. A fuller explanation is
     found in block_transform.block_simplify.
     """
     from block_util import isscalar
     from block_transform import block_simplify
     A = block_simplify(self.A)
     if isscalar(A):
         return A
     if isinstance(A, block_transpose):
         return A.A
     return block_transpose(A)
예제 #5
0
 def block_collapse(self):
     """See block_transform.block_collapse."""
     from block_transform import block_collapse, block_simplify
     from block_mat import block_mat
     A = block_collapse(self.A)
     if not isinstance(A, block_mat):
         return block_transpose(A)
     m, n = A.blocks.shape
     ret = block_mat(n, m)
     for i in range(m):
         for j in range(n):
             ret[j, i] = block_transpose(A[i, j])
     return block_simplify(ret)
예제 #6
0
    def block_collapse(self):
        """Create a block_mat of block_muls from a block_mul of
        block_mats. See block_transform.block_collapse."""
        from block_mat import block_mat
        from block_util import isscalar
        from block_transform import block_collapse, block_simplify

        # Reduce all composed objects
        ops = map(block_collapse, self.chain)

        # Do the matrix multiply, blockwise. Note that we use
        # block_mul(A,B) rather than A*B to avoid any implicit calculations
        # (e.g., scalar*matrix->matrix) -- the result will be transformed by
        # block_simplify() in the end to take care of any stray scalars.
        while len(ops) > 1:
            B = ops.pop()
            A = ops.pop()

            if isinstance(A, block_mat) and isinstance(B, block_mat):
                m, n = A.blocks.shape
                p, q = B.blocks.shape
                C = block_mat(m, q)
                for row in range(m):
                    for col in range(q):
                        for i in range(n):
                            C[row, col] += block_mul(A[row, i], B[i, col])
            elif isinstance(A, block_mat) and isscalar(B):
                m, n = A.blocks.shape
                C = block_mat(m, n)
                for row in range(m):
                    for col in range(n):
                        C[row, col] = block_mul(A[row, col], B)
            elif isinstance(B, block_mat) and isscalar(A):
                m, n = B.blocks.shape
                C = block_mat(m, n)
                for row in range(m):
                    for col in range(n):
                        C[row, col] = block_mul(A, B[row, col])
            else:
                C = block_mul(A, B)
            ops.append(C)
        return block_simplify(ops[0])
예제 #7
0
 def block_simplify(self):
     """Try to combine scalar terms and remove multiplicative identities,
     recursively. A fuller explanation is found in block_transform.block_simplify.
     """
     from block_util import isscalar
     from block_transform import block_simplify
     operators = []
     scalar = 1.0
     for op in self.chain:
         op = block_simplify(op)
         if isscalar(op):
             scalar *= op
         else:
             operators.append(op)
     if scalar == 0:
         return 0
     if scalar != 1 or len(operators) == 0:
         operators.insert(0, scalar)
     if len(operators) == 1:
         return operators[0]
     ret = block_mul(None, None)
     ret.chain = operators
     return ret