0% found this document useful (0 votes)
10 views22 pages

COL100-Lecture 15 Lists As Polynomials

The document discusses various representations and operations for polynomials and matrices, including scalar multiplication, addition, and multiplication of polynomials in both little-endian and big-endian formats. It also covers sparse representations of polynomials and matrix operations such as addition, transposition, and dot product. Additionally, it includes exercises to reinforce understanding of the concepts presented.

Uploaded by

Jadugar Chirag
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views22 pages

COL100-Lecture 15 Lists As Polynomials

The document discusses various representations and operations for polynomials and matrices, including scalar multiplication, addition, and multiplication of polynomials in both little-endian and big-endian formats. It also covers sparse representations of polynomials and matrix operations such as addition, transposition, and dot product. Additionally, it includes exercises to reinforce understanding of the concepts presented.

Uploaded by

Jadugar Chirag
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

Polynomials

and
Matrices
Representing Polynomials as lists
Representation: Little Endian and “dense”

A list L = [ a0, a1, …, am] represents the polynomial


p(x) = a0 + a1.x + … + am.xm

• A polynomial p(x) in x of degree m represented as a list with m+1 terms


• The polynomial p(x) == 0 is represented as
zeroPoly = [ ]
• It can also be represented as [ 0 ]
Scalar multiply a polynomial p(x) by a constant c

def scalarMultPoly(L, c):


# INPUT list L == [a0,…,am] represents a0 + a1.x + … + am.xm
# OUTPUT L3 represents c * p(x)
return [ c * x for x in L ]

Exercise: Check that len(scalarMultPoly(L, c)) == len(L)


Exercise: Write a simple O(n) function eval(L, a) which
evaluates polynomial p(x) represented by L, at value x == a using a loop
Adding Polynomials
def addPoly(L1,L2):
# Little-Endian
# INPUT list L1==[a0,…,am] represents p1 == a0 + a1.x + … + am.xm
# INPUT list L2==[b0,…, bn] represents p2 == b0 + b1.x + … + bn.xn
# OUTPUT L3 represents p1 + p2
m1, n1 = len(L1), len(L2) # m1 == m+1, n1 == n+1
shorter = min(m1,n1)
L3 = [ ] # initialisation
# INVARIANT forall j: 0 ≤j < i, L3[j] = L1[j] + L2[j]
for i in range(0,shorter): # for successive i from 0 to shorter-1
L3.append(L1[i] + L2[i]) # add the corresponding coeffs
# EXIT i == shorter,
# Copy across remaining coefficients
if m1 < n1:
for i in range(m1,n1):
L3.append(L2[i])
else:
for i in range(n1,m1):
L3.append(L1[i])
return L3 # O(max(m,n)) == O(m+n)
Properties of Polynomial Addition
Exercise: Check that len(addPoly(L1, L2)) == max(len(L1), len(L2))
Exercise: Check that
addPoly(L, zeroPoly) == L == addPoly(zeroPoly, L)
Exercise: Check that addPoly(L1, L2) == addPoly(L2, L1)
Exercise: Check that
addPoly(addPoly(L1, L2),L3) == addPoly(L1, addPoly(L2, L3))

An additive inverse of a polynomial p(x) is a polynomial q(x) such that


p(x)+ q(x) = 0

def addInverse(L):
# INPUT list L==[a_0,…,a_m] represents p == a0 + a1.x
+ … + am.xm
# OUTPUT represents - p(x)
return [ - x for x in L ]
Canonical Forms
zeroPoly can also be represented as [ ] or [ 0 ]
• or as [0, 0] or [0, 0, 0 ] or …
Convert a polynomial into canonical form, with no trailing zeroes:
L==[a_0,…,a_m] where am =/= 0

def makeCanonical(L):
m = len(L)
i = m-1 # start from the highest coeff
highzero = True
while (i >= 0) and highzero: # Repeatedly
if (L[i] == 0):
del L[i] # delete redundant trailing zero
i -= 1
else:
highzero = False # stop at non-zero coefficient

Exercise: Check that


makeCanonical(addPoly(L,addInverse(L))) == zeroPoly
Multiplying Polynomials
def multPoly(L1,L2):
# INPUT list L1==[a0,…,am] represents p1 == a0 + a1.x + … + am.xm
# INPUT list L2==[b0,…, bn] represents p2 == b0 + b1.x + … + bn.xn
# OUTPUT L3 represents p1 * p2
m, n =len(L1), len(L2)
L3 = [ ]
if n>0:
# multiply L1 by lowest term of L2
L4 = [ L2[0] * x for x in L1 ]
# recursively call multiply on L1 with remaining L2 terms
L5 = multPoly(L1,L2[1:n])
# shift the entire L5 by one place to the right
L5.insert(0,0)
# add L4 to the shifted L5
L3 = addPoly(L4,L5)
return L3
Properties of Polynomial Addition

Exercise: What is len(multPoly(L1, L2))?


Exercise: Check that
multPoly(L, zeroPoly) == zeroPoly == addPoly(zeroPoly, L)
Exercise: Check that multPoly(L1, L2) == multPoly(L2, L1)
Exercise: Check that
multPoly(multPoly(L1,L2),L3) == multPoly(L1,multPoly(L2,L3))

What is the identity element onePoly of multPoly?

A multiplicative inverse of a non-zero polynomial p(x) is a polynomial q(x) such


that
p(x) * q(x) = 1

Exercise: Think about how to define multInverse(L)


Big-Endian Representation of Polynomials
Representation 2: Big Endian and “dense”

A list L = [ am, a1, …, a0] represents the polynomial


p(x) = am.xm + … + a1.x + a0

• A polynomial p(x) in x of degree m represented as a list with m+1 terms


• The polynomial p(x) == 0 is represented as
zeroPoly = [ ]

Scalar multiply a polynomial p(x) by a constant c is the same:

def scalarMultPolyB(L, c):


# INPUT list L == [a0,…,am] represents a0 + a1.x + … + am.xm
# OUTPUT L3 represents c * p(x)
return [ c * x for x in L ]

So is addInverse:

def addInverseB(L):
# INPUT list L==[a_m,…,a_0] represents p == am.xm + … + a1.x + a0
# OUTPUT represents - p(x)
return [ - x for x in L ]

Exercise: Check that len(scalarMultPoly(L, c)) == len(L)


Adding Big-Endian Polynomials

def addPolyB(L1,L2):
# Big-Endian
# INPUT list L1 == [a_m,…,a_0] represents p1 == am.xm + … + a1.x + a0
# INPUT list L2 ==[b_n,…, b_0] represents p2 == bn.xn + … + b1.x + b0
# OUTPUT L3 is the representation of p1 + p2
m, n =len(L1), len(L2)
diff = abs(m-n)
L3 = [ ]
if m < n:
for i in range(0,diff):
L3.append(L2[i])
for i in range(diff,n):
L3.append(L1[i-diff] + L2[i])
else:
for i in range(0,diff):
L3.append(L1[i])
for i in range(diff,m):
L3.append(L1[i] + L2[i-diff])
return L3
Big_Endian Canonical Forms
Convert a polynomial into canonical form, with no leading zeroes:
L==[a_m,…,a_0] where am =/= 0

def makeCanonicalB(L):
m = len(L)
i = 0 # start from the highest coeff
highzero = True
while (i < m) and highzero: # Repeatedly
if (L[0] == 0):
# Note: del modifies L by deleting elem at index
del L[0] # delete redundant leading zero coif
i += 1
else:
highzero = False # stop at first non-zero
coefficient

Exercise: Check that


makeCanonicalB(addPolyB(L,addInverseB(L))) == zeroPoly
Multiplying Big-Endian Polynomials
Similar

def multPolyB(L1,L2):
# Big-Endian
# INPUT L1 == [a_m,…,a_0] represents p1 == am.xm + … + a1.x + a0
# INPUT L2 ==[b_n,…, b_0] represents p2 == bn.xn + … + b1.x + b0
# OUTPUT L3 is the representation of p1 * p2
m, n =len(L1), len(L2)
L3 = [ ]
if n>0:
# multiply L1 by lowest term of L2
L4 = [ L2[n-1] * x for x in L1 ]
# recursively call multiply on L1 with remaining L2 terms
L5 = multPoly(L1,L2[0:n-1])
# shift the entire L5 by one place here at end
L5.append(0)
# add L4 to the shifted L5
L3 = addPolyB(L4,L5)
return L3
Evaluating Big-Endian Polynomials

Horner’s Rule

def hornerB(L, x):


# Big-Endian
# INPUT L1 == [a_m,…,a_0] represents p1== am.xm + … + a1.x +
a0
# OUTPUT ans == value of p at x
m1 = len(L) # m1 = m+1
ans = 0
# INVARIANT: ans = Sum(0≤j<i) L[j].xi-j
for i in range(0,m1):
ans = ans * x + L[i]
return ans
Sparse Representation of Polynomials
Representation 3: “Sparse” (and Big-Endian)

Consider p(x) = x1000 + 4x + 3


The earlier representations contain many zero coefficients. Inefficient.
Use instead a list L = [ (1, 1000), (4,1), (3,0)]

[ (a_i, i) | a_i =/= 0 ]


Elements are (coeff, exponent)
coeff is not zero
Sorted on exponent, i.e, second component of the elements
Big-endian representation (Little endian also possible)

zeroPoly = [ ]
Scalar multiply a polynomial p(x) by a constant c is the same code
So is the code for addInverse

Exercise: Check that len(scalarMultPolyS(L, c)) == len(L)


Exercise: Check that len(addInvS(L)) == len(L)
Addition of Sparse Polynomials
def addPolyS(L1, L2):
# INPUT L1 sparse representation of polynomial p1
# INPUT L2 sparse representation of polynomial p2
# Output L3 sparse representation of polynomial p1+p2
L3 = [ ]
m, n = len(L1), len(L2)
i, j = 0, 0
while (i < m) & (j < n): # traverse both lists, like in merge
ai, ei = L1[i] # get coeff and exponent of ith term in p1
bj, ej = L2[j] # get coeff and exponent of jth term in p2
if ei > ej # exponent ei is higher than exponent ej
L3.append(L1[i]) # include ith term of p1
i += 1
elif ei < ej: # exponent ej is higher than exponent ei
L3.append(L2[j]) # include jth term of p2
j+= 1
else: # Both have the same ei == ej
ck = ai+bj
if (not (ck == 0)): # if the sum of coeffs is 0, drop the term
L3.append( (ck, ei) )
i += 1 # advance indices on both lists
j += 1
if (i == m): # copy over terms left over from p2
while (j < n):
L3.append(L2[j])
j+= 1
else: # copy over terms left over from p1
while (i < m):
L3.append(L1[i])
i += 1
return L3
Matrices
Matrices as lists of lists
Representation:
[
[ x11, ….. , x1n ]
[ x21, ….. , x2n ]
: : :
[ xm1, ….. ,xmn ]
]

m rows and n columns


Note: All the rows must be of the same length n.
What if m = 0? n = 0?

Creating a matrix with all entries equal to k

def createM(m,n,k):
if m == 0:
return [ ]
else:
R = [ ] # initialisation of a row
for j in range(0,n):
R.append(k) # k appears in each of the n positions
M = [ ]
for i in range(0,m):
r = R.copy() # fresh copy of the row; avoid shared refs
M.append(r) # copy of R appears as each of the m rows
return M
Identity Matrix
Representation:
[
[ 1, 0,….. , 0 ]
[ 0, 1,….. , 0 ]
: : :
[ 0, 0,….. , 1 ]
]

Creating the Identity matrix

def createI(m):
if m == 0:
return [ ]
else:
M = [ ] # initialisation
for i in range(0,m):
R = [ ] # a different R each time
for j in range(0,m):
if i==j:
R.append(1)
else:
R.append(0)
r = R.copy() # can we directly append R?
M.append(r)
return M
Dimensions of a Matrix
Well-formedness: Need to check if all rows are the same length.
def dim(M):
if M==[ ]:
return(True, 0,0)
else:
m = len(M) # number of rows
n = len(M[0]) # number of cols in 1st row
proper = True
i = 0
while proper and i < m:
if len(M[i]) == n: # row has n columns
i += 1
else: # row has =/= n columns
proper = False
return(proper, m, n)
Addition of Matrices

def addM(M1, M2):


proper1, m1, n1 = dim(M1) # get dimensions of M1
proper2, m2, n2 = dim(M2) # get dimensions of M2
# if the dimensions match…
if (proper1 & proper2) and (m1==m2) and (n1==n2):
M3 = createM(m1,n1, 0) # create a mxn matrix
for i in range(0,m1):
for j in range(0,n1):
M3[i][j] = M1[i][j] + M2[i][j] # add corr. entries
return(True, M3)
else:
return(False, [ ])
Transposing Matrices

def transposeM(L):
proper, m, n = dim(L) # get dimensions
if proper:
A = createM(n,m,0) # create a n x m matrix
for i in range (0,m):
for j in range (0,n):
A[j][i] = L[i][j]
return(True,A)
else:
return (False, [ ])
Dot Product of two Vectors

def dotprod(L1, L2):


# INPUT L1, L2 two n-dim vectors
# OUTPUT Sum of products of corr. entries
n1, n2 = len(L1), len(L2)
if n1 == n2: # Both should be of the same length
ans = 0
# INVARIANT ?
for i in range(0,n1):
ans += L1[i] * L2[i]
return(True, ans)
else:
return (False, 0)
Multiplying Matrices
def multM(M1, M2):
# INPUT M1 is a m1 x n1 matrix
# INPUT M2 is a m2 x n2 matrix
# OUTPUT A = M x N
proper1, m1, n1 = dim(M1)
proper2, m2, n2 = dim(M2)
# If the dimensions match i.e., n1 == m2
if (proper1 & proper2) and (n1==m2):
A = createM(m1, n2, 0) # create a m1 x n2 matrix
_, B = transposeM(M2) # easier to transpose
for i in range(0,m1):
for j in range (0,n2):
_, A[i][j] = dotprod(M1[i], B[j])
return(True, A)
else:
return(False, [ ])

You might also like