Meeting
Time: MWF 11:00am-11:50 pm Baldwin
Instructor: Fred Annexstein
Office: 889 Rhodes (
Phone: 556-1807
Email: fred.annexstein (at) uc.edu
Web: http://www.cs.uc.edu/~annexste
Course syllabus
HOMEWORK
Assignments
Item Homework #4: Due Friday March 13
1. Show that 2-coloring is in P
2. Show that 2-SAT is in P. Hint: For each clause (x v y) in the instance, we know that if the instance is satisfiable that not x implies y, and not y implies x. Build a graph based on these implications.
3. Low-Diameter Clustering problem: given n objects p1 , p2 , . . . , pn with pairwise distances between them, and a bound B, we ask can the objects be partitioned into k sets, so that no two points in the same set are at distance greater than B from one another? Prove that this problem is NP-complete (Hint: try a reduction from 3-coloring)
4. (26.16) Show that 0/1 Knapsack is NP-complete. (Hint: try a reduction from Partition)
5.(26.17) Show that Bin-Packing is NP-complete (Hint: try a reduction from SumofSubsets)
Item Homework #3: Due Monday March 2 in class
Advanced Algorithms 1 (781) --- Winter 2009
Assignment 3
Due Monday, March 2 at the beginning of the class
0. Consider the problem of finding an independent set of vertices (no pair share an edge) on a path whose weight is as large as possible. a) Show an example path that shows the greedy algorithm sometimes fails. b) Show an example path that shows that choosing the odd or even vertices on the path sometimes fails. c) Give a dynamic programming solution that always finds the optimal.
1. Write a Python program to solve the "optimal parenthesization" problem. Use your code to solve page 285, Exercise 9.7
2. Page 286, Exercise 9.10
3. Page 286, Exercise 9.15
4. Page 287, Exercise 9.17
5. Page 287, Exercise 9.20
Item Homework #2 Due Friday Feb 6 5:00PM
Do the following exercies:
1. p. 110 3.35
2. p. 111 3.49
3. p. 712 22.2
4. P. 712 22.8
5. p. 262 8.13
6. p. 234 7.14
7. p. 234 7.15
8. Formally show that if T is an optimal prefix tree with probabilities {p_1, ..., p_k},
then p_i < p_j implies that depth(message_i) >= depth(message_j)
Item Homework #1 Due in Digital Dropbox Friday Jan 16 5:00PM
CS781- Winter 2009
Homework #1 Due in Digital Dropbox Friday Jan 16 5:00PM
1. Using the definition, show that for any constant k, (n+k)^4 is O(n^4).
2. Using the definition, show that if p(n) is a polynomial in n, then log(p(n)) is O(log n).
3. Using the definition, show that for any pair of constants 0< e <1, and k>1 that n^e is Omega(log^k n)
4. Suppose you implement a vector (extendable array) in which each push_back (add) operation takes a) constant time if sufficient space is allocated or b) time proportional to the current size of the vector, if the structure is full. In class we showed that if each extention doubled the size of the vector than the cost of n push_back operations is O(n) time.
a) suppose each extension increased the size of the vector by a constant size k. What is the complexity of n push_back operations? Prove your answer.
b) suppose each extension increased the size of the vector by a number equal to ceiling of sqrt of size. What is the complexity of n push_back operations? Prove your answer is correct.
5. I am thinking of two positive integers m < n. I tell you n, and your task is to determine m. For each guess you give, I will only tell you whether m is "correct", "higher" or "lower". However, if I say "lower" two times, you have failed the task. How many guesses will you need to determine m without fail? Show that your answer is optimal up to constant factors.
6. Suppose you are given a 0/1 nxn matrix A, in which all the rows are sorted. Give an O(n) algorithm that determines the row(s) of A with the most 1s. Show that your algorithm is O(n) and not O(n^2).
7. Convert the following O(n^2) Python program to compute running statistics to a linear time algorithm
# Quadratic time for running averages and variances
def main (x):
run_avg=[]
run_var=[]
partial_sum=0
for i in range(len(x)):
partial_sum += x[i]
run_avg.append(partial_sum/(i + 1.0))
partial_sumsquares=0
for j in range(i+1):
partial_sumsquares += (x[j]-run_avg[i])**2
run_var.append(partial_sumsquares/(i+1.0))
for i in range(len(x)):
print "%5.2f , %5.2f, %5.2f" % (x[i], run_avg[i], run_var[i])
main([1,1,1,0,0,0,1,1])
>>>
1.00 , 1.00, 0.00
1.00 , 1.00, 0.00
1.00 , 1.00, 0.00
0.00 , 0.75, 0.19
0.00 , 0.60, 0.24
0.00 , 0.50, 0.25
1.00 , 0.57, 0.24
1.00 , 0.62, 0.23
LECTURE NOTES
Lecture on Polynomial Multiplication - Jan 16
FFT.pdf (632.158 Kb)
Midterm Practice Exam
Midterm-781-2009.doc (38.5 Kb)
3-coloring and NP-completeness course notes
3-coloring.pdf (439.243 Kb)
planarGraphColoring.pdf (376.529 Kb)
Approximating NPC Problems
781-NPC.htm (19.791 Kb)
781-NPC2.htm (15.244 Kb)
781-NPC3.htm (20.403 Kb)
Notes March 11- K-Center Problems and Solutions
CS781-March 11.pdf
Final Practice Exam and Topic Sheet
FInalStudy-781-2009.doc (36.5 Kb)
CODE SAMPLES
Python generators of combinatorial objects
#Python has very nice syntax for defining generators of combinatorial objects such as subsets, k-element subsets, permutations, etc.
#The syntax lends itself to be used in a natural way with "for" statements. Generators work off the "yield" construct which suspends the
#state of the function, and is continued from precisely that point when the generator.next() is called from behind the scenes of a for statement.
#Here are some example generators
#The classic Fibonacci sequence as a generator
def fib():
a, b = 0, 1
while 1:
yield b
a, b = b, a+b
#for i in fib():
# print i
#The generator of all subsets
def all_subsets(str):
if len(str) < 1:
yield str
else:
for subset in all_subsets(str[1:]):
yield str[0:1] + subset
yield subset
#for s in all_subsets(['a','b','c','d']):
# print s
#for s in all_subsets("abcd"):
# print s
#A tour de force: a generator of all permutations
def all_permutations(str):
if len(str) <=1:
yield str
else:
for perm in all_permutations(str[1:]):
for i in range(len(perm)+1):
yield perm[:i] + str[0:1] + perm[i:]
#for p in all_permutations(['a','b','c','d','e']):
# print p
Feb 18 Notes: RNA Dynamic Programming Example
#Predicting RNA Secondary Structure
def printpairs(i,j,R):
if i>=j-4:
return
else:
x = opt(i,j,R)
if x[0]==0: #no pairs
return
elif x[1]==-1: # base j not paired
printpairs(i,j-1,R)
else:
t=x[1]
print "R[",t,"]=",R[t]," --- R[",j, "]=", R[j]
printpairs(i,t-1,R)
printpairs(t+1,j-1,R)
def opt(i,j,R):
#for each pair i,j this function returns the max number of base pairs
#in the interval from i to j in R as well as the pairing
#of jth base that achieves this; base j is paired with base maxt
if j - i < 5:
return [0,'x'] # no pairings possible in small interval
else:
maxsofar = opt(i,j-1,R)[0]
maxt = -1
for t in range(i,j-4):
if WCpair(R[t],R[j]):
val = 1+ opt(i, t-1,R)[0] + opt(t+1,j-1,R)[0]
if maxsofar < val:
maxsofar=val
maxt=t
return [maxsofar,maxt]
def WCpair(x,y):
if (x=='A' and y=='U') or (x=='U' and y=='A'):
return True
if (x=='C' and y=='G') or (x=='G' and y=='C'):
return True
return False
def main():
#R=raw_input("Enter RNA string")
R="GUCGAUUGAGCGAAUGUAACAACGUCGCUACGGCGAGA"
# has maximum 12 pairs
print " The maximum number of WC-base pairings for \n", R,":"
printpairs(0,len(R)-1,R)
main()
#Here is the memoized version
def printpairsmemo(OPT,i,j,R):
if i>=j-4:
return
if OPT[i][j][1]==-1:
printpairs(OPT,i,j-1,R)
else:
t=OPT[i][j][1]
print t,j,R[t],R[j]
printpairs(OPT,i,t-1,R)
printpairs(OPT,t+1,j-1,R)
def main_memoized():
R="GUCGAUUGAGCGAAUGUAACAACGUCGCUACGGCGAGA"
OPT=[]
for i in range(len(R)):
zrow=[]
for j in range(len(R)):
zrow.append([0,-1])
OPT.append(zrow)
for diag in range(len(R)):
for i in range(len(R)-diag):
j= i + diag
if j-i > 4:
OPT[i][j][0]=OPT[i][j-1][0]
for t in range(i,j-4):
if WCpair(R[t],R[j]):
if t > i:
val = 1+ OPT[i][t-1][0] + OPT[t+1][j-1][0]
else:
val = 1 + OPT[t+1][j-1][0]
if OPT[i][j][0] < val:
OPT[i][j] = [val,t]
best = OPT[0][len(R)-1]
print " The maximum number of WC-base pairings for \n", R,":", best[0]
print "PRINT MAX WC-BASE PAIRS"
printpairsmemo(OPT,0,len(R)-1,R)