next up previous
Next: About this document ...

Q and A
for Assignment 4

    

Here are some answers to questions, and (possibly) hints for Assignment 4, listed in anti-chronological order (latest near the top).

December 4:
Q: Under optimal BST it says that the minimum cost of a BST with nodes $ (K_0, f_0), \ldots, (K_n, f_n)$ will end up in table entry $ c[-1][n+1]$. Arrays in C/C++ don't allow negative indices, so how can you do this?

A: We don't limit our imagination (or our notation) by the boundaries of a programming language (no matter how charming it is). To represent a table with negative indices you will need to translate (or shift) your indices in your array.

For example, suppose you are working on a BST with two nodes, $ N_0$ and $ N_1$. The formula says your minimum cost will be in table entry $ c[-1][2]$, which could be represented in a 4x4 array by element $ C[0][3]$ if you used the translation $ c[i][j] == C[i+1][j+1]$.

The details of setting up a big enough array to hold your table, and shifting the indices appropriately could be handled in the constructors and the overloaded versions of minPartition in the derived classes, or in some other manner of your own invention.

December 4:
Q: The handout says that we should define $ c[i][k]$ to be the minimum cost of grouping matrices $ M_0 \cdots
M_{k-1}$. What role does $ i$ play in this? It doesn't seem to follow the pattern of the other chains (BST and polygons).

A: That's a typographical error, it should say ``Define $ c[i][k]$ to be the minimum cost of grouping matrices $ M_i \cdots M_{k-1}$,'' which is analogous to the other two versions of the definition.

December 4:
Q: Since we're using recursion, are we forbidden to use loops?

A: The two are not exclusive. For example, if you're trying to find the minimum value for $ i<j<k$ of $ c[i][j] + c[j][k] +
w(i,j,k)$ it might be reasonable to iterate over a loop with index $ j$ and make recursive calls to a function that calculates $ c[i][j]$ and $ c[j][i]$.

December 4:
Q: Is there a standard order to list a partition in? Also, is there a standard order to index the links of a chain with?

textbfA: The components that make up a partition can be listed in any order. The links in a chain should be indexed starting from 0 and increasing

I believe the first two are the only choice that would come to mind. The last one makes sure that what you specify is a convex polygon (clockwise order would also work). You may assume that the links we use for testing follow these conventions, and start with link 0. For example, pentagon.chn lists 5 vertices in ccw order, starting from vertex 0:
polygon
5
0       0
1       0
2       1
1       2
0       2
15.300563

December 2:
Q: I'm having difficulty getting started, especially with memoization. Can you recommend some incremental steps to get started?

A: You can write the code that finds the cost of a minimum partition in purely recursive form at first. This will be very inefficient, but you'll be able to test it on small cases. Once you have some confidence, add a table to keep track of intermediate results.

You should probably focus on whichever of the three problems seems most natural to you. Fill in the corresponding derived class, and convince your self that it's working before going to the other two.

December 2:
Q: What the following error messages mean? Is something wrong with my program?

g++: -rpath: linker input file unused because linking not done
g++: /local/lib: linker input file unused because linking not done

These messages don't indicate any problem with your program. Rather, they indicate a problem with the g++ script on some of the CDF linux machines when using the '-c' switch. You can safely ignore them, and they won't occur during our testing of your program.

November 30:
Q: Are we required to use memoization when we are piecing together a list of components from the array m[i][j]? In the course Readings they use a simple recursive function to process best[i][j], which seems to play the same role.

A: You don't have to use memoization at this step, since the recursive sub-cases don't overlap and the complexity is easily within the required bounds.

November 30:
Q: Why do the derived classes have overloaded versions of minPartition as public members?

A: Most of the algorithm you need to perform is generic: it's common for all three cases. However, you may need to shift the indices a bit in setting things up. You are allowed to use the overloaded minPartition as a front-end that manipulates indices a bit, and uses the base class's minPartition for the heavy lifting.

November 29:
Q: You seem to treat linkList as an array, not a linked list??

A: Unfortunate choice of names. Perhaps listOLinks would have been better. You may treat it as an array.

November 29:
Q: Can you give an example of memoization?

A: memoized fibonacci should illustrate the principle, while being sufficiently far from A4.

#include <stdio.h>
int fib(int n)
{
    int rec_fib_mem(int n, int *fibs);
    int *fibs, fibResult;

    if (n < 2) /* defined only for non-negative integers */
        return n;
    else {
        fibs = new int[n+1];
        fibs[0] = 0;
        fibs[1] = 1;
        for (int i = 2; i <= n; i++)
            fibs[i] = -1; /* sentinel value */
        fibResult = rec_fib_mem(n,fibs);
        delete []fibs; /* hygiene */
        return fibResult;
    }
}

int rec_fib_mem(int n, int *fibs)
{
    if (fibs[n] == -1) /* work to do still */
        fibs[n] = rec_fib_mem(n-1, fibs) + rec_fib_mem(n-2, fibs);
    return fibs[n];
}

int main()
{
    int n;
    printf("Enter non-negative integer: ");
    scanf("%d", &n);
    printf("fib(%d): %d\n", n, fib(n));
    return 0;
}
November 27:
Q: Isn't there an easier way to solve these problems than DP?

A: Perhaps, but nobody's come up with one yet. For example, an entire class of ``easier'' algorithms is called Greedy Algorithms, which build an optimal solution step-by-step, using some sort of ready criterion, and they never reconsider a step once it's taken.

As an example, suppose you decided to group a matrix product by grouping the matrices so that the last matrix product taken involved as few multiplications as possible. You might then repeat this approach on the sub-groupings of your matrix product until you had at most two matrices to multiply at any given step. This approach comes to grief when you have matrices $ A_0$, $ A_1$, and $ A_2$ with dimensions $ 2\times 3$, $ 3\times 4$, and $ 4\times 3$, respectively. The criterion suggested means that we'd group the matrices as follows:

$\displaystyle (A_0 (A_1 A_2)),
$

...requiring 54 multiplications. However, grouping them:

$\displaystyle ((A_0 A_1) A_2)
$

...requires only 48 multiplications. So that particular greedy algorithmm doesn't work. How about choosing a grouping so that the final product requires as many multiplications as possible? Just modify the previous example so that the dimensions are $ 2\times 3$, $ 3\times 4$, and $ 4\times 2$, respectively, and you'll find that this approach doesn't work either.

Okay, you may think that you've got a fool-proof greedy algorithm for building an optimal BST. After all, it seems obvious that the most frequently accessed nodes should be at the top, so why not make that a quick principle for building a BST: place the most frequently accessed node at the root, the next most-frequently accessed node should be its root, and so on. Consider a BST formed from three nodes: the first has key 'A' and frequency 3, the second has key 'B' and frequency 2, the last has key 'C' and frequency 2. The just-mentioned criterion places 'A' at the root, and leads to a more costly tree than if you placed 'B' at the root. Whoops.

If you're willing to provide more greedy algorithms, I'll try to come up with counter-examples.




next up previous
Next: About this document ...
Danny Heap 2002-12-04