<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CS 170: Efficient Algorithms and Intractable Problems on</title><link>https://notes.bencuan.me/cs170/</link><description>Recent content in CS 170: Efficient Algorithms and Intractable Problems on</description><generator>Hugo</generator><language>en</language><atom:link href="https://notes.bencuan.me/cs170/index.xml" rel="self" type="application/rss+xml"/><item><title>Algorithms for Integer Arithmetic</title><link>https://notes.bencuan.me/cs170/Algorithms-for-Integer-Arithmetic/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Algorithms-for-Integer-Arithmetic/</guid><description>&lt;blockquote&gt;
&lt;p&gt;💡 Creating good algorithms requires two main building blocks: &lt;strong&gt;correctness&lt;/strong&gt; and &lt;strong&gt;efficiency.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="addition"&gt;
 Addition
 &lt;a class="anchor" href="#addition"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We would like to define an algorithm $A_{add}$ such that&amp;hellip;&lt;/p&gt;
&lt;p&gt;$(\forall x,y)(A_{add}(x,y) \to x+y)$&lt;/p&gt;
&lt;h3 id="a-naive-approach"&gt;
 A naive approach
 &lt;a class="anchor" href="#a-naive-approach"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;One straightforward way to add is to &amp;ldquo;count by fingers&amp;rdquo;- that is, keep adding one continually until you reach the end of the number.&lt;/p&gt;
&lt;p&gt;Given $n$ digits, this algorithm, in the worst case, must add one $10^n - 1$ times. This is quite inefficient! Let&amp;rsquo;s see if we can do better.&lt;/p&gt;</description></item><item><title>Divide and Conquer (Master Theorem)</title><link>https://notes.bencuan.me/cs170/Divide-and-Conquer-Master-Theorem/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Divide-and-Conquer-Master-Theorem/</guid><description>&lt;h3 id="divide-and-conquer-an-intro"&gt;
 Divide and Conquer: an Intro
 &lt;a class="anchor" href="#divide-and-conquer-an-intro"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;![[/cs170/img/Divide-and-Conquer-Master-Theorem/Untitled.png]]&lt;/p&gt;
&lt;p&gt;Sometimes, especially for recursive algorithms, we can write a runtime as a &lt;strong&gt;recurrence relation&lt;/strong&gt;: that is, part of a function&amp;rsquo;s runtime definition is the function itself with a smaller problem size.&lt;/p&gt;
&lt;p&gt;This applies directly to a method called &lt;strong&gt;divide and conquer,&lt;/strong&gt; which goes something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We&amp;rsquo;re given some input $x$ and are trying to evaluate a function $A(x)$.&lt;/li&gt;
&lt;li&gt;We can split $x$ into smaller parts $x_1, x_2, \cdots x_a$.&lt;/li&gt;
&lt;li&gt;We can then find the output of each individual part $A(x_1), A(x_2), \cdots A(x_a)$.&lt;/li&gt;
&lt;li&gt;Sum up all of these outputs to get the original desired value $A(x)$.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take this example (Karatsuba Multiplication): $T(n) = 3T(n/2) + cn$&lt;/p&gt;</description></item><item><title>Matrix Multiplication</title><link>https://notes.bencuan.me/cs170/Matrix-Multiplication/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Matrix-Multiplication/</guid><description>&lt;h3 id="general-method"&gt;
 General Method
 &lt;a class="anchor" href="#general-method"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;If we were just to multiply two matrixes by hand (let&amp;rsquo;s say we are trying to find $XY$), then we would need to multiply the $i$th row of $X$ with the $j$th column of $Y$ to get the $i,j$ position of the result $Z$.&lt;/p&gt;
&lt;p&gt;![[/cs170/img/Matrix-Multiplication/Untitled.png]]&lt;/p&gt;
&lt;h3 id="naive-algorithm"&gt;
 Naive Algorithm
 &lt;a class="anchor" href="#naive-algorithm"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A straightforward way of going by this is simply to loop through every possible value of $i$ and $j$:&lt;/p&gt;</description></item><item><title>Sorting</title><link>https://notes.bencuan.me/cs170/Sorting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Sorting/</guid><description>&lt;h2 id="general-introduction"&gt;
 General Introduction
 &lt;a class="anchor" href="#general-introduction"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The problem of sorting:&lt;/strong&gt; given a list of numbers $a_1, \cdots, a_n$, output them in increasing or decreasing order.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Idea (Divide and conquer):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Split the list in to two halves.&lt;/li&gt;
&lt;li&gt;Recursively sort each half.&lt;/li&gt;
&lt;li&gt;Merge the two halves together.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This sounds familiar&amp;hellip;&lt;/p&gt;
&lt;h2 id="merge-sort"&gt;
 Merge Sort
 &lt;a class="anchor" href="#merge-sort"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mergesort&lt;/span&gt;(lst):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; lst has &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; element:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; lst[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	s_l &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mergesort(first half of lst)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	s_r &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mergesort(second half of lst)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	s &lt;span style="color:#f92672"&gt;=&lt;/span&gt; merge(s_l, s_r)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;merge&lt;/span&gt;(s_l, s_r):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; s_r &lt;span style="color:#f92672"&gt;is&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; empty:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; s_l &lt;span style="color:#f92672"&gt;is&lt;/span&gt; empty:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result &lt;span style="color:#f92672"&gt;+&lt;/span&gt; s_r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; s_l[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; s[r]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			result &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; s_l[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			remove s_l[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result &lt;span style="color:#f92672"&gt;+&lt;/span&gt; s_l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The runtime of the &lt;strong&gt;merge&lt;/strong&gt; operation is $\Theta(|s_l| + |s_r|)$ since we go through each element in each list exactly once.&lt;/p&gt;</description></item><item><title>Median Finding</title><link>https://notes.bencuan.me/cs170/Median-Finding/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Median-Finding/</guid><description>&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Given a set $S=\{a_1, \cdots, a_n\}$, find the median $a \in S$ such that half of the values in $S$ are greater than $a$ and the other half is less than $a$.&lt;/p&gt;
&lt;p&gt;The median is less sensitive to outliers than the mean.&lt;/p&gt;
&lt;h2 id="finding-the-median"&gt;
 Finding the Median
 &lt;a class="anchor" href="#finding-the-median"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="a-naive-solution"&gt;
 A naive solution
 &lt;a class="anchor" href="#a-naive-solution"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;One method of finding the median is simply sorting the list, then getting the middle element. This requires $n\log(n)$ comparisons (see [[03 Sorting]] for more information).&lt;/p&gt;</description></item><item><title>Fast Fourier Transform (FFT)</title><link>https://notes.bencuan.me/cs170/Fast-Fourier-Transform-FFT/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Fast-Fourier-Transform-FFT/</guid><description>&lt;h1 id="polynomial-multiplication"&gt;
 Polynomial Multiplication
 &lt;a class="anchor" href="#polynomial-multiplication"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="the-problem"&gt;
 The Problem
 &lt;a class="anchor" href="#the-problem"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s say we have two input polynomials $A(x) = \sum_{i=0}^d a_ix^i$ and $B(x) = \sum_{i=0}^d b_ix^i$.&lt;/p&gt;
&lt;p&gt;We would like to find an output $C(x) = A(x) \cdot B(x)$. $C(x)$ has a degree $2d$.&lt;/p&gt;
&lt;p&gt;By definition of polynomial multiplication,&lt;/p&gt;
$$
C(x) = \sum_{i=0}^d \sum_{j=0}^d a_i b_j x^i x^j
$$&lt;p&gt;Let&amp;rsquo;s gather all of the coefficients with the same power together to make this expression more useful:&lt;/p&gt;</description></item><item><title>Graphs</title><link>https://notes.bencuan.me/cs170/Graphs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Graphs/</guid><description>&lt;h1 id="graph-representations"&gt;
 Graph Representations
 &lt;a class="anchor" href="#graph-representations"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;A graph is a pair $(V,E)$ where $V$ is the vertex set and $E \subseteq V \times V$ is the edge set. (For an introductory data-structures treatment, see [[cs61b/abstract-data-types/graphs]]; for the discrete-math/combinatorial properties used in proofs, see [[cs70/discrete-math/graphs]].)&lt;/p&gt;
&lt;p&gt;There are 2 main ways to represent graphs for an algorithm:&lt;/p&gt;
&lt;h2 id="adjacency-matrix"&gt;
 Adjacency Matrix
 &lt;a class="anchor" href="#adjacency-matrix"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;$M_G = \begin{pmatrix} m_{ij} \end{pmatrix} \in \{0,1\}^{m \times n}$&lt;/p&gt;
&lt;p&gt;If $m_{ij} = 1$, then that means the vertices $i$ and $j$ are connected with an edge.&lt;/p&gt;</description></item><item><title>Greedy Algorithms</title><link>https://notes.bencuan.me/cs170/Greedy-Algorithms/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Greedy-Algorithms/</guid><description>&lt;h2 id="what-are-greedy-algorithms"&gt;
 What are greedy algorithms?
 &lt;a class="anchor" href="#what-are-greedy-algorithms"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Greedy algorithms are a general algorithmic approach:&lt;/p&gt;
&lt;p&gt;At every step, choose what to do based on local information without considering the next steps. This works nicely in some cases because of the efficiency of such a concept.&lt;/p&gt;
&lt;h3 id="a-simple-example"&gt;
 A simple example
 &lt;a class="anchor" href="#a-simple-example"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s say you have 6 assignments that are due in 1, 1, 2, 2, 4, and 5 hours respectively. Each one takes 1 hour to complete. What is the maximum number you can complete before the deadline?&lt;/p&gt;</description></item><item><title>Minimum Spanning Trees</title><link>https://notes.bencuan.me/cs170/Minimum-Spanning-Trees/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Minimum-Spanning-Trees/</guid><description>&lt;h3 id="the-problem"&gt;
 The Problem
 &lt;a class="anchor" href="#the-problem"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Given an undirected graph $G$ with positive edge weights, find a subset $T \subseteq E$ such that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All vertices are connected.&lt;/li&gt;
&lt;li&gt;The sum of edge weights in $T$ is minimized.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For step-by-step worked examples of the two classical algorithms, see [[cs61b/algorithms/minimum-spanning-trees/kruskals-algorithm]] and [[cs61b/algorithms/minimum-spanning-trees/prims-algorithm]].&lt;/p&gt;
&lt;p&gt;We can notice that $T$ is actually a &lt;strong&gt;tree&lt;/strong&gt;!&lt;/p&gt;
&lt;h3 id="tree-properties"&gt;
 Tree Properties
 &lt;a class="anchor" href="#tree-properties"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;An undirected graph $T$ is a tree if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$T$ is connected.&lt;/li&gt;
&lt;li&gt;$T$ has no cycles.&lt;/li&gt;
&lt;li&gt;$|E| = |V| - 1$.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Any 2 of these properties implies the third.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Huffman Coding</title><link>https://notes.bencuan.me/cs170/Huffman-Coding/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Huffman-Coding/</guid><description>&lt;h1 id="the-problem-data-compression"&gt;
 The Problem: Data Compression
 &lt;a class="anchor" href="#the-problem-data-compression"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Given a string of characters &lt;code&gt;ABACCDBB...&lt;/code&gt; from an alphabet $\{A,B,C,D \cdots\}$, how may bits do we need in order to encode it?&lt;/p&gt;
&lt;p&gt;Of course, there is the naive way (just store the entire string), which requires $O(n)$ bits, but with Huffman encoding, we can do better!&lt;/p&gt;
&lt;h1 id="prefix-free-codes"&gt;
 Prefix-Free Codes
 &lt;a class="anchor" href="#prefix-free-codes"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;One strategy is a greedy algorithm which assigns more frequently seen characters a shorter length bit representation. For example, if A occurs 40% of the time, B 30%, C 20%, and D 10%, we could do something like:
&lt;code&gt;A → 0, B → 10, C → 110, D → 111&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Horn Formulas</title><link>https://notes.bencuan.me/cs170/Horn-Formulas/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Horn-Formulas/</guid><description>&lt;h1 id="horn-formulas"&gt;
 Horn Formulas
 &lt;a class="anchor" href="#horn-formulas"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="the-problem-boolean-expressions"&gt;
 The Problem: Boolean Expressions
 &lt;a class="anchor" href="#the-problem-boolean-expressions"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Suppose we have a boolean expression such as $(w \lor y \lor z) \land (y \implies w) \lor (\lnot u \land \lnot v \land \lnot z)$ and so on.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;d like to answer the question: are there any values of boolean variables that make this statement true?&lt;/p&gt;
&lt;p&gt;In the general case, this problem is NP-hard&amp;hellip;&lt;/p&gt;
&lt;h2 id="a-special-case"&gt;
 A Special Case
 &lt;a class="anchor" href="#a-special-case"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are some special cases, though, that can be solved with a greedy algorithm. These are called &lt;strong&gt;Horn clauses:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Dynamic Programming</title><link>https://notes.bencuan.me/cs170/Dynamic-Programming/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Dynamic-Programming/</guid><description>&lt;h1 id="what-is-dynamic-programming"&gt;
 What is Dynamic Programming?
 &lt;a class="anchor" href="#what-is-dynamic-programming"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Dynamic Programming (DP) is a general approach to many types of problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Main idea:&lt;/strong&gt; Solve a big problem by breaking it into smaller subproblems, and solve subproblems in order from small to large.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Approach:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define subproblems (that are smaller than the original problem).&lt;/li&gt;
&lt;li&gt;Show how we can solve the original problem given the answers to the subproblems.&lt;/li&gt;
&lt;li&gt;Define base cases (when to return a simple result).&lt;/li&gt;
&lt;li&gt;Choose the order to solve subproblems such that we can make the algorithm efficient.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="how-is-this-different-from-recursion-though"&gt;
 How is this different from recursion though?
 &lt;a class="anchor" href="#how-is-this-different-from-recursion-though"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In DP, &lt;strong&gt;we solve smaller subproblems first.&lt;/strong&gt; In recursion, we don&amp;rsquo;t reach these subproblems until we try to calculate the larger problem.&lt;/li&gt;
&lt;li&gt;In other words, &lt;strong&gt;when we reach a larger subproblem, all its subproblems must already have been computed.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="some-examples"&gt;
 Some Examples
 &lt;a class="anchor" href="#some-examples"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="shortest-paths-in-dags"&gt;
 Shortest Paths in DAGs
 &lt;a class="anchor" href="#shortest-paths-in-dags"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Given a graph $G(V,E)$ with integer weights (negative weights ok), find the shortest path from $s \in V$ to $v \in V$.&lt;/p&gt;</description></item><item><title>Linear Programming</title><link>https://notes.bencuan.me/cs170/Linear-Programming/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Linear-Programming/</guid><description>&lt;h1 id="what-is-linear-programming"&gt;
 What is Linear Programming?
 &lt;a class="anchor" href="#what-is-linear-programming"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Linear programming is expressing and solving linear optimization, typically in higher dimension problems.&lt;/p&gt;
&lt;p&gt;An optimization problem has the following form:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$n$ real variables $x_1, \cdots, x_n \in \mathbb{R}$,&lt;/li&gt;
&lt;li&gt;An objective function $f(x_1, \cdots, x_r) \in \mathbb{R}$&lt;/li&gt;
&lt;li&gt;$m$ constraints $c_1, \cdots c_m$ such that $c_i(x_1, \cdots, x_n)$ returns either true or false.&lt;/li&gt;
&lt;li&gt;A goal to get the maximum of $f(x_1, \cdots, x_n)$ such that all constraints are true.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A linear programming problem is a subset of optimization problems, such that:&lt;/p&gt;</description></item><item><title>Network Flow</title><link>https://notes.bencuan.me/cs170/Network-Flow/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Network-Flow/</guid><description>&lt;h1 id="what-is-flow"&gt;
 What is Flow?
 &lt;a class="anchor" href="#what-is-flow"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Suppose we have a directed graph with a source $s$ and sink $v$. Each edge has a positive capacity $c &gt; 0$.&lt;/p&gt;
&lt;p&gt;A (feasible) flow is a function that maps edges to real numbers $f: E \to \mathbb{R}$ that satisfies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Capacity constraints:&lt;/strong&gt; $\forall e \in E$, $0 \le f(e) \le c(e)$. Each edge can only have a particular capacity (think pipes).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conservation constraints:&lt;/strong&gt; $\forall u \in V \setminus \{s, t\}$, $\sum f(w, u) = \sum f(u, v)$. The amount of flow that enters a particular vertex is the same amount that leaves that vertex.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;value&lt;/strong&gt; of a flow is the amount that leaves the source. This should equal the amount that enters the sink if the flow is feasible.&lt;/p&gt;</description></item><item><title>Duality</title><link>https://notes.bencuan.me/cs170/Duality/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Duality/</guid><description>&lt;h2 id="primal-and-dual-an-example"&gt;
 Primal and Dual: An Example
 &lt;a class="anchor" href="#primal-and-dual-an-example"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Suppose we have an original, known as a &lt;strong&gt;primal&lt;/strong&gt;, linear program with variables $x_1, \cdots, x_n$ and some constraints on those variables.&lt;/p&gt;
&lt;p&gt;As an example, let&amp;rsquo;s say we are trying to maximize $2x_1 + 4x_2$ such that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x_1, x_2 \ge 0$&lt;/li&gt;
&lt;li&gt;$x_1 \le 50, x_2 \le 80$&lt;/li&gt;
&lt;li&gt;$x_1 + x_2 \le 100$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can rewrite the objective function as a linear combination of the constraints:&lt;/p&gt;</description></item><item><title>Zero-Sum Games</title><link>https://notes.bencuan.me/cs170/Zero-Sum-Games/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Zero-Sum-Games/</guid><description>&lt;h1 id="zero-sum-games"&gt;
 Zero Sum Games
 &lt;a class="anchor" href="#zero-sum-games"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;In this scheme, there are two players (known as the &lt;strong&gt;column player&lt;/strong&gt; and &lt;strong&gt;row player&lt;/strong&gt;, or analogously, &lt;strong&gt;minimizer&lt;/strong&gt; and &lt;strong&gt;maximizer&lt;/strong&gt;) playing a game with a particular strategy.&lt;/p&gt;
&lt;p&gt;![[/cs170/img/Zero-Sum-Games/Untitled.png]]&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;strategy&lt;/strong&gt; generally entails assigning a probability to choosing one particular row and column (either A or B in the above image). In the matrix, a numerical element represents the &lt;strong&gt;payoff&lt;/strong&gt; for making that move.&lt;/p&gt;
&lt;p&gt;The total payoff can be calculated as a weighted sum, where the payoff of a particular row or column is multiplied by the probability that it is chosen.&lt;/p&gt;</description></item><item><title>Reductions</title><link>https://notes.bencuan.me/cs170/Reductions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Reductions/</guid><description>&lt;h2 id="introduction"&gt;
 Introduction
 &lt;a class="anchor" href="#introduction"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The strategy of reduction is to reduce a particular Problem A into another Problem B using a subroutine. We can then use Problem B to solve Problem A.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good news:&lt;/strong&gt; If Problem B is efficient, then this provides a fast algorithm for Problem A.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bad news:&lt;/strong&gt; If Problem A is hard, Problem B must be hard too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step by Step:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Preprocess - turn the input of A into an input for B.&lt;/li&gt;
&lt;li&gt;Run Problem B.&lt;/li&gt;
&lt;li&gt;Postprocess - convert the output of B into the output of A.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can use reduction to:&lt;/p&gt;</description></item><item><title>Search Problems, P/NP</title><link>https://notes.bencuan.me/cs170/Search-Problems-P-NP/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Search-Problems-P-NP/</guid><description>&lt;h1 id="intro-to-search-problems"&gt;
 Intro to Search Problems
 &lt;a class="anchor" href="#intro-to-search-problems"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="definitions"&gt;
 Definitions
 &lt;a class="anchor" href="#definitions"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;binary relation&lt;/strong&gt; is a subset of pairs of finite bit strings, where $(x,w)$ is a (instance, witness) relationship. Remember that any data structure can be represented as a bit string, since it can be programmed into a computer.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;decision problem&lt;/strong&gt; &lt;code&gt;decide(R)&lt;/code&gt; takes an input instance $x$, and determines if there exists a witness $w$ such that $(x, w) \in R$, i.e. does there exist a solution to the problem?&lt;/p&gt;</description></item><item><title>Randomized Algorithms</title><link>https://notes.bencuan.me/cs170/Randomized-Algorithms/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Randomized-Algorithms/</guid><description>&lt;h2 id="types-of-randomized-algorithms"&gt;
 Types of Randomized Algorithms
 &lt;a class="anchor" href="#types-of-randomized-algorithms"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are two main classes of random algorithms, Las Vegas algorithms and Monte Carlo algorithms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Las Vegas algorithms&lt;/strong&gt; are &lt;strong&gt;correct, and probably fast.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For example, randomized quicksort (where we choose a random pivot) is guaranteed to return a correct sort regardless of the pivots chosen, but it&amp;rsquo;s possible to choose bad pivots and result in a poor runtime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monte Carlo algorithms&lt;/strong&gt; are &lt;strong&gt;fast, and probably correct.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Streaming</title><link>https://notes.bencuan.me/cs170/Streaming/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Streaming/</guid><description>&lt;h1 id="streaming-algorithms"&gt;
 Streaming Algorithms
 &lt;a class="anchor" href="#streaming-algorithms"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;In applications like the internet, we might have vast amounts of data &amp;ldquo;streaming&amp;rdquo; by. How do we quickly store and update this data via approximation?&lt;/p&gt;
&lt;h2 id="examples-of-streaming-algorithms"&gt;
 Examples of Streaming Algorithms
 &lt;a class="anchor" href="#examples-of-streaming-algorithms"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="morriss-algorithm-for-approximate-counting"&gt;
 Morris&amp;rsquo;s Algorithm for Approximate Counting
 &lt;a class="anchor" href="#morriss-algorithm-for-approximate-counting"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Suppose we were counting total sales. Given an input of $n$ sales with prices $p_1, \cdots, p_n$, output the total $p = \sum_{i=1}^n p_i$.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Initialize a running counter $X$. With probability $\frac{1}{2^X}$, increment $X$ by $1$. Then, return $\tilde{n} = 2^X - 1$.&lt;/p&gt;</description></item><item><title>Lower Bounds</title><link>https://notes.bencuan.me/cs170/Lower-Bounds/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://notes.bencuan.me/cs170/Lower-Bounds/</guid><description>&lt;p&gt;Typically, when we are considering algorithms we talk about the &lt;em&gt;upper bounds&lt;/em&gt; of runtime, i.e. how long a function takes to calculate some result.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s try to prove a lower bound that applies to &lt;strong&gt;any&lt;/strong&gt; problem that solves a particular problem.&lt;/p&gt;
&lt;h3 id="sorting"&gt;
 Sorting
 &lt;a class="anchor" href="#sorting"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We know that all comparison sorting algorithms take $\Omega(n \log n)$ time. This is because this is the required number of comparisons needed to find a relation between all numbers in a tree structure.&lt;/p&gt;</description></item></channel></rss>