Last time | Next time |
Today:
************************* I just wanted to point out to all of you that CSC-485/585 will be offered this summer session. This is the "Theory of Computation" course which is required for the Computer Science major. Theory can be a difficult course for some students and being able to focus upon that one course alone can be a great advantage for many. I have designed an online version of the course which has worked out quite well over the past 2.5 semesters (I know it sounds like I am bragging but it really is a good online course I think). The summer schedule is available and registration is open so if you are interested please sign up. If you are curious about what the course covers I can summarize it as follows: We search for the answer to one simple question : "What is computable?" or, to put it another way, "Are there problems that we cannot solve with any computer?". That is, we search for a simple model of computation which is equivalent in computational power to your friendly neighborhood computer and we try to determine if there are problems that cannot be solved using said model (Spoiler alert - there are!!!). We then find a way to actually prove that some problems are, in fact, unsolvable with ANY computational device - and I do not mean weird metaphysical questions like "What is the meaning of life?" or "Can God create a stone that she herself can't lift?" or stuff like that - I mean clear problems that can be stated in straight-forward mathematical terms. Along the way, as we search for our model and proof technique, we discover models for other families of problems that are quite useful in day to day problem solving and we discover properties about them which we can use in our repertoire of programming skills. If you have any questions, please let me know. Also, please keep in mind that, as a required course, CSC 485 often fills up very quickly during the Fall/Spring semesters. If you have any questions about the course or anything else that I can help you with feel free to contact me at newellg@nku.edu *****************************
Chapter 7 is the last material covered for your exam. While we introduced a fair number of techniques, we didn't do as much analysis as we might. So today we do some analysis. The following ideas/algorithms are featured in these three sections (7.2-7.4):
A few initial comments:
Now to the algorithms.
Now find the smallest entry in the two rows (other than the one already used), in a new column (representing at new node). One only need seek in "new columns", so the search each time is reduced by one in terms in columns, but augmented by one in terms of rows -- so the first search is $1(n-1)$; then $2*(n-2)$; then $3*(n-3)$; and so on.
If one is clever, one can minimize the amount of sorting (in fact, only finding the minimum is necessary -- which is O(n)). If one is not clever, then you're sorting $n-1$ lists of lengths \[ \{k(n-k)\}_{k=1,n-1}, \] each of which requires $m \log_2(m)$ comparisons. \[ \sum_{k=1}^{n-1} k(n-k)\log_2(k(n-k)) \]
This is actually a little worse than cubic, actually.
So there's an $n^2$ sort (if the graph is undirected, you can get by with half that -- but it's still on the order of $n^2$); and then one refills the matrix and checks that it's got every row covered. Can you guess the worst case situation?
I won't go into the details, but let's look at an example.
As I showed, this algorithm is one in which the problem is reduced in size with each vertex visited. A vertex is trimmed from the graph, with weights updated to incorporate the short-cuts from that node.
This is a greedy algorithm, and it starts by choosing the nearest node (because the weights are all positive, you can't do any better to the nearest node by using another node -- it can only increase your distance).
This should remind us of linear recurrence relations: for a simple graph, \[ C_n = C_{n-1} + (n-1) \] and $C_1=0$.
This implies that we're counting only the work you have to do to find the minimum among the other $n-1$ nodes to visit (call it $k$).
But then the weights to other nodes may need be adjusted to account for shortcuts using the chosen node. Each of that node's adjacencies (of which we need to consider $n-2$, at most) must be checked for improvement, involving checking a sum (the distance to $k$ plus the distance along the adjacency) against the current shortest distance to each other node.
So in sort of a worst case, counting everythingish way, we might have
\[ C_n = C_{n-1} + 3(n-1) \] and $C_1=0$.
This is still quadratic. Solving it is easy:
\[ 0, 3, 3+3(2)=9, 9+3(3)=18, 18+3(4)=30, ... \] That is, $3(0, 1, 3, 6, 10, ...)$, or \[ 3\frac{n(n-1)}{2} \]
Each of these can be formulated as a recursive scheme: we trim out a vertex each time a vertex is written (since it is never re-written). In each case, it's simply a matter of writing $n$ vertices, and deciding how to choose the order.
Again,
\[ C_n=C_{n-1}+n-1 \] with a worst case of $\frac{n(n-1)}{2}$.
Similarly for breadth first.
You should know how to carry out each of these algorithms, and any problems that can arise (e.g. Euler path).