Why Hava?

Hava is a computational tool for formulating, solving and interpreting a wide variety of decision analysis models that arise in industrial engineering, operations research, operations management and finance. It enhances the experience of teaching or learning about these applications by providing access to a wider variety of problems. In particular:

  • For the instructor: Hava enables you to pose and numerically solve interesting, real-world extensions to classic textbook models. You are no longer confined to stylized models whose structure permits a simple closed-form solution, which your students will later misapply because the model’s special assumptions were forgotten or ignored.

  • For the student: Hava enables you to quickly formulate, solve and interpret interesting (or assigned) problems without the overhead that necessarily arises when using a spreadsheet or general programming language.

  • For both: Hava encourages the practice of modifying an existing program with small changes, rather than having to construct each program from scratch. Problem variations can be created with a few keystrokes, and the results appear immediately. It is possible to examine many such problem variations in a short span of time, and to learn by trial and error. Best of all, it is not necessary to be a skilled programmer in order to use and benefit from Hava.

Let us consider Hava in the context of other computational tools commonly used to tackle these kinds of problems. At the easy end of the scale, we have “solution by hand” (and pencil, paper and calculator). This is great for really small problems, but it quickly becomes impossibly demanding and tedious as the problem size increases.

At the hard end of the scale, we have programming languages such as Java. They offer more power, of course, but programming is harder to learn and use. For example, a Java program must provide its own custom data types (objects) and user I/O mechanisms. A homework problem or project might require several days (all-nighters?); at most one or two can be tackled in a term. Most of the effort contributes little to understanding the course material, and a significant percentage of students in the course will simply lack the programming skills to pull it off.

At the middle of the scale, we have spreadsheets, which perform the arithmetic, and display intermediary steps in a rectangular grid. Indeed, Hava is in many ways like a spreadsheet: the user provides a collection of definitions, and the software automatically determines the sequence in which to apply these definitions in order to generate computed values. Like a spreadsheet, Hava is not, strictly speaking, a programming language: It does not require the user to provide sequential instructions, or to tackle abstractions of the computational process. Like the definitions behind each spreadsheet cell, Hava statements resemble the algebraic statements used to specify a model.

Yet, there are fundamental differences between Hava and spreadsheets:

  • Focus. A spreadsheet is designed to generate attractive output, and it hides the underlying mechanisms. Looking at a spreadsheet, you can see what it produced, but you cannot see what rules it followed. Hava, by comparison, shows the rules, and does not attempt to produce formatted output. (The lack of formatting is deliberate: When it is available, users are tempted to spend time making the output attractive, and not focus on modeling or obtaining correct results.)

  • Organization. Spreadsheets do best when a problem is naturally organized into a rectangular grid. Hava works with indexed variables x(s) where s can be anything --- a number, a pair of numbers, a list of numbers, a list of lists of tokens and numbers, etc. So Hava is equally at home with problems that are organized on trees, or Cartesian products of ordinal sets, or whatever. This feature facilitates problem representation and organization of the logical relationships among variables when these variables take values that are not simply numbers, vectors or matrices.

The issue of organization is particularly acute in the context of dynamic programming. It is generally recognized that dynamic programming is difficult to teach. A more subtle observation is that dynamic programming is difficult to do, even when you understand it in principle. One might argue that you don't really understand it until you've done it.

One way to approach small dynamic programming problems is to exploit the concept of stage and state in order to write a Bellman equation, and then to evaluate this Bellman equation as a recursive function. This is fairly easy to do in Matlab or Java. And it will generate the correct solution, for sufficiently small problems. But it is terribly slow, because it amounts to total enumeration. And it completely overlooks a critical feature of dynamic programming, namely, the advantage derived from computing values only once.

This point is mentioned in our Language Tutorial, but let us review it here in detail. The problem is to compute the N-th row of Pascal's triangle using the recursion:

C(n,k) = 1 (if k is 0 or n), or C(n-1,k-1) + C(n-1,k) (otherwise).

The n-th row contains n-1 elements that require one addition each to calculate, so the Nth row can be obtained in N(N-1)/2 additions. For N=10, that's 45 additions. If C(n, k) is evaluated as a function, it will evaluate the terms C(n-1,k-1) and C(n-1,k) in order to obtain their sum, but discard their values. Consequently, every computed value in row N-1 will be evaluted twice. And every value in row N-2 will be computed four times. And so on. The total effort is 1013 additions, as was noted in the tutorial. You can see them all in the Hava trace!

We chose this problem as an example because everybody is already familiar with it. Perhaps too familiar. After all, there is already a closed-form expression for C, so there is no need to do any calculations at all, or so the thinking goes. But the closed-form expression

C(n, k) = n! / k! n-k!

uses factorials, which aren't given out for free; somebody had to calculate them. And they require quite a few multiplications, in fact, the same order of magnitude, O(N²), as the additions in our original recursive formulation. So the presumed benefit of a closed-form expression is an illusion; it does not buy us anything in run time.

As we have hopefully demonstrated, the ability to retain intermediary values is critically important when evaluating recursively-defined expressions. This is not something that will "automatically" happen if these expressions are evaluated as Matlab or Java functions, although it might be achieved by specifying, in advance, the sequence in which values will be computed. This works best when the states are known, and are naturally sequenced along an axis. Now the problem is naturally organized into a grid, with stages along one axis and states along the other. It can be solved on a spreadsheet, or in Matlab or Java, with the values arranged into a matrix.

But even these looser conditions fail to hold for many of the examples we have offered on our home page. In the dynamic programming solution to the knapsack problem, the states and stages would appear to be arranged into a grid. But that's another illusion, which is easily dispelled by examining the Hava trace. The states that matter at each stage are the possible amounts of resource remaining after the first few items have been assigned. A list of reachable states is not available a priori, and calculating values for a larger set of states (e.g. all integers) is computationally inefficient.

Hava manages these things natively, so the Hava user is not required to deal with them.

Hava is perhaps seen to best advantage in the Machine Repair example, which is, essentially, a large decision tree. As the referenced MIT lecture notes demonstrate, this is not an easy problem to formulate. The literature shows few examples of solutions for this kind of problem, and those that were obtained required considerable effort. What is remarkable about the Hava approach is that it did obtain a solution, working from a formal specification that closely resembles the algebraic formulation.

In summary, Hava was created to fill a gap in the kit of computational tools available to students and faculty, not to replace those already available. If the problems you wish to solve can be addressed with existing tools, you have no need to use Hava. But for many problems that are rarely tackled in the classroom, for lack of a means to solve them, Hava offers new opportunities for exploration, experience and growth. Just imagine how much richer that MIT lecture might have been had Hava been available at the time.