Sympy Assignment Help | Linear Algebra Assignment Help Using Sympy

In this task, you will become familiar with the Sympy library for linear algebra. A library is a collection of functions, methods, and objects that allow us to create and manipulate vectors and matrices. Sympy is the library that contains these items to assist us in doing so.


Getting Started Libraries need to be loaded and are not standard when opening Python. This is due to the nature of memory and allocation of computer resources. If Python were to automatically load every package in existence, your computer would likely crash. We import a library by using the import command. The "as" portion allows us to simplify the name of the library so that, when we call it, we can use sp instead of spelling out numpy each time. sp is just a name. We could, in theory, call it abc, but then it would be harder to remember.


import sympy as sp

# The commands below are not important to understand - they make the matrices display nicely in the lines that follow.
from sympy.interactive.printing import init_printing
init_printing(use_unicode=False, wrap_line=False, no_global=True)
from sympy.matrices import *


We are now ready to use the Sympy library features. We wish to create a matrix that contains two rows: the first one will contain elements 1 and 2 and the second will contain elements 3 and 4. Since creating a matrix requires calling the Matrix() function, and since this function is native to the Sympy library, we need to tell Python to look for it in the Sympy library. To do this, we simply type sp.Matrix(). If we omit sp, then we will get an error, since the function cannot be found in the standard Python libraries. Take careful note of the use of brackets: the outer brackets start the matrix. Each row is created by []. Within those brackets, we type the elements, separated by commas. We separate each row block by commas. So, one row will be [1, 2] and the other will be [3, 4]. To put this in a matrix, we would need [ [1,2], [3,4] ], as shown below. We store this matrix in a variable called 𝑋X so that we can perform manipulations on the matrix. We also create matrices called 𝑌Y and 𝑍Z so that we can perform operations on them.


Example

X = sp.Matrix( [ [1,2],[3,4] ] )
X # Show X

Output:

[1 2

3 4]


Y = sp.Matrix( [ [5,6],[7,8] ] )
Z = sp.Matrix( [ [1], [7] ] )

Matrix Features and Operations First, we can check to see the size of a matrix by using the .shape attribute. If we type X.shape, we will get back its size. Notice that we called this an attribute instead of a function. This is because we are not performing any operations on the matrix. Instead, we wish only to get its attribute - namely, its size.


print(X.shape)
print(Y.shape)
print(Z.shape)

Output:

(2, 2)
(2, 2)
(2, 1)

The tuples (ordered pairs) above are useful to see, but we may need to know, for instance, the number of rows that a matrix has so that we can execute some task accordingly (knowing how many rows to add or remove from a matrix, for example). You can access the components of a tuple via indexing. An ordered pair has two indices. The first is for the first element. For example, if you have an ordered pair (7,5), that represents the shape of a 7 x 5 matrix, 𝑋X, and you want to know how many rows this matrix has (it has 7), you can access the 7 by calling X.shape[0] (recall that Python starts with an index of 0). To access the 5, we would type X.shape[1],. Both of these calls will return a single value.


B = sp.Matrix( [ [1,7,3,5], [2,4,6,10] ] )
print(B.shape)

Output:

(2, 4)

B.shape[0] # Returns 2, the number of rows in matrix B

Output: 2


B.shape[1] # Returns 4, the number of columns in matrix B

Output: 4



Performing matrix arithmetic

Performing matrix arithmetic is quite simple. Below, we scale 𝑍Z by a factor of 3 and then add 𝑋X and 𝑌Y and then attempt to add 𝑌Y and 𝑍Z (this will return a strange matrix, which is not consistent with what we know about linear algebra - addition of matrices requires matrices of equal size).


#Mulitply Matrix
3*Z

Output:

[3

21]


#Adding Two Matrix
X+Y

Output:

[6 8

10 12]



Transpose a Matrix or Vector

Sometimes it becomes handy to transpose a matrix or vector. For a vector, this simply means taking a column vector and turning it into a row (or vice versa). For a matrix, this means we take the first row and turn it into the first column of the new matrix, the second row into the second column, etc. To do this we use the T attribute.


X = sp.Matrix([[1,2],[3,4]])
X

X.T

We can also create matrices filled with desired values. There are two useful functions: zeros() and ones().

zeros() takes two dimensions as an argument and outputs a matrix of that size (rows, columns) filled with zeros.

ones() takes the same type of argument, but fills the matrix with ones.


sp.zeros(3,3)
sp.ones(4,3)

What if we want to fill the matrix with, say, 2.4's? We can create a ones matrix and multiply it by the scalar 2.4.


sp.ones(4,3)*2.4

From time to time, it will be handy to create a matrix filled with random values between 0 and 1. Run the cell below a few times to see it generate different 3 x 2 matrices.


sp.randMatrix(3,2)



Turning Vectors into a Matrix

As you will see later on in this course, it will be handy to take a set of vectors and to then form a matrix out of them. In this example, we first define three vectors, each of which is a single column of three values (a 3 x 1):


x1 = sp.Matrix([[1],[2],[3]])
x2 = sp.Matrix([[4],[5],[6]])
x3 = sp.Matrix([[7],[8],[9]])

x1, x2, x3

If we want these vectors to form individual columns of a new matrix, we want to stack them horizontally. The function row_join() will attach matrices to some initial matrix (x1) another matrix. We can have multiple row_join() calls in one line.


x1.row_join(x2).row_join(x3)

If we want to save this as a new matrix, we simply assign it to a new variable.



X = x1.row_join(x2).row_join(x3)

X

Less obviously, we might wish for these vectors to get stacked vertically, so they form one long vector (9 x 1). We use the col_join() function to do this.


x1.col_join(x2).col_join(x3)

There are many instances in which we wish to extract a particular row, column, or individual element of a matrix. We can use a similar process as when we wanted to extract a single element from an ordered pair. A matrix has two indices: one for the rows and another for the column. If we have a matrix, 𝑋X, and we want the element in the third row and fourth column, we would type X[2,3]. Why 2 and 3? Recall that the first row is row 0 and that the first column is column 0. The third row would be row value 2 and the fourth column would be the column value 3.


X=sp.Matrix([ [1,2,3,5],[3,4,-1,2],[0,2,1,-6] ])

X
print( X[2,3] ) # Returns the bottom-right element of this matrix

Output:

-6


To access an entire row, say row 3, we need to tell Python that we would like all columns for that particular row. To do this, we use a colon.

X[2,:] # Returns "all" columns for row 3

Output:

[0 2 1 −6]



Similar logic holds for returning column 4:

X[:,3] # Returns "all" rows for column 4

output:

[5

2

−6]



Gaussian Elimination


Suppose we have the system of equations below that we want to solve:


Suppose we have the system of equations below that we want to solve:

𝑥+𝑦=10 2𝑥−𝑦=14


We can create the matrix representation of this system and then run the rref() (stands for reduced-row echelon form).


A = sp.Matrix( [ [1, 1, 10], [2, -1, 14] ])
A

Output:

[1 1 10

2 -1 14]



A.rref() # The tuple (0,1) is not of importance to us

Output:




We see that x=8 and y=2 solves this system.



Changing the Rows and Columns of a Matrix


Sometimes we want to add or delete rows or columns from a matrix. First off, we present a shorthand way to access a certain row or column.


X = sp.Matrix( [ [1, 2, 3], [4, 5, 6] ])
X

Output:

[1 2 3

4 5 6]


Simply using the .row() or .col() functions on a matrix will return the desired row. For instance, to get the 2nd row and 1st column of 𝑋X:


X.row(1)

Output:

[4 5 6]


X.col(0)

Output:

[1

4]


To delete a row or column, we use the .row_del() and .col_del() functions on a matrix, respectively.


Y = sp.Matrix( [ [1,2,3], [4,5,6], [7,8,9] ] )
Y

Output:

[1 2 3

4 5 6

7 8 9]


Y.col_del(1)
Y

Output:

[1 3

4 6

7 9]



Problem 1

The function below is to calculate the total prices for various initial prices given in a matrix called P. Imagine P represents a table of prices for, maybe various products (rows) and their various attributes (columns). We wish to first apply a discount, given by the matrix D, a matrix that is the same size as 𝑃P but that contains the discount for the corresponding product price in P. Finally, a tax rate of t% is to be applied to these discounted rates. The output should be a matrix, T, containing the total prices after discount and tax. Note that t is a percentage and so it will need to be converted into decimal form.


Solution:

def total_price(P,D,t):
    T1  = (P-D)
    T2 = T1 * (t/100)
    T = T1 +T2
    return T
P = sp.Matrix([[45,27,48],[39,44,27]])

D = sp.Matrix([[5,4,8],[2,3,4]])


Test:

t = 8.25
print(total_price(P,D,t).evalf(4))

Output: Matrix([[43.30, 24.90, 43.30], [40.05, 44.38, 24.90]])


Problem 1.) Code Test If your total_price() function is working properly, you should get the corresponding outputs below for each of the input calls shown. Note that you can copy/paste the input into a new code box and run it on each set of inputs. ################################################### P = sp.Matrix([[45,27,48],[39,44,27]]) D = sp.Matrix([[5,4,8],[2,3,4]]) t = 8.25 print(total_price(P,D,t).evalf(4)) # .evalf(4) rounds values to 4 significant digits OUTPUT: Matrix([[43.30, 24.90, 43.30], [40.05, 44.38, 24.90]]) ################################################### P = sp.Matrix([[17,20,17],[8,41,36]]) D = sp.Matrix([[1,2.5,4.1],[3.1,7.6,4.9]]) t = 7.5 print(total_price(P,D,t).evalf(4)) OUTPUT: Matrix([[17.20, 18.81, 13.87], [5.268, 35.90, 33.43]]) ################################################### P = sp.Matrix([[8,7],[3, 2],[10, 12]]) D = sp.Matrix([[1,2.1],[.5, .1],[1, 1.2]]) t = 8 print(total_price(P,D,t).evalf(4)) OUTPUT: Matrix([[7.560, 5.292], [2.700, 2.052], [9.720, 11.66]]) ###################################################



Problem 2

It is sometimes the case that a matrix of data is not oriented properly. That is to say, maybe you want the rows to be columns. Suppose you have an m x p matrix, A, that you need to add to a data matrix, D. However, suppose that D is p x m, and so it needs to be transposed before you can apply A to it. Complete the function below, so that the two input matrices get added correctly to form a final matrix, F, that is m x p.


def add_to_data(A,D):
    D = D.T
    F = A + D
    return F


A = sp.Matrix( [ [1,3,4],[2,8,-4] ] )

D = sp.Matrix( [ [4,5],[3,7],[2,1] ] )

#D.T
print(add_to_data(A,D))

Output: Matrix([[5, 6, 6], [7, 15, -3]])


A = sp.Matrix( [ [2,4,1],[1.2,3.7,-4.6], [1,2,3], [3,4,3] ] )

D = sp.Matrix( [ [4,5,3,2],[3,7,1,7],[2,1,-3,1] ] )

print(add_to_data(A,D).evalf(2))

Output: Matrix([[6.0, 7.0, 3.0], [6.2, 11., -3.6], [4.0, 3.0, 0], [5.0, 11., 4.0]])



Problem 2.) Code Test

If your add_to_data() function is working properly, you should get the corresponding outputs below for each of the input calls shown. Note that you can copy/paste the input into a new code box and run it on each set of inputs. ################################################### A = sp.Matrix( [ [1,3,4],[2,8,-4] ] ) D = sp.Matrix( [ [4,5],[3,7],[2,1] ] ) print(add_to_data(A,D)) OUTPUT: Matrix([[5, 6, 6], [7, 15, -3]]) ################################################### A = sp.Matrix( [ [2,4,1],[1.2,3.7,-4.6], [1,2,3], [3,4,3] ] ) D = sp.Matrix( [ [4,5,3,2],[3,7,1,7],[2,1,-3,1] ] ) print(add_to_data(A,D).evalf(2)) OUTPUT: Matrix([[6.0, 7.0, 3.0], [6.2, 11., -3.6], [4.0, 3.0, 0], [5.0, 11., 4.0]]) ###################################################



Problem 3

Here you will write a function that accepts a matrix, X, that is m x p and a constant, c. In some applications it is necessary to construct a matrix filled with a constant that is the same size as another matrix, X, for example. The function should determine the size of X, and should output a matrix, B, that is the same size as X and that is filled with the constant, c, that is passed to the function.


def fill_matrix(X, c):
    B = sp.ones(X.shape[0],X.shape[1])
    B = B * c
    return B

X = sp.Matrix( [ [1,3,4],[2,8,-4] ])
print(fill_matrix( X , 3))

Output: