In this assignment you will use Python to implement several of the vector and matrix operations and predicates we have introduced
so far.
**Please submit a single file a3.py containing your solutions.**

**Your file may not import any modules or employ any external library functions
(unless the problem statement explicitly permits this).
You will be graded on the correctness, concision, and mathematical legibility of your code.
The different problems and problem parts rely on each other; carefully consider whether you can use functions you define
in one part within subsequent parts.**

- In this assignment, we will represent vectors as Python tuples.
For example, the vector [1;2;3] would be represented in Python as
`(1,2,3)`

.- Define a Python function
`scale(s,v)`

that takes two arguments: a scalar`s`

and a vector`v`

. The function should return the result of multiplying the vector by the scalar.scale(2, (3,4,5)) # Returns (6,8,10).

- Define a Python function
`norm(v)`

that takes a vector argument`v`

and returns its norm (i.e., its length).

- Define a Python function
`dot(v,w)`

that takes two vectors as arguments and returns their dot product. If the two vectors do not have the same number of components, the function should return`None`

.

Include a comment explaining**exactly**how many addition operations and how many multiplication operations your implementation performs when the input is a pair of vectors that each have`n`

components.dot((1,2), (3,4)) # Returns 11. dot((5,1,0), (1,1,2)) # Returns 6. dot((5,1,0,4), (1,2)) # Returns None.

- Define a Python function
`orthogonal(v,w)`

that takes two vectors as arguments and returns`True`

only if the two input vectors are orthogonal to one another; if they are not orthogonal, it returns`False`

. If the two vectors do not have the same number of components, the function should return`None`

.

- Define a Python function
`proj(v,w)`

that takes two vectors as arguments and returns a vector that is the projection of`v`

onto`w`

.

- Define a Python function
- In this assignment, we will represent matrices as tuples of tuples. For example, the matrix

would be represented as1 2 3 4 `((1,2),(3,4))`

:- Define a Python function
`mult(A,B)`

that takes two matrix arguments and returns the matrix that is the result of multiplying`A`

by`B`

. If either argument is not a valid matrix, or if the two matrices cannot be multiplied because the number of rows and/or columns does not match as necessary, the function should return`None`

.

Include a comment explaining**exactly**how many addition operations and how many multiplication operations your implementation performs when the input is a pair of matrices that each have`n`

rows and columns.mult(((1,2),(3,4)), ((-5,-6),(7,8))) # Returns ((9,10),(13,14)).

- Define a Python function
`upper(A)`

that takes a matrix argument and returns`True`

only if the matrix`A`

is upper triangular; otherwise, it returns`False`

. - Define a Python function
`transpose(A)`

that takes a matrix argument and returns the transpose of that matrix. - Define a Python function
`lower(A)`

that takes a matrix argument and returns`True`

only if the matrix`A`

is lower triangular; otherwise, it returns`False`

. - Define a Python function
`symmetric(A)`

that takes a matrix argument and returns`True`

only if the matrix`A`

is symmetric; otherwise, it returns`False`

. - Define a Python function
`orthogonal(A)`

that takes a matrix argument and returns`True`

only if the matrix`A`

is orthogonal; otherwise, it returns`False`

.**You may name this function**`orthogonal2()`

if all your tests are at the end of your file and you don't want this definition to hide the definition of`orthogonal()`

from Problem #1(d) above.

- Define a Python function
- In this problem you will implement functions that can be used to generate elementary matrices corresponding to the
three types of elementary row operations.
**In matrices, the first row is indexed as**`i = 1`

(unlike tuples and lists in Python). Thus, you will need to convert the*row indices*`i`

and`j`

into the corresponding Python tuple indices.**Hint: begin with the identity matrix and apply the row operation to that matrix.**

- Define a Python function
`elementary_swap(r,c,i,j)`

. This function should take four integer arguments:`r`

is the number of rows`c`

is the number of columns;`i`

and`j`

are the two rows to swap.

`i`

with row`j`

by using matrix multiplication. See example below.mult(elementary_swap(3,3,1,3), ((1,2,3), (0,0,0), (7,8,9))) # Returns ((7,8,9), (0,0,0), (1,2,3)).

- Define a Python function
`elementary_scale(r,c,i,s)`

. This function should take four integer arguments:`r`

and`c`

are the row and column counts, respectively;`i`

is the row to scale;`s`

is the scalar to use.

`i`

using the scalar`s`

. See example below.mult(elementary_scale(2,2,2,-1), ((1,2), (3,4))) # Returns ((1,2), (-3,-4)).

- Define a Python function
`elementary_add(r,c,i,j,s)`

. This function should take four integer arguments:`r`

and`c`

are the row and column counts, respectively;`i`

is the row to add to row`j`

;`s`

is the scalar with which to scale row`i`

before adding it to row`j`

.

`s`

) of row`i`

to row`j`

. See example below.mult(elementary_add(3,3,1,2,-1), ((1,2,3), (0,0,0), (7,8,9))) # Returns ((1,2,3), (-1,-2,-3), (7,8,9)).

- Define a Python function
- Define a Python function
`is_rref(A)`

that takes a matrix argument`A`

and returns`True`

only if`A`

is in reduced row echelon form; otherwise, it returns`False`

.