Lecture 23: Profits and Weighted Intervals

$\def\opt{ {\mathrm{opt}} }$

Overview

1. Profit Maximization via Dynamic Programming
2. Weighted Interval Scheduling

Profit Maximization

Input. Array $a$ of size $n$

• $a[i] =$ price of Alphabet stock on day $i$

Output. Indices $b$ (buy) and $s$ (sell) with $1 \leq b \leq s \leq n$ that maximize profit

• $p = a[s] - a[b]$

Another (Recursive) Procedure?

• consider last day, $n$
• two cases for optimal solution:
1. max profit achieved by selling on day $n$
2. max profit achieved by selling before day $n$

Questions.

1. In case 1, how should we determine buy date?

• find minimum price in $a[1..n]$
2. In case 2, how should we compute max profit?

• recursively find max profit for $a[1..n-1]$

Recursive Procedure

  MaxProfit(a, n):
if n = 1 then return 0
min <- FindMin(a, n)
max <- MaxProfit(a, n-1)
return max(a[n] - min, max)


Running time?

• $\Theta(n^2)$
• $n$ method calls of sizes $n, n-1, n-2, \ldots, 1$
• running time is $\Theta(n + (n-1) + \cdots + 1) = \Theta(n^2)$

Memoizing MaxProfit

Create two arrays:

1. min[i] stores minimum value in a[1..i]
2. max[i] stores maximum profit achievable by selling up to time i

Question. How to update these arrays?

Memoized Maximum Profit

  MMaxProfit(a):
initialize arrays min, max
min[1] <- a[1]
max[1] <- 0
for i from 2 to n do
min[i] <- Min(min[i-1], a[i])
max[i] <- Max(max[i-1], a[i] - min[i])
endfor
return max[n]


Correctness

Claim. For every $i$, max[i] stores the maximum profit achievable by selling on a day $s \leq i$.

Proof. Induction on $i$…

Running Time?

  MMaxProfit(a):
initialize arrays min, max
min[1] <- a[1]
max[1] <- 0
for i from 2 to n do
min[i] <- Min(min[i-1], a[i])
max[i] <- Max(max[i-1], a[i] - min[i])
endfor
return max[n]


Optimization

Can do without arrays for min and max

  MMaxProfit(a):
min <- a[1]
max <- 0
for i from 2 to n do
min <- Min(min, a[i])
max <- Max(max, a[i] - min)
endfor
return max[n]


Exercise

Update MMaxProfit to return the buy/sell days in addition to the maximum achievable profit.

Weighted Interval Scheduling

Previously

Interval Scheduling:

Input. A set $R$ of $n$ intervals $r_1 = [s_1, t_1], r_2 = [s_2, t_2], \ldots, r_n = [s_n, t_n]$

Output. A collection of intervals from $R$ that is:

1. feasible no two intervals overlap
2. maximum the largest possible feasible collection

Maximum feasible collection can be found in $O(n \log n)$ time using a greedy algorithm

Today

Weighted Interval Scheduling:

Input.

1. A set $R$ of $n$ intervals $r_1 = [s_1, t_1], r_2 = [s_2, t_2], \ldots, r_n = [s_n, t_n]$
2. For each interval $r \in R$, a weight $w(r) > 0$
• e.g., weight = profit from serving request $r$

Output. A collection of intervals from $R$ that is

1. feasible no two intervals overlap
2. maximum weight choice maximizes sum of $w(r)$ for chosen $r$

Note: equivalent to (unweighted) interval scheduling when all weights are the same

Exercise

Construct an example for which the greedy algorithm for unweighted interval scheduling does not find a maximum weight solution.

Pre-processing

1. Sort intervals by end date
• $[s_1, t_1], [s_2, t_2], \ldots, [s_n, t_n]$
• $t_1 \leq t_2 \leq \cdots \leq t_n$
2. For each interval $r_i = [s_i, t_i]$ define
• $p[r_i] = r_j$ where $r_j$ is last interval with $t_j < s_i$

Optimal Solution Structure

Two cases for optimal solution $\opt$:

1. last interval $r_n$ is in $\opt$
2. last interval $r_n$ is not in $\opt$

Questions.

1. What is the structure of optimal solution in case 1?

2. What is the structure of optimal solution in case 2?

A Recursive Solution

  MaxWeightSchedule(w, p, n):
if n = 0 then return 0
opt-n <- w[n] + MaxWeightSchedule(w, p, p[n])
opt-no-n <- MaxWeightSchedule(w, p, n-1)
return Max(opt-n, opt-no-n)


Correctness?

Running Time?

  MaxWeightSchedule(w, p, n):
if n = 0 then return 0
opt-n <- w[n] + MaxWeightSchedule(w, p, p[n])
opt-no-n <- MaxWeightSchedule(w, p, n-1)
return Max(opt-n, opt-no-n)


Recursion to Iteration

Idea. Store array max:

• max[i] is maximum weight of schedule consisting of intervals $r_1, r_2, \ldots, r_i$

Question. How to initialize/update max values?

Iterative Solution

  IMaxWeightSchedule(w, p)
max <- new array of size n+1
max[0] <- 0
for i = 1 up to n do
max[i] <- Max(w[i] + max[p[i]], max[i-1])
endfor
return max[n]


Correctness:

• same argument as recursive solution

Running Time?

Overall Running Time?

Steps: (assume $n$ intervals)

1. Sort intervals by end time

2. Compute array p

3. Run IMaxWeightSchedule(w, p)

Total?

Exercise

Update IMaxWeightSchedule to return the actual schedule of maximum weight, not just the weight itself.

Next Time

• Sequence Alignment