예제 #1
0
def ludcmp_chol(matrix, test=False):
    """
    Decomposes/factorizes square, positive definite input matrix into 
    one lower and one upper matrix. The upper matrix is the transpose of 
    the lower matrix. 
    
    NB. It only works on square, symmetric, positive definite matrices!!! 
    """

    if test:
        errortext1 = "Input matrix not positive definite in ludcmp_chol!"
        assert is_posdefinite(matrix), errortext1
        errortext2 = "Input matrix not symmetric in ludcmp_chol!"
        assert is_symmetrical(matrix), errortext2

    ndim = squaredim(matrix, 'ludcmp_chol')

    # Create new square matrix of the same size as the input matrix:
    clower = Matrix()
    clower.zero(ndim, ndim)

    # Perform the necessary manipulations:
    for k in range(0, ndim):
        kp1 = k + 1
        for j in range(0, kp1):
            summ = 0.0
            for i in range(0, j): summ += clower[k][i]*clower[j][i]
            if j == k: clower[k][j] = sqrt(matrix[k][j] - summ)
            else:      clower[k][j] = (matrix[k][j]-summ) / float(clower[j][j])

    clowert = transposed(clower)

    return clower, clowert
예제 #2
0
def is_posdefinite(matrix):
    """
    The test for positive definiteness using the determinants of the nested 
    principal minor matrices is taken from Varian; "Microeconomic Analysis". 
    Returns True if input matrix is positive definite, False otherwise. 
    """

    flag = True

    ndim = squaredim(matrix, 'is_posdefinite')

    for k in range(0, ndim):
        '''# Test No. 1 - Necessary condition for positive SEMI-definiteness:
        if matrix[k][k] <= 0.0:
            flag = False
            break'''
        # (Test No. 2 -) Sufficient condition for positive definiteness:
        minor = Matrix()
        kp1 = k + 1
        minor.zero(kp1, kp1)
        for j in range(0, kp1):
            for i in range(0, kp1): minor[j][i] = matrix[j][i]
        x = determinant(minor)
        del minor
        if x <= 0.0:
            flag = False
            break

    return flag
예제 #3
0
def ludcmp_crout(matrix):
    """
    Decomposes/factorizes square input matrix into a lower and an 
    upper matrix using Crout's algorithm WITHOUT pivoting. 
    
    NB. It only works for square matrices!!! 
    """

    ndim = squaredim(matrix, 'ludcmp_crout')

    # Copy object instance to new matrix in order for the original instance 
    # not to be destroyed.
    # Create two new square matrices of the same sized as the input matrix:
    # one unity matrix (to be the lower matrix), one zero matrix (to be 
    # the upper matrix)
    copymx   = deepcopy(matrix)
    lower    = Matrix()
    lower.unity(ndim)
    upper    = Matrix()
    upper.zero(ndim, ndim)
    permlist = list(range(0, ndim))

    # Perform the necessary manipulations:
    for j in range(0, ndim):
        iu = 0
        while iu <= j:
            k    = 0
            summ = 0.0
            while k < iu:
                summ += lower[iu][k]*upper[k][j]
                k   = k + 1
            upper[iu][j] = copymx[iu][j] - summ
            iu = iu + 1
        il = j + 1
        while il < ndim:
            k    = 0
            summ = 0.0
            while k < j:
                summ += lower[il][k]*upper[k][j]
                k = k + 1
            divisor = float(upper[j][j])
            if abs(divisor) < TINY: divisor = fsign(divisor)*TINY
            lower[il][j] = (copymx[il][j]-summ) / divisor
            il = il + 1

    parity = 1.0


    return lower, upper, permlist, parity
예제 #4
0
def ludcmp_crout(matrix):
    """
    Decomposes/factorizes square input matrix into a lower and an 
    upper matrix using Crout's algorithm WITHOUT pivoting. 
    
    NB. It only works for square matrices!!! 
    """

    ndim = squaredim(matrix, 'ludcmp_crout')

    # Copy object instance to new matrix in order for the original instance
    # not to be destroyed.
    # Create two new square matrices of the same sized as the input matrix:
    # one unity matrix (to be the lower matrix), one zero matrix (to be
    # the upper matrix)
    copymx = deepcopy(matrix)
    lower = Matrix()
    lower.unity(ndim)
    upper = Matrix()
    upper.zero(ndim, ndim)
    permlist = list(range(0, ndim))

    # Perform the necessary manipulations:
    for j in range(0, ndim):
        iu = 0
        while iu <= j:
            k = 0
            summ = 0.0
            while k < iu:
                summ += lower[iu][k] * upper[k][j]
                k = k + 1
            upper[iu][j] = copymx[iu][j] - summ
            iu = iu + 1
        il = j + 1
        while il < ndim:
            k = 0
            summ = 0.0
            while k < j:
                summ += lower[il][k] * upper[k][j]
                k = k + 1
            divisor = float(upper[j][j])
            if abs(divisor) < TINY: divisor = fsign(divisor) * TINY
            lower[il][j] = (copymx[il][j] - summ) / divisor
            il = il + 1

    parity = 1.0

    return lower, upper, permlist, parity
예제 #5
0
def inverted(matrix, pivoting=True):
    """
    Only square matrices can be inverted! 
    """

    ndim = squaredim(matrix, 'inverted')

    # First: LU-decompose matrix to be inverted
    if pivoting:
        lower, upper, permlist, parity = ludcmp_crout_piv(matrix)
    else:
        lower, upper, permlist, parity = ludcmp_crout(matrix)

    # Create unity matrix
    unitymatrix = Matrix()
    unitymatrix.unity(ndim)

    # Loop over the columns in unity matrix and substitute
    # (uses the fact that rows and columns are the same in a unity matrix)
    columns = Matrix()
    columns.zero(ndim, ndim)
    for k in range(0, ndim):
        columns[k] = lusubs(lower, upper, unitymatrix[k], permlist)
        # preparations below for changing lusubs to handling column vector
        # instead of list
        #row = Matrix([unitymatrix[k]])
        #column = transpose(row)
        #columns[k] = lusubs(lower, upper, column, permlist)
        #del column

    # Transpose matrix to get inverse
    newmatrix = ndim * [float('nan')]
    for k in range(0,
                   ndim):  # List comprehension is used for the innermost loop
        newmatrix[k] = array('d', [row[k] for row in columns])
    imatrix = Matrix(newmatrix)
    del newmatrix

    return imatrix
예제 #6
0
def inverted(matrix, pivoting=True):
    """
    Only square matrices can be inverted! 
    """

    ndim = squaredim(matrix, 'inverted')

    # First: LU-decompose matrix to be inverted
    if pivoting:
        lower, upper, permlist, parity = ludcmp_crout_piv(matrix)
    else:
        lower, upper, permlist, parity = ludcmp_crout(matrix)

    # Create unity matrix
    unitymatrix = Matrix()
    unitymatrix.unity(ndim)

    # Loop over the columns in unity matrix and substitute
    # (uses the fact that rows and columns are the same in a unity matrix)
    columns = Matrix()
    columns.zero(ndim, ndim)
    for k in range(0, ndim):
        columns[k] = lusubs(lower, upper, unitymatrix[k], permlist)
        # preparations below for changing lusubs to handling column vector 
        # instead of list
        #row = Matrix([unitymatrix[k]])
        #column = transpose(row)
        #columns[k] = lusubs(lower, upper, column, permlist)
        #del column

    # Transpose matrix to get inverse
    newmatrix = ndim*[float('nan')]
    for k in range(0, ndim): # List comprehension is used for the innermost loop
        newmatrix[k] = array('d', [row[k] for row in columns])
    imatrix = Matrix(newmatrix)
    del newmatrix

    return imatrix
예제 #7
0
def ludcmp_crout_piv(matrix):
    """
    Decomposes/factorizes square input matrix into a lower 
    and an upper matrix using Crout's algorithm WITH pivoting. 
    
    NB. It only works on square matrices!!! 
    """

    ndim     = squaredim(matrix, 'ludcmp_crout_piv')
    ndm1     = ndim - 1
    vv       = array('d', ndim*[0.0])
    permlist = list(range(0, ndim))
    parity   = 1.0
    imax     = 0

    # Copy to matrix to be processed (maintains the original matrix intact)
    compactlu = deepcopy(matrix)

    for i in range(0, ndim):   # Copy and do some other stuff
        big = 0.0
        for j in range(0, ndim):
            temp = abs(compactlu[i][j])
            if temp > big: big = temp
        assert big > 0.0
        vv[i] = 1.0/big

    # Perform the necessary manipulations:
    for j in range(0, ndim):
        for i in range(0, j):
            sum = compactlu[i][j]
            for k in range(0, i): sum -= compactlu[i][k] * compactlu[k][j]
            compactlu[i][j] = sum
        big = 0.0
        for i in range(j, ndim):
            sum = compactlu[i][j]
            for k in range(0, j): sum -= compactlu[i][k] * compactlu[k][j]
            compactlu[i][j] = sum
            dum = vv[i] * abs(sum)
            if dum > big:
                big  = dum
                imax = i
        if j != imax:
            # Substitute row imax and row j
            imaxdum        = permlist[imax]   # NB in !!!!!!!!!!!!!!!!
            jdum           = permlist[j]      # NB in !!!!!!!!!!!!!!!!
            permlist[j]    = imaxdum          # NB in !!!!!!!!!!!!!!!!
            permlist[imax] = jdum             # NB in !!!!!!!!!!!!!!!!
            for k in range(0, ndim):
                dum                = compactlu[imax][k]
                compactlu[imax][k] = compactlu[j][k]
                compactlu[j][k]    = dum
            parity   = - parity
            vv[imax] = vv[j]
        #permlist[j] = imax   # NB out !!!!!!!!!!!!!!!!!!!!!
        divisor = float(compactlu[j][j])
        if abs(divisor) < TINY: divisor = fsign(divisor)*TINY
        dum = 1.0 / divisor
        if j != ndm1:
            jp1 = j + 1
            for i in range(jp1, ndim): compactlu[i][j] *= dum

    lower = Matrix()
    lower.zero(ndim, ndim)
    upper = Matrix()
    upper.zero(ndim, ndim)

    for i in range(0, ndim):
        for j in range(i, ndim): lower[j][i] = compactlu[j][i]
    for i in range(0, ndim):
        lower[i][i] = 1.0

    for i in range(0, ndim):
        for j in range(i, ndim): upper[i][j] = compactlu[i][j]

    del compactlu


    return lower, upper, permlist, parity
예제 #8
0
def ludcmp_crout_piv(matrix):
    """
    Decomposes/factorizes square input matrix into a lower 
    and an upper matrix using Crout's algorithm WITH pivoting. 
    
    NB. It only works on square matrices!!! 
    """

    ndim = squaredim(matrix, 'ludcmp_crout_piv')
    ndm1 = ndim - 1
    vv = array('d', ndim * [0.0])
    permlist = list(range(0, ndim))
    parity = 1.0
    imax = 0

    # Copy to matrix to be processed (maintains the original matrix intact)
    compactlu = deepcopy(matrix)

    for i in range(0, ndim):  # Copy and do some other stuff
        big = 0.0
        for j in range(0, ndim):
            temp = abs(compactlu[i][j])
            if temp > big: big = temp
        assert big > 0.0
        vv[i] = 1.0 / big

    # Perform the necessary manipulations:
    for j in range(0, ndim):
        for i in range(0, j):
            sum = compactlu[i][j]
            for k in range(0, i):
                sum -= compactlu[i][k] * compactlu[k][j]
            compactlu[i][j] = sum
        big = 0.0
        for i in range(j, ndim):
            sum = compactlu[i][j]
            for k in range(0, j):
                sum -= compactlu[i][k] * compactlu[k][j]
            compactlu[i][j] = sum
            dum = vv[i] * abs(sum)
            if dum > big:
                big = dum
                imax = i
        if j != imax:
            # Substitute row imax and row j
            imaxdum = permlist[imax]  # NB in !!!!!!!!!!!!!!!!
            jdum = permlist[j]  # NB in !!!!!!!!!!!!!!!!
            permlist[j] = imaxdum  # NB in !!!!!!!!!!!!!!!!
            permlist[imax] = jdum  # NB in !!!!!!!!!!!!!!!!
            for k in range(0, ndim):
                dum = compactlu[imax][k]
                compactlu[imax][k] = compactlu[j][k]
                compactlu[j][k] = dum
            parity = -parity
            vv[imax] = vv[j]
        #permlist[j] = imax   # NB out !!!!!!!!!!!!!!!!!!!!!
        divisor = float(compactlu[j][j])
        if abs(divisor) < TINY: divisor = fsign(divisor) * TINY
        dum = 1.0 / divisor
        if j != ndm1:
            jp1 = j + 1
            for i in range(jp1, ndim):
                compactlu[i][j] *= dum

    lower = Matrix()
    lower.zero(ndim, ndim)
    upper = Matrix()
    upper.zero(ndim, ndim)

    for i in range(0, ndim):
        for j in range(i, ndim):
            lower[j][i] = compactlu[j][i]
    for i in range(0, ndim):
        lower[i][i] = 1.0

    for i in range(0, ndim):
        for j in range(i, ndim):
            upper[i][j] = compactlu[i][j]

    del compactlu

    return lower, upper, permlist, parity