Algorithm II
4. Greedy Algorithms I
WU Xiaokun 吴晓堃
xkun.wu [at] gmail
Greedy decision: builds up a solution in small steps, choosing a decision at each step myopically to optimize some underlying criterion.
It’s easy to invent greedy algorithms for almost any problem;
Goal. Given U.S. currency denominations \{ 1, 5, 10, 25, 100 \}, devise a method to pay amount to customer using fewest coins.
Coin Changing Problem. Given a set C = \{c_1, .., c_n\} of natural numbers and a target value S, find n multipliers M = \{m_1, .., m_n\} such that \sum_{k = 1 .. n} m_k c_k = S.
Customer usually does not like handsful small changes.
Ex. $2.89
Cashier′s algorithm. At each iteration, add coin of largest value that does not take us past the amount to be paid.
Is cashier’s algorithm optimal?
No. See below.
Q. Is cashier’s algorithm optimal for any set of denominations?
A. No. Consider U.S. postage: 1, 10, 21, 34, 70, 100, 350, 1225, 1500.
A. No. It may not even lead to a feasible solution if c_1 > 1: 7, 8, 9.
Property. Number of pennies \le 4.
Pf. Replace 5 pennies with 1 nickel.
Property. Number of nickels \le 1.
Property. Number of quarters \le 3.
Property. Number of nickels + number of dimes \le 2.
Pf.
Theorem. Cashier’s algorithm is optimal for U.S.
coins \{ 1, 5, 10, 25, 100 \}.
Pf. [ by induction on amount to be paid S ]
Consider n subjects are sharing a single resource.
A set of n Jobs:
Interval Scheduling Problem. Find maximum subset of mutually compatible jobs.
Which rule is optimal?
Different rule leads to different greedy algorithm.
Claim. The earliest-finish-time-first algorithm is optimal.
Proposition. Can implement
earliest-finish-time-first in O(n \log
n) time.
Pf.
Remember: greedy rules do not always lead to optimal solution.
Stay ahead: greedy algorithm is doing better in each step.
Claim. Earliest-finish-time-first is doing better in each step.
Observation. Greedy rule guarantees that f(i_1) \le f(j_1).
Lemma. For all indices r
\le k we have f(i_r) \le
f(j_r).
Pf. observed true for r =
1,
now suppose true for r - 1: f(i_{r-1}) \le f(j_{r-1})
Theorem. The earliest-finish-time-first algorithm is
optimal.
Pf. otherwise m >
k.
f(i_k) \le f(j_k) by lemma
Suppose that each job also has a positive weight and the goal is to find a maximum weight subset of mutually compatible intervals. Is earliest-finish-time-first algorithm still optimal?
Weighted Interval Scheduling will be solved by Dynamic Programming optimally.
Consider n subjects are sharing identical resources.
Goal: find minimum number of resources so that no incompatibility for each resource.
Which rule is optimal?
Depth. Maximum number that pass over any single point on the time-line.
Claim. In any instance of Interval Partitioning, the number of resources needed is at least the depth of intervals set.
Key Observation. If an algorithm always produce a schedule using resources equal to the depth, then it must be optimal.
“Characteristic bound”: greedy algorithm always attain a certain characteristic value.
Claim. Earliest-start-time-first algorithm uses a number of resources equal to the depth of intervals.
Proposition. The earliest-start-time-first algorithm
can be implemented in O(n \log n)
time.
Pf.
priority queue
(key
=
finish time of its last request).
INSERT
resource onto
priority queue.INCREASE-KEY
of
resource k to f_j.FIND-MIN
Remark. This implementation chooses a resource k whose finish time of its last request is the earliest.
Observation. ESTF never schedules two incompatible requests with same resource; every request will be fulfilled (by new allocation).
Theorem. Earliest-start-time-first algorithm is
optimal.
Pf.
Consider n subjects are sharing a single resources.
Goal: minimize the maximum lateness: L = \max_j l_j.
Which order minimizes the maximum lateness?
shortest processing time
smallest slack
length is not even related?
Observation 1 Earliest-deadline-first has no “gap”.
Idle time: there is work to be done, yet machine is sitting idle.
Observation 2. There exists an optimal schedule with no idle time.
Note: no-idle-time is a common property shared by greedy and optimal.
Exchange argument: given an optimal \mathcal{O}, gradually modify it
Def. Given a schedule S, an inversion is a pair of jobs i and j such that: d_i < d_j but j is scheduled before i.
.. | d_i | .. | d_j | .. |
---|---|---|---|---|
.. | j | .. | i | .. |
Observation 3 Earliest-deadline-first has no inversion (and no idle time).
Claim. All schedules with no inversions and no idle
time have the same maximum lateness.
Pf.
Key to show optimality: there is an optimal schedule that has no inversions and no idle time.
Observation 4. If an idle-free schedule has an
inversion, then it has an adjacent inversion (scheduled
consecutively).
Pf. Let i–j be the
closest inversion.
Let k be element immediately to the
right of j.
.. | d_i | .. | d_j | d_k | .. | ||
---|---|---|---|---|---|---|---|
.. | k | j | .. | i | .. | ||
.. | j | k | .. | i | .. |
Lemma. Exchanging two adjacent, inverted jobs i and j
reduces the number of inversions by 1
and does not increase max lateness.
Pf. Let l be the
lateness before swap, and let lʹ be it
afterwards.
\ | .. | d_i | .. | d_j | .. |
---|---|---|---|---|---|
before swap | .. | j | .. | i | .. |
after swap | .. | i | .. | j | .. |
Theorem. The earliest-deadline-first schedule is
optimal.
Pf.
Greedy algorithm stays ahead. Show that after each step of greedy algorithm, its solution is at least as good as any other algorithm’s.
Characteristic bound. Discover a simple characteristic bound asserting that every possible solution must have a certain value. Then show that your algorithm always achieves this bound.
Exchange argument. Gradually transform any solution to the one found by greedy algorithm without hurting its quality.
Other greedy algorithms. Gale–Shapley, Kruskal, Prim, Dijkstra, Huffman, etc.
LeetCode: https://leetcode.com
Caching.
Applications. CPU, RAM, hard drive, web, browser, etc.
Goal. Eviction schedule that minimizes the number of evictions.
Ex. k = 2, initial cache = ab, requests: a, b, c, b, c, a, b.
a | b | c | b | c | a | b |
---|---|---|---|---|---|---|
a | a | c | c | c | a | a |
b | b | b | b | b | b | b |
LIFO/FIFO. Evict item brought in least (most) recently.
LRU. Evict item whose most recent access was earliest.
LFU. Evict item that was least frequently requested.
Farthest-in-future. Evict item in the cache that is not requested until farthest in the future.
Theorem. [Bélády 1966] FF is optimal eviction schedule.
FF: 2 evictions
a | b | c | d | a | d | e | a | d | b | c |
---|---|---|---|---|---|---|---|---|---|---|
a | a | a | a | a | a | a | a | a | a | a |
b | b | b | b | b | b | e | e | e | e | e |
c | c | c | d | d | d | d | d | d | d | d |
FF: 2 evictions
a | b | c | d | a | d | e | a | d | b | c |
---|---|---|---|---|---|---|---|---|---|---|
a | a | a | a | a | a | a | a | a | a | a |
b | b | b | b | b | b | e | e | e | e | e |
c | c | c | d | d | d | d | d | d | d | d |
Note: other options may be just as good.
a | b | c | d | a | d | e | a | d | b | c |
---|---|---|---|---|---|---|---|---|---|---|
a | a | a | a | a | a | a | a | a | a | a |
b | b | b | d | d | d | d | d | d | d | d |
c | c | c | c | c | c | e | e | e | e | e |
So why FF is optimal?
Observation. Swapping one decision for another does not change cost.
Def. A reduced schedule does minimal amount of work necessary in a given step.
Note: FF is clearly reduced
Claim. Given any unreduced schedule S, can transform it into a reduced schedule
Sʹ with no more evictions.
Pf. [induction on step j] case-by-case discussion:
Or just “pretends” to cache but actually leaves d out
Note: for any reduced schedule, the number of items that are brought in is exactly the number of misses.
Let S_{FF} denote schedule produced
by Farthest-in-Future,
Let S^\ast denote a schedule that
incurs minimum possible number of misses
Theorem. FF is optimal eviction algorithm, since it incurs no more misses than any other schedule.
Lemma. If S_{FF} and S make same eviction decision through first j steps, then there is a reduced schedule S' that make same eviction decision as S through first j + 1 steps, and incurs no more misses than S.
S_{FF} and S have same cache contents.
Let d denote the item requested in step
j + 1.
S | steps | S’ | ||||
---|---|---|---|---|---|---|
same | e | f | step j | same | e | f |
same | e | d | step j + 1 | same | d | f |
… until following happens for the first time:
S | steps | S’ | ||||
---|---|---|---|---|---|---|
same | e | d | step j + 1 | same | d | f |
same | g | d | step A | same | d | g |
same | f | d | step B | same | d | f |
same | e | d | step C | same | d | e |
Problem of FF: in practice, generally impossible to know future request order.