def eval_covariance_matrix_qr(J1, J2):
    M,N = J1.shape
    K,N = J2.shape
    Q,R = qr_full(J2.T)
    Q2 = Q[:,K:].T
    J1_tilde = dot(J1,Q2.T)
    Q,R = qr(J1_tilde)
    V = solve(R.T, Q2)
    return dot(V.T,V)
def eval_covariance_matrix_qr(J1, J2):
    M, N = J1.shape
    K, N = J2.shape
    Q, R = qr_full(J2.T)
    Q2 = Q[:, K:].T
    J1_tilde = dot(J1, Q2.T)
    Q, R = qr(J1_tilde)
    V = solve(R.T, Q2)
    return dot(V.T, V)
def algopy_expm(A, n):
    """
    Compute the matrix exponential using Pade approximation.
    Reference --
    N. J. Higham,
    "The Scaling and Squaring Method for the Matrix Exponential Revisited",
    SIAM. J. Matrix Anal. & Appl. 26, 1179 (2005).
    """
    # XXX can I get rid of the n argument to this function?
    # XXX also my algopy_eye function does not work anyway.
    ident = algopy_eye(n, dtype=A)
    U, V = _algopy_pade7(A, ident)
    return algopy.solve(-U + V, U + V)
def algopy_expm(A, n):
    """
    Compute the matrix exponential using Pade approximation.
    Reference --
    N. J. Higham,
    "The Scaling and Squaring Method for the Matrix Exponential Revisited",
    SIAM. J. Matrix Anal. & Appl. 26, 1179 (2005).
    """
    # XXX can I get rid of the n argument to this function?
    # XXX also my algopy_eye function does not work anyway.
    ident = algopy_eye(n, dtype=A)
    U, V = _algopy_pade7(A, ident)
    return algopy.solve(-U + V, U + V)
Example #5
0
    def test_pullback_solve_inv_comparison(self):
        """simple check that the reverse mode of solve(A,Id) computes the same solution
        as inv(A)
        """
        (D,P,N) = 3,7,10
        A_data = numpy.random.rand(D,P,N,N)

        # make A_data sufficiently regular
        for p in range(P):
            for n in range(N):
                A_data[0,p,n,n] += (N + 1)

        A = UTPM(A_data)

        # method 1: computation of the inverse matrix by solving an extended linear system
        # tracing
        cg1 = CGraph()
        A = Function(A)
        Id = numpy.eye(N)
        Ainv1 = solve(A,Id)
        cg1.trace_off()
        cg1.independentFunctionList = [A]
        cg1.dependentFunctionList = [Ainv1]

        # reverse
        Ainvbar = UTPM(numpy.random.rand(*(D,P,N,N)))
        cg1.pullback([Ainvbar])

        # method 2: direct inversion
        # tracing
        cg2 = CGraph()
        A = Function(A.x)
        Ainv2 = inv(A)
        cg2.trace_off()
        cg2.independentFunctionList = [A]
        cg2.dependentFunctionList = [Ainv2]

        # reverse
        cg2.pullback([Ainvbar])

        Abar1 = cg1.independentFunctionList[0].xbar
        Abar2 = cg2.independentFunctionList[0].xbar

        assert_array_almost_equal(Abar1.data, Abar2.data)
A = A[:,:2]


# Method 1: Naive approach
Apinv = dot(inv(dot(A.T,A)),A.T)

print('naive approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv),A) - A)
print('naive approach: Apinv A Apinv - Apinv = 0 \n', dot(dot(Apinv, A),Apinv) - Apinv)
print('naive approach: (Apinv A)^T - Apinv A = 0 \n', dot(Apinv, A).T  - dot(Apinv, A))
print('naive approach: (A Apinv)^T - A Apinv = 0 \n', dot(A, Apinv).T  - dot(A, Apinv))


# Method 2: Using the differentiated QR decomposition
Q,R = qr(A)
tmp1 = solve(R.T, A.T)
tmp2 = solve(R, tmp1)
Apinv = tmp2

print('QR approach: A Apinv A - A = 0 \n',  dot(dot(A, Apinv),A) - A)
print('QR approach: Apinv A Apinv - Apinv = 0 \n', dot(dot(Apinv, A),Apinv) - Apinv)
print('QR approach: (Apinv A)^T - Apinv A = 0 \n', dot(Apinv, A).T  - dot(Apinv, A))
print('QR approach: (A Apinv)^T - A Apinv = 0 \n', dot(A, Apinv).T  - dot(A, Apinv))

# Method 3: Stable evaluation of the analytical derivative formula

A0 = A.data[0,0]
A1 = A.data[1,0]

Q0, R0 = numpy.linalg.qr(A0)
A = A[:, :2]

# Method 1: Naive approach
Apinv = dot(inv(dot(A.T, A)), A.T)

print('naive approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv), A) - A)
print('naive approach: Apinv A Apinv - Apinv = 0 \n',
      dot(dot(Apinv, A), Apinv) - Apinv)
print('naive approach: (Apinv A)^T - Apinv A = 0 \n',
      dot(Apinv, A).T - dot(Apinv, A))
print('naive approach: (A Apinv)^T - A Apinv = 0 \n',
      dot(A, Apinv).T - dot(A, Apinv))

# Method 2: Using the differentiated QR decomposition
Q, R = qr(A)
tmp1 = solve(R.T, A.T)
tmp2 = solve(R, tmp1)
Apinv = tmp2

print('QR approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv), A) - A)
print('QR approach: Apinv A Apinv - Apinv = 0 \n',
      dot(dot(Apinv, A), Apinv) - Apinv)
print('QR approach: (Apinv A)^T - Apinv A = 0 \n',
      dot(Apinv, A).T - dot(Apinv, A))
print('QR approach: (A Apinv)^T - A Apinv = 0 \n',
      dot(A, Apinv).T - dot(A, Apinv))

# Method 3: Stable evaluation of the analytical derivative formula

A0 = A.data[0, 0]
A1 = A.data[1, 0]
y.data[1, 0, :, 0] = [1, 2, 1, 2, 1]

alpha = 10**-5
A = dot(x, x.T) + alpha * dot(y, y.T)
A = A[:, :2]

# Method 1: Naive approach
Apinv = dot(inv(dot(A.T, A)), A.T)

print('naive approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv), A) - A)
print('naive approach: Apinv A Apinv - Apinv = 0 \n',
      dot(dot(Apinv, A), Apinv) - Apinv)
print('naive approach: (Apinv A)^T - Apinv A = 0 \n',
      dot(Apinv, A).T - dot(Apinv, A))
print('naive approach: (A Apinv)^T - A Apinv = 0 \n',
      dot(A, Apinv).T - dot(A, Apinv))

# Method 2: Using the differentiated QR decomposition
Q, R = qr(A)
tmp1 = solve(R.T, A.T)
tmp2 = solve(R, tmp1)
Apinv = tmp2

print('QR approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv), A) - A)
print('QR approach: Apinv A Apinv - Apinv = 0 \n',
      dot(dot(Apinv, A), Apinv) - Apinv)
print('QR approach: (Apinv A)^T - Apinv A = 0 \n',
      dot(Apinv, A).T - dot(Apinv, A))
print('QR approach: (A Apinv)^T - A Apinv = 0 \n',
      dot(A, Apinv).T - dot(A, Apinv))
Example #9
0
def _truss(A):
    P = 1e5 # applied loads
    Ls = 360 # length of sides
    Ld = np.sqrt(360**2 * 2) # length of diagonals

    # start = algopy.zeors(10, dtype=)
    start = np.array([5, 3, 6, 4, 4, 2, 5, 6, 3, 4]) - 1
    finish = np.array([3, 1, 4, 2, 3, 1, 4, 3, 2, 1]) - 1
    phi = np.deg2rad(np.array([0, 0, 0, 0, 90, 90, -45, 45, -45, 45]))
    L = np.concatenate(([Ls] * 6, [Ld] * 4), axis=0)

    nbar = np.size(A)
    E = 1e7 * np.ones( nbar) # modulus of elasticity
    rho = 0.1 * np.ones(nbar) # material density

    Fx = algopy.zeros(6, dtype=float)
    Fy = np.array([0.0, -P, 0.0, -P, 0.0, 0.0])
    rigidx = np.array([0, 0, 0, 0, 1, 1])
    rigidy = np.array([0, 0, 0, 0, 1, 1])

    n = np.size(Fx) #number of nodes
    DOF = 2

    # compute mass
    mass = sum(rho * A * L)

    # assemble global matrices
    K = algopy.zeros((DOF * n, DOF * n), dtype=A)
    S = algopy.zeros((nbar, DOF * n), dtype=A)

    for i in range(nbar): #loop through each bar
        Ksub, Ssub = bar(E[i], A[i], L[i], phi[i])
        idx = node2idx([start[i], finish[i]], DOF)
        idxx, idxy = np.meshgrid(idx,idx)

        for j in range(4):
            S[i, int(idx[j])] = Ssub[j]
            for k in range(4):
                K[int(idxy[j,k]), (idxx[j,k])] += Ksub[j,k]
        # set_trace()

    #setup applied loads
    # F = algopy.zeros(n * DOF, dtype=A)
    F = np.zeros(n * DOF)

    for i in range(n):
        idx = node2idx([i], DOF)
        # F[int(idx[0])] = Fx[i]
        # F[int(idx[1])] = Fy[i]
        F[idx[0]] = Fx[i]
        F[idx[1]] = Fy[i]

    #setup boundary condition
    idxx = np.argwhere(rigidx).squeeze()
    idxy = np.argwhere(rigidy).squeeze()
    removex = node2idx(idxx.tolist(), DOF)
    tempx = np.reshape(removex, (2,-1), order='F')
    removey = node2idx(idxy.tolist() , DOF)
    tempy = np.reshape(removey, (2,-1), order='F')
    removex = tempx[0,:]
    removey = tempy[1,:]

    remove = np.concatenate((removex, removey), axis=0)

    # K = np.delete(K, remove, axis=0)
    # K = np.delete(K, remove, axis=1)
    # F = np.delete(F, remove)
    # S = np.delete(S, remove, axis=1)
    K = K[:8, :8]
    F = F[:8]
    S = S[:, :8]

    d = algopy.solve(K, F.reshape((8,1)))
    # d = F.solve(K)
    # d = K.solve(F)
    stress = algopy.dot(S, d)

    return mass, stress
x.data[0,0,:,0] = [1,1,1,1,1]
x.data[1,0,:,0] = [1,1,1,1,1]

y.data[0,0,:,0] = [1,2,1,2,1]
y.data[1,0,:,0] = [1,2,1,2,1]

alpha = 10**-5
A = dot(x,x.T) + alpha*dot(y,y.T)
A = A[:,:2]

# Method 1: Naive approach
Apinv = dot(inv(dot(A.T,A)),A.T)

print('naive approach: A Apinv A - A = 0 \n', dot(dot(A, Apinv),A) - A)
print('naive approach: Apinv A Apinv - Apinv = 0 \n', dot(dot(Apinv, A),Apinv) - Apinv)
print('naive approach: (Apinv A)^T - Apinv A = 0 \n', dot(Apinv, A).T  - dot(Apinv, A))
print('naive approach: (A Apinv)^T - A Apinv = 0 \n', dot(A, Apinv).T  - dot(A, Apinv))


# Method 2: Using the differentiated QR decomposition
Q,R = qr(A)
tmp1 = solve(R.T, A.T)
tmp2 = solve(R, tmp1)
Apinv = tmp2

print('QR approach: A Apinv A - A = 0 \n',  dot(dot(A, Apinv),A) - A)
print('QR approach: Apinv A Apinv - Apinv = 0 \n', dot(dot(Apinv, A),Apinv) - Apinv)
print('QR approach: (Apinv A)^T - Apinv A = 0 \n', dot(Apinv, A).T  - dot(Apinv, A))
print('QR approach: (A Apinv)^T - A Apinv = 0 \n', dot(A, Apinv).T  - dot(A, Apinv)) 
# N number of cols of J1
# K number of rows of J2 (must be smaller than N)
D, P, M, N, K, Nx = 2, 1, 100, 3, 1, 1

# METHOD 1: nullspace method
cg1 = CGraph()

J1 = Function(UTPM(numpy.random.rand(*(D, P, M, N))))
J2 = Function(UTPM(numpy.random.rand(*(D, P, K, N))))

Q, R = Function.qr_full(J2.T)
Q2 = Q[:, K:].T

J1_tilde = dot(J1, Q2.T)
Q, R = qr(J1_tilde)
V = solve(R.T, Q2)
C = dot(V.T, V)
cg1.trace_off()

cg1.independentFunctionList = [J1, J2]
cg1.dependentFunctionList = [C]

print('covariance matrix: C =\n', C)
print('check that Q2.T spans the nullspace of J2:\n', dot(J2, Q2.T))

# METHOD 2: image space method (potentially numerically unstable)
cg2 = CGraph()

J1 = Function(J1.x)
J2 = Function(J2.x)
D,P,M,N,K,Nx = 2,1,100,3,1,1


# METHOD 1: nullspace method
cg1 = CGraph()

J1 = Function(UTPM(numpy.random.rand(*(D,P,M,N))))
J2 = Function(UTPM(numpy.random.rand(*(D,P,K,N))))


Q,R = Function.qr_full(J2.T)
Q2 = Q[:,K:].T

J1_tilde = dot(J1,Q2.T)
Q,R = qr(J1_tilde)
V = solve(R.T, Q2)
C = dot(V.T,V)
cg1.trace_off()

cg1.independentFunctionList = [J1, J2]
cg1.dependentFunctionList = [C]

print('covariance matrix: C =\n',C)
print('check that Q2.T spans the nullspace of J2:\n', dot(J2,Q2.T))

# METHOD 2: image space method (potentially numerically unstable)
cg2 = CGraph()

J1 = Function(J1.x)
J2 = Function(J2.x)
Example #13
0
def truss_AD(A):
    """Computes mass and stress for the 10-bar truss problem
    Parameters
    ----------
    A : ndarray of length nbar
        cross-sectional areas of each bar
        see image in book for number order if needed
    Outputs
    -------
    mass : float
        mass of the entire structure
    stress : ndarray of length nbar
        stress in each bar
    """

    # --- specific truss setup -----
    P = 1e5  # applied loads
    Ls = 360.0  # length of sides
    Ld = sqrt(360**2 * 2)  # length of diagonals

    start = [5, 3, 6, 4, 4, 2, 5, 6, 3, 4]
    finish = [3, 1, 4, 2, 3, 1, 4, 3, 2, 1]
    phi = np.array([0, 0, 0, 0, 90, 90, -45, 45, -45, 45]) * pi / 180
    L = np.array([Ls, Ls, Ls, Ls, Ls, Ls, Ld, Ld, Ld, Ld])

    nbar = len(A)  # number of bars
    E = 1e7 * np.ones(nbar)  # modulus of elasticity
    rho = 0.1 * np.ones(nbar)  # material density

    Fx = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
    Fy = np.array([0.0, -P, 0.0, -P, 0.0, 0.0])
    rigid = [False, False, False, False, True, True]
    # ------------------

    n = len(Fx)  # number of nodes
    DOF = 2  # number of degrees of freedom

    # mass
    mass = np.sum(rho * A * L)

    # stiffness and stress matrices
    K = algopy.zeros((DOF * n, DOF * n), dtype=A)
    S = np.zeros((nbar, DOF * n))

    for i in range(nbar):  # loop through each bar

        # compute submatrix for each element
        Ksub, Ssub = bar(E[i], A[i], L[i], phi[i])
        # insert submatrix into global matrix
        idx = node2idx([
            start[i], finish[i]
        ], DOF)  # pass in the starting and ending node number for this element
        # K[np.ix_(idx, idx)] += Ksub
        for j in range(4):
            for k in range(4):
                K[idx[j], idx[k]] += Ksub[j, k]
        S[i, idx] = Ssub

    # applied loads
    F = np.zeros((n * DOF, 1))

    for i in range(n):
        idx = node2idx([i + 1],
                       DOF)  # add 1 b.c. made indexing 1-based for convenience
        F[idx[0]] = Fx[i]
        F[idx[1]] = Fy[i]

    # boundary condition
    idx = np.squeeze(np.where(rigid))
    remove = node2idx(idx + 1,
                      DOF)  # add 1 b.c. made indexing 1-based for convenience

    # K = np.delete(K, remove, axis=0)
    # K = np.delete(K, remove, axis=1)
    K = K[:8, :8]
    F = np.delete(F, remove, axis=0)
    S = np.delete(S, remove, axis=1)

    # solve for deflections
    d = algopy.solve(K, F)

    # compute stress
    stress = algopy.dot(S, d).reshape(nbar)

    return mass, stress