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
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
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
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