Beispiel #1
0
def steepest_descent(A, b, x_init=None, M=10000, ε=10e-10, check_spd=True):        
    """
    finds a solution to the linear system Ax = b via steepest descent

    inputs:
        A is an nxn SPD matrix
        b is an n x 1 vector
        x0 is the initial estimate vector (nx1) (default is zero vector)
        M is max number of iterations (default 10000)
        ε is machine precision (default .0001)
        if check_spd, the program will fail in the event that the system is not
        spd

    note:
    -   uses size of || x_{k+1} - x_k ||_2^2 as stopping condition 
    -   please don't break this code with weird stuff (more testing needed)
    """

    if not spd(A):
        raise Exception("""
                A must be positive definite!
                pass check_spd=False to bypass""")

    # initialize x_0 as zero vector if one wasn't provided
    if x_init is None:
        x = np.zeros_like(b, np.float)
    else:
        x = x_init

    for k in range(M):
        v = b - A.dot(x)
        u = A.dot(v)
        t = v.T.dot(v) / u.T.dot(v)
        x, x_old = ( x + t*v , x)
        
        x_change = norm(x-x_old) 
        
        if x_change < ε:
            break
        #print(locals())    
        #input('...')

    else:
        print('warning: exhausted max iterations (M={})'.format(M))
  
    summary = "terminated in {} iterations (out of M={}) with tolerance ε={}".format(k+1, M, ε)
    
    print(summary)
    return x
Beispiel #2
0
def conjugate_gradient(A, b, M=10000, x=None, tol=10e-10, check_spd=True):
    """
    conjugate gradient solution of Ax = b

    INPUTS
    A:  a nxn array representing a symmetric positive definite matrix
    b:  a nx1 array 
    M:  max iterations to run (see below) 
    x:  a starting guess (default is zero vector)
    tol:    tolerance (used for stopping condition)
    check_spd:  pre-check that A is in fact symmetric positive definite

    OUTPUT
    x:      the approximate solution to the system Ax=b

    NOTES:

    -   M should be superfluous; theoretically this method with terminate
    successfuly in n == b.size iterations, provided A is s.p.d. No such
    guarantee is made if A is not s.p.d.
    -   Similarly, a starting guess of x=0 is typically desired, as it minimizes
    computational error.
    -   If A is not symmetric positive definite and check_spd==True, then a
        generic Exception will be thrown, terminating execution.
    """
   
    assert A.shape[1] == b.shape[0], "system doesn't match"
    
    if not spd(A):
        raise Exception("""
            A is not positive definite; aborting.
            pass check_false=False to bypass""")

    # set an initial guess or check inputted
    if x is None:
        x = np.zeros_like(b) # creates an nx1 zero vector
    else:
        assert x.shape == b.shape, "system doesn't match"

    r = b - A.dot(x)
    c = vdot(r,r)
    v = r

    for i in range(M):

        if np.sqrt(c) < tol:
            print("tolerance reached!")
            break

        u = A.dot(v)
        alpha = c / (u.T.dot(v))
        x = x + alpha*v
        r = r - alpha*u
        d = vdot(r,r)
        
        if np.sqrt(d) < tol:
            print("tolerance reached!")
            break
        else:
            v = r + (d/c)*v
            c = d

    else:
        print("max ({}) iterations exhausted".format(i+1))
    
    print("finished in {} iterations".format(i))

    return x