Esempio n. 1
0
def matrix_eigenvalues(m):
    """
        Module B3, page 14

        This is one example of something easier with just using the libaries!
        You could just do Matrix(m).eigen_values()! m should be a sympy
        Matrix, e.g. Matrix([[0, 1], [1, 0]]).
    """

    k = symbols('k')

    # To make it clearer, lets assign out the matrix elements
    a, b, c, d = m[0, 0], m[0, 1], m[1, 0], m[1, 1]
    # See B3 page 19, equation 2.5 for this definition
    characteristic_equation = k ** 2 - (a + d) * k + (a * d - b * c)
    roots = solve(characteristic_equation)

    print "Characteristic equation:\n\n%s\n" % pp(characteristic_equation)

    if len(roots) == 1:
        # Make dupe of repeated root
        roots = roots * 2

    if roots[0].is_real:
        print "Eigenvalues: %s\n" % pp(roots)
        return roots
    else:
        # Note that the statement 'no eigenvalues' is by definition
        print "Roots are complex, no eigenvalues"
        return None
Esempio n. 2
0
def matrix_eigenlines(m):
    """
        Module B3, page 21
    """

    eigenvalues = matrix_eigenvalues(m)
    # Now make sure we've got something to work with!
    assert(eigenvalues is not None)

    # Now to work out the eignlines we use the eigenvector equation
    # Ax = kx where A is our matrix m, k is a particular eigenvalue
    # and x represents the (x, y) vector
    x, y = symbols('x, y')
    x_vector = Matrix([x, y])

    eigenlines = list()
    for eigenvalue in eigenvalues:
        # Now we evaluate Ax = kx, since we can't do a 'a = b' style expression
        # in sympy/python we subtract the right hand side so we are basically
        # skipping a small step and writing Ax - kx = 0
        equations = m * x_vector - eigenvalue * x_vector
        print "Set of equations for eigenvalue %s:\n\n%s" % (eigenvalue, pp(equations))

        # For a given eigenvalue the equations returned above both reduce
        # to the same expression, so we can pick the first one, simplify it
        # down to the lowest terms. Then we solve for y which basically
        # rearranged it into standard form. This is the eigenline equation.
        # As we're dealing with solve, we take the first (only) result
        eigenline = solve(simplify(equations[0]), y)[0]
        print "Eigenline equation for eigenvalue %s:\n\n%s\n" % (eigenvalue, pp(eigenline))
        eigenlines.append(eigenline)

    return eigenlines
Esempio n. 3
0
def matrix_eigenvector(m, line=0, x=1):
    """
        Module B3, page 22

        Returns a possible eigenvector for eigenline #line, usually by
        evaluting x = 1 but this can be changed on demand to get a
        particular eigenvector
    """
    # First we need to get the eigenlines for the matrix
    eigenlines = matrix_eigenlines(m)
    # Now evaluate the equation of the line
    val = eigenlines[line].subs({'x': x})
    # Finally the eigenvector is simply the given x value with the
    # evaluated y value from above in vector form
    eigenvector = Matrix([x, val])

    print 'Eigenvector for eigenline %s (x=%0.2f):\n\n%s\n' % (eigenlines[line], x, pp(eigenvector))
    return eigenvector
Esempio n. 4
0
def linear_second_order_recurrence(p, q, _u0, _u1):
    """
        Module A1

        Solve a second order linear recurrence step by step using the method
        in the MS221 handbook and chapter A1 of the course. Some bits here
        are more explict than they would need to be by using Sympy so that
        each step is outlined.

        Sympy has built in solvers for nth-order recurrence sequences, see
        rsolve: http://docs.sympy.org/dev/modules/solvers/solvers.html#recurrence-equtions
    """

    # Initalize our symbols we'll be using
    r, A, B, n = symbols('r, A, B, n')

    # Create a the auxillary equation first
    aux = r ** 2 - p * r - q
    roots = solve(aux)

    # We've two options for the general solution based on if the root repeats
    if len(roots) == 2:
        print "Auxillary equation solutions (a, b) = (%s, %s)" % (pp(roots[0]), pp(roots[1]))
        general_solution = A * roots[0] ** n + B * roots[1] ** n
    else:
        print "Auxillary equation repeated root a = %s" % roots[0]
        general_solution = (A + B*n) * roots[0] ** n
        # Now for ease of referencing make the repeated root a list
        roots = roots * 2

    # Could use solvers.solve_linear_system but this spells
    # out the steps of the algebra for reference as if you
    # were doing it by hand

    # Evaluate u0 and u1 by substituting for n in the general solution
    u0 = general_solution.subs({'n': 0})
    u1 = general_solution.subs({'n': 1})

    # Solve for the given inital values _u0 & _u1. Sympy will return
    # a solution in terms of the variable A, it's a list so we need
    # the first value back
    b0, b1 = solve(u0 - _u0)[0], solve(u1 - _u1)[0]

    # If the above equations have a single variable they'll be integer
    # solutions, otherwise they'll be in terms of the variable A
    if type(b0) == dict:
        b0 = b0[A]
    if type(b1) == dict:
        b1 = b1[A]

    # Now solve the two simulataeous equations to get B
    _B = solve(b0 - b1)[0]
    # And replace this into one of the initial value equations
    # to get the value of A
    _A = b0.subs({'B': _B})

    print "A: %s\nB: %s\n" % (_A, _B)

    # Finally for the specific solution we replace our general solution
    # with the found values of A & B
    solution = general_solution.subs({'A': _A, 'B': _B})

    print "Solution:\n" + "%s\n" % pp(solution)
    return (roots, _A, _B), solution