0% found this document useful (0 votes)
2 views60 pages

15 Algorithm Analysis

Chapter 4 discusses algorithm analysis, focusing on how to determine the efficiency of algorithms through execution time and complexity analysis. It introduces Big-O notation to classify algorithms by their growth rates and provides examples of different algorithm complexities. The chapter also evaluates Python code efficiency and highlights the importance of understanding different cases of algorithm performance.

Uploaded by

Rengin Ozder
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)
2 views60 pages

15 Algorithm Analysis

Chapter 4 discusses algorithm analysis, focusing on how to determine the efficiency of algorithms through execution time and complexity analysis. It introduces Big-O notation to classify algorithms by their growth rates and provides examples of different algorithm complexities. The chapter also evaluates Python code efficiency and highlights the importance of understanding different cases of algorithm performance.

Uploaded by

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

Algorithm Analysis Chapter 4

© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Algorithms

⚫ Algorithms are designed to solve problems.


⚫ A problem can have multiple solutions.

How do we determine which


solution is the most efficient?

Chapter 4: Algorithm Analysis –2


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Execution Time
⚫ Measure execution time:
⚫ construct a program for a given solution.
⚫ execute the program.
⚫ time it using a “wall clock”.

⚫ Dependent on:
⚫ amount of data
⚫ type of hardware and time of day
⚫ programming language and compiler

⚫ Analyse an algorithm’s efficiency independent of


the implementation details
Chapter 4: Algorithm Analysis –3
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Complexity Analysis

⚫ What if we examine the solution itself and


measure critical operations:
⚫ logical comparisons
⚫ assignments
⚫ arithmetic operations

Chapter 4: Algorithm Analysis –4


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Example Algorithm

⚫ Given a matrix of size n x n, compute the:


⚫ sum of each row of a matrix.
⚫ overall sum of the entire matrix.

Chapter 4: Algorithm Analysis –5


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.

© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Compare the Results

⚫ Number of additions: v1: 2n2 v 2: n 2 + n


⚫ Second version has fewer additions (n > 1)
⚫ Will execute faster than the first.
⚫ Difference will not be significant.

Both algorithms execute on the


same order of magnitude, n2

Chapter 4: Algorithm Analysis –7


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Growth Rates

⚫ As n increases, both algorithms increase at approx


the same rate:

n 2n2 n2 + n
10 200 110
100 20,000 10,100
1000 2,000,000 1,001,000
10,000 200,000,000 100,010,000
100,000 20,000,000,000 10,000,100,000

Chapter 4: Algorithm Analysis –8


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Growth Rates

Chapter 4: Algorithm Analysis –9


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Big-O Notation

⚫ No need to count precise number of steps.


⚫ Classify algorithms by order of magnitude.
⚫ execution time
⚫ space requirements

Approximates actual number of


steps or actual storage in terms
of variable-sized data sets.

Chapter 4: Algorithm Analysis –10


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Big-O Definition

⚫ Given a function T(n)


⚫ # of steps required for an input of size n.
⚫ Ex: T2(n) = n2 + n

⚫ Suppose there exist a function f(n) for all


integers n > 0 such that
T(n) < c f(n)

for some constant c and for all large values of n

Chapter 4: Algorithm Analysis –11


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Big-O Definition

⚫ Then, the algorithm has a time-complexity of or


executes “on the order of” f(n)
⚫ We use the notation: O( f(n) )
⚫ Big-O is intended for large values of n.

f(n) indicates the rate of growth


at which the run time increases
as the input size increases.

Chapter 4: Algorithm Analysis –12


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Big-O Example (v.1)

⚫ Consider the previous sample algorithms.


⚫ Version 1: T1(n) = 2n2

T1(n) < c f(n) Let c = 2


2n2 < 2n2

O( n2 )

Chapter 4: Algorithm Analysis –13


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Big-O Example (v.2)

⚫ Consider the previous sample algorithms.


⚫ Version 2: T2(n) = n2 + n

T2(n) < c f(n) Let c = 2


n2 + n < n2 + n 2
n2 + n < 2n2

O( n2 )

Chapter 4: Algorithm Analysis –14


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Upper Bound

⚫ There is more than one f(n) for an algorithm.


n2 + n < c f(n)
⚫ n2 is not the only choice
⚫ f(n) could be n2, n3, n4

Objective: find an f(n) that


provides the tightest (lowest)
upper bound.

Chapter 4: Algorithm Analysis –15


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Constant of Proportionality

⚫ Is it important?
⚫ Consider two algorithms:
⚫ O(n2), with c = 1
⚫ O(2n), with c = 2

n n2 2n
10 100 20
100 10,000 200
1000 1,000,000 2,000
10,000 100,000,000 20,000
100,000 10,000,000,000 200,000 50K more operations

Chapter 4: Algorithm Analysis –16


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Constant of Proportionality

Chapter 4: Algorithm Analysis –17


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Constructing T(n)

⚫ We don't count total number of specific


instructions (math operations, comparisons, etc)
⚫ Assume each basic statement takes the same time,
constant time.
⚫ Total number of steps required:

T(n) = f1(n) + f2(n) + ... + fk(n)

Chapter 4: Algorithm Analysis –18


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Choosing the Function

⚫ Given T(n), choose the dominant term.

T(n) = n2 + log2n + 3n

n2 dominates the other terms (for n > 3)

n2 + log2n + 3n < n2 + n2 + n2
n2 + log2n + 3n < 3n2

Chapter 4: Algorithm Analysis –19


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Choosing the Function

⚫ What is the dominant term for the following


expression?

T(n) = 2n2 + 15n + 500

When n < 16, 500 dominates.


When n > 16, n2 is the dominate term.

Chapter 4: Algorithm Analysis –20


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Classes of Algorithms

⚫ Many algorithms have a time-complexity selected


from a common set of functions.

f() Common Name


1 constant
log n logarithmic
n linear
n log n log linear
n2 quadratic
n3 cubic
an exponential

Chapter 4: Algorithm Analysis –21


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Classes of Algorithms

Chapter 4: Algorithm Analysis –22


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Evaluating Python Code

⚫ Basic operations only require constant time:


⚫ x = 5
⚫ z = x + y * 6
⚫ if x > 0 and x < 100

⚫ What about function calls?


y = ex1(n)

Chapter 4: Algorithm Analysis –23


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #1
def ex1( n ):
count = 0
for i in range( n ):
count += i
return count

O(n)

Chapter 4: Algorithm Analysis –24


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #2

def ex2( n ):
count = 0
for i in range( n ):
count += 1
for j in range( n ):
count += 1
return count

O(n)
Chapter 4: Algorithm Analysis –25
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #3

def ex3( n ):
count = 0
for i in range( n ):
for j in range( n ):
count += 1
return count

2
O(n )
Chapter 4: Algorithm Analysis –26
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #4
def ex4( n ):
count = 0
for i in range( n ):
for j in range( 25 ):
count += 1
return count

O(n)
Chapter 4: Algorithm Analysis –27
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #5
def ex5( n ):
count = 0
for i in range( n ):
for j in range( i+1 ):
count += 1
return count

2
O(n )
Chapter 4: Algorithm Analysis –28
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Code Evaluation #6

def ex6( n ):
count = 0
i = n
while i >= 1 :
count += 1
i = i // 2
return count

O(log(n))
Chapter 4: Algorithm Analysis –29
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Different Cases

⚫ Some algorithms have different run times for


different sets of inputs of the same size.
⚫ best case
⚫ worst case
⚫ average case

Chapter 4: Algorithm Analysis –30


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Different Cases

def findNeg( intSeq ):


n = len( intSeq )
for i in range( n ) :
if intSeq[i] < 0 :
return i
return None

L = [ 72, 4, 90, 56, 12, 67, 43, 17, 2, 86, 33 ]


p = findNeg( L )

L = [ -12, 50, 4, 67, 39, 22, 43, 2, 17, 28 ]


p = findNeg( L )

Chapter 4: Algorithm Analysis –31


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
The Python List

⚫ We used the list to implement many of our ADTs.


⚫ Their efficiency depends on the efficiency of
Python's list.

Chapter 4: Algorithm Analysis –32


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Traversal

⚫ Iterates over the contiguous elements of the


underlying array.
# Sum the elements of a list.
sum = 0
for value in valueList :
sum = sum + value

# Alternate version.
sum = 0
n = len(valueList)
for i in range( n ) :
sum = sum + valueList[i]

Chapter 4: Algorithm Analysis –33


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Allocation

⚫ Creating a non-empty list is not constant.

temp = list()
listX = [ 0 ] * n
valueList = [ 4, 8, 20, 2, 15, 89, 60, 75 ]

Chapter 4: Algorithm Analysis –34


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Appending

⚫ When space is available, the item is stored in the


next slot.

What if the underlying


array is full?

Chapter 4: Algorithm Analysis –35


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Expansion

⚫ Expanding the underlying array:


⚫ Step 1: create a new array, double the size.
⚫ Step 2: copy the items from original array to the new array.
⚫ Step 3: replace the original array with the new array.
⚫ Step 4: store the new value the next slot of the new array.

Chapter 4: Algorithm Analysis –36


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Extending

⚫ Adds the contents of a source list to the end of the


destination list.

Chapter 4: Algorithm Analysis –37


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Python List: Time-Complexities

List Operation Worst Case


v = list() O(1)
len(v) O(1)
v=[0]*n O(n)
v[i] = x O(1)
[Link](x) O(n)
[Link](w) O(n)
[Link](x) O(n)
[Link]() O(n)
traversal O(n)

Chapter 4: Algorithm Analysis –38


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Amortized Cost

⚫ Consider a sequence of n append operations:


L = list()
for i in range( 1, n+1 ):
[Link]( i )

⚫ What is the worst-case running time?

Chapter 4: Algorithm Analysis –39


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Special Case

⚫ The append() method introduces a special case.


⚫ available capacity: O(1)
⚫ expansion required: O(n)

How many times does


append require O(n) time?

Chapter 4: Algorithm Analysis –40


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Amortized Analysis

⚫ Given a sequence of operations, compute the


time-complexity by computing the average cost
over the entire sequence.
⚫ Cost per operation must be known.
⚫ Cost must vary, with
− many ops contributing little cost.
− only a few ops contributing high cost.

Chapter 4: Algorithm Analysis –41


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Aggregate Method

⚫ Determine upper bound total cost: T(n)


⚫ Calculate average cost: T(n) / n

⚫ Example: sequence of n append operations


⚫ Storage of a single item: O(1)
⚫ Expansion only occurs when (i – 1) is a power of 2.
⚫ Cost of the expansion based on current array size.

Chapter 4: Algorithm Analysis –42


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Amortized Cost

⚫ The append() operation:


⚫ worst-case time: O(n)
⚫ amortized cost: O(1)

⚫ Can only be used for a long sequence of append


operations.

Chapter 4: Algorithm Analysis –43


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
The Sparse Matrix

⚫ A matrix containing a large number of 0 elements.


⚫ Common in scientific applications.
⚫ Formal definition:
⚫ An m x n matrix that contains k non-zero elements.
⚫ Such that k << m x n.

Chapter 4: Algorithm Analysis –44


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Data Organization

⚫ The use of a 2-D array for the Matrix ADT:


⚫ Works well for general matrices.
⚫ Wastes space for large sparse matrices.

Chapter 4: Algorithm Analysis –45


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Data Organization

⚫ Use a single list and store the non-zero elements.

Chapter 4: Algorithm Analysis –46


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix Class
[Link]

class SparseMatrix :
def __init__( self, numRows, numCols ):
self._numRows = numRows
self._numCols = numCols
self._elementList = list()

def numRows( self ):


return self._numRows

def numCols( self ):


return self._numCols
# ...

class _MatrixElement:
def __init__( self, row, col, value ):
[Link] = row
[Link] = col
[Link] = value
Chapter 4: Algorithm Analysis –47
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix: ScaleBy
[Link]

class SparseMatrix :
# ...
def scaleBy( self, scalar ):
for element in self._elementList :
[Link] *= scalar

Chapter 4: Algorithm Analysis –48


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Setting an Element

⚫ Set an element by row and column indices.


M = SparseMatrix(5, 8)
M[0,1] = 3
M[3,7] = 3
M[1,6] = 5

⚫ In the 2-D array implementation of the Matrix


class, this was easy.
⚫ For the SparseMatrix class, an element can not be
directly set.

Chapter 4: Algorithm Analysis –49


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Setting an Element

⚫ There are four possible conditions:


⚫ The element is not in the list.
− New value is not 0
− New value is 0
⚫ The element is in the list.
− New value is not 0.
− New value is 0.

Chapter 4: Algorithm Analysis –50


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix: SetItem
[Link]

class SparseMatrix :
# ...
def __setitem__( self, ndxTuple, scalar ):
ndx = self._findPosition( ndxTuple[0], ndxTuple[1] )

if ndx is not None :


if scalar != 0.0 :
self._elementList[ndx].value = scalar
else :
self._elementList.pop( ndx )

else :
if scalar != 0.0 :
element = _MatrixElement( ndxTuple[0],
ndxTuple[1], scalar )
self._elementList.append( element )

Chapter 4: Algorithm Analysis –51


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix: Find Position
[Link]

class SparseMatrix :
# ...
def _findPosition( self, row, col ):
n = len( self._elementList )
for i in range( n ) :
if row == self._elementList[i].row and \
col == self._elementList[i].col:
return i
return None

Chapter 4: Algorithm Analysis –52


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix: Addition

⚫ The same add() operation can be used.


class SparseMatrix :
# ...
def __add__( self, rhsMatrix ):
for r in range( [Link]() ) :
for c in range( [Link]() ) :
newMatrix[r,c] = self[r,c] + rhsMatrix[r,c]
return newMatrix

Chapter 4: Algorithm Analysis –53


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix Analysis

⚫ Assume a square n x n matrix with k << n x n.


⚫ constructor: O(1)
⚫ size: O(1)
⚫ scaleBy: O(k)
⚫ get/set item: O(k)
⚫ addition O(n2)

Chapter 4: Algorithm Analysis –54


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Faster Addition

⚫ We can improve the addition operation by only


considering the non-zero elements.

Chapter 4: Algorithm Analysis –55


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Faster Addition

Chapter 4: Algorithm Analysis –56


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Faster Addition

⚫ Requires 4 steps.
⚫ Verify the precondition.
⚫ Create a new SparseMatrix object.
⚫ Duplicate the elements of the self matrix.
⚫ Iterate over the rhs matrix elements and add them
to the new matrix.

Chapter 4: Algorithm Analysis –57


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
SparseMatrix: Faster Addition
[Link]

class SparseMatrix :
# ...
def __add__( self, rhsMatrix ):
assert [Link]() == [Link]() and \
[Link]() == [Link](), \
"Matrix sizes not compatible for the add operation."

newMatrix = SparseMatrix([Link](), [Link]())

for element in self._elementList :


dupElement = _MatrixElement([Link], [Link],
[Link])
newMatrix._elementList.append( dupElement )

for element in rhsMatrix._elementList :


value = newMatrix[ [Link], [Link] ]
value += [Link]
newMatrix[ [Link], [Link] ] = value

return newMatrix
Chapter 4: Algorithm Analysis –58
© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Faster Addition Analysis

⚫ Assume a square n x n matrix with k << n x n.


⚫ check precondition: O(1)
⚫ create new matrix: O(1)
⚫ Duplicate lhs: O(k)
⚫ Loop through rhs list: O(2k2)
− get item: O(k)
− set item: O(k)

Chapter 4: Algorithm Analysis –59


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.
Time-Complexity Comparisons

Operation Matrix SparseMatrix


constructor O(n2) O(1)
[Link]() O(1) O(1)
[Link]() O(1) O(1)
[Link](x) O(n2) O(k)
x = m[i, j] O(1) O(k)
m[i, j] = x O(1) O(k)
r=m+t O(n2) O(k2)

Chapter 4: Algorithm Analysis –60


© 2011 John Wiley & Sons, Data Structures and Algorithms Using Python, by Rance D. Necaise.

You might also like