Nash - Scientific Computing with PCs (523165), страница 38
Текст из файла (страница 38)
Even learning the behavior of a specific input handler sufficiently well to rely on it requiresconsiderable effort. Worse, the behavior of the input handler may change from version to version of the12: STEPS IN PROBLEM SOLVING109product in which it is embedded. We found three different input routines in different parts of onedatabase program.For reading text data, various errors may arise relating to the length of the string or to special charactersthat cannot be entered. To enter such special characters or nulls, we may have to alter our inputmechanism. Typical approaches use some form of escape character that tell our program that a specialcharacter is coming.
For example, we could specify accents by using an escape character "\" (back-slash)then the letter of the alphabet, then a character defining an accent, such as \e’ to define é. Such tactics areneeded for entering characters that might stop execution.Of course, we sometimes have to halt our programs. For example, when a program prompts for a number,we may realize we need to look it up in a reference book, so wish to abort the run. This can sometimesbe impossible, short of switching the PC off. A good input routine has some mechanism for stopping aprogram.
However, the choices made by system implementors are not uniform. One interesting choice wasthat of Sinclair Research in the Sinclair ZX81 and Timex Sinclair 1000. The BASIC interpreter in these verysmall machines assumed all input was to be interpreted just like a program so the handler would acceptEXP ( -PI/4)as a valid numerical entry. To stop a program when it was prompting for data, the STOP keyword wasneeded rather than the BREAK key (Nash J C and Nash M M, 1982, 1983b).We strongly advocate (Nash J C, 1990b, 1990d, 1992) allowing programs to be controlled from a file, whichwe will call a script.
We can build various test scripts that include error conditions. We like to be able toinclude comments in input scripts (Section 9.6). We also insist (Section 9.6) that programs should be ableto copying all output to a file for later review. This is critical if we want to run programs in batch mode,but it simplifies verification of results.12.6 Testing — Sub-programsA well-defined sub-program makes testing easier, since we can focus on a smaller segment of code. Weneed to know all the possible inputs to a sub-program and the correct response to those inputs.
We mustalso be sure all required exits from the sub-program are correctly included.To test a sub-program, we can employ a dummy driver program that calls the sub-program with knowninput information and reports on the correctness of returned results. The biggest task, as in data entry,is to provide all possible cases. Users will eventually produce cases that match a given permutation ofconditions, however unlikely.
If our program prevents certain options, we do not have to test the subprogram for these. For example, in a subroutine to find the eigenvalues and eigenvectors of a realsymmetric matrix, we may choose not to verify symmetry if other program components guarantee thisproperty. However, if the subroutine becomes part of a general library of mathematical software, asymmetry test or a warning should be included.Structuring sub-programs (Sections 6.4 and 6.5) so that they have only one entry and one exit helps tocontrol the amount of testing required. However, we sometimes need failure exits from sub-programs. Inprogram libraries, handling errors is a major headache. There may be sophisticated mechanisms to carryout the task of reporting errors and stopping the program.
In a PC one can be much less fancy. A simplePRINT "message" and STOP suffices. The general library must allow the user program to regain controlafter an error has been detected. If we are writing both driver and sub-program, our decisions can bemade at the most convenient point in the program. We do not have to return to the driver programinformation as to where, when and how the program failed, and pass this back through two or threelevels of sub-programs to our driver program.As an example, suppose we are trying to calculate the so-called square root of a matrix A.
We shallassume A is real symmetric and positive definite, so that we can form an eigenvalue/eigenvector110Copyright © 1984, 1994 J C & M M NashSCIENTIFIC COMPUTING WITH PCsNash Information Services Inc., 1975 Bel Air Drive, Ottawa, ON K2C 0X1 CanadaCopy for:Dr. Dobb’s Journaldecomposition(12.6.1)A = V D VTwhere V is the matrix of eigenvectors andis then(12.6.2)D is the diagonal matrix of eigenvalues. The square root of AH = V S VTwhere(12.6.3)Sii =Dii = (Dii)1/2fori = 1, 2,.
. .,nas can be seen by forming(12.6.4)H H = V S VT V S VT = V S2 VT = V D VT = Aand using the fact that the eigenvectors of a real symmetric matrix are orthonormal. Suppose we have asubroutine to compute the square root of a matrix. If, unknown to us, A has negative eigenvalues,execution may halt when the square root of a negative number is attempted in a sub-program at least twocalls below the driver program. Preferably, our "matrix square root" subroutine will instead return to themain program with a flag variable set to indicate A is not positive definite.12.7 Testing — Complete ProgramsTesting a complete program is an extension of the ideas in the previous two sections. We must find allthe possible routes through the program and make sure all of them are valid and properly executed.Clearly it is worth keeping the control structure of the program simple.If we develop the main programs and sub-programs simultaneously, a top-down approach to testing maybe useful (Howden, 1982, p.
224). Program units under development are replaced by dummy routines thatmerely return the right results using sample inputs and outputs. This allows the calling program to betested independent of the sub-program. Once the sub-program is verified correct, we may substitute it forthe dummy routine. Expensive calculations may be avoided if we preserve the dummy program fortesting purposes.Test data sets and certified test results are valuable and difficult to come by. Such collections are notfrequently published, yet they form an important tool for building reliable and correct software.Programmers should carefully document and preserve such data sets.Examples of input and output help users of programs (Nash J C, 1992).
In particular, prepared scripts canbe used as a template for the user to develop the input data for a new problem.12.8 Production runsEven a properly implemented, fully tested program does not lead automatically to a correct solution ofa given problem. "Large" problems may not fit in the memory available despite our best efforts. Moreannoying may be the very slow progress of calculations, particularly if the solution method is iterativein nature.
Elapsed times of several hours are not uncommon when using PCs for difficult numericalproblems. If such a computation has been running for some time and another use for the PC arises, wemust decide whether to abandon the calculation in favor of the new task, thereby wasting the effort sofar expended.By modifying a program to save appropriate information at some point in the calculation, we can arrangefor it to be restarted without losing all the work done so far. This is worthwhile for "long" calculations.12: STEPS IN PROBLEM SOLVING111We run multiple calculations of a similar nature using a command script, either as a set of instructionsto the program or else a batch command file for the operating system that runs our program with differentdata sets.
In one case, we performed 6000 nonlinear least squares problems for a client in one week. Theoutput data filled all the available fixed disk space on our machines several times. We moved this outputonto diskettes in compressed form, automatically generating summary data for our client, and were ableto continue computations from the next case in the script.For one-off problems, we have found it most convenient to use packages that give us a high levelcomputing environment, such as Stata or MATLAB.
However, we like to use a command script to carryout the solution because we can store the script or incorporate it in our working documentation. It is tooeasy to forget the details of how we accomplished a solution. Although the script is only "used" once, itcan be referred to often. Truthfully, we cannot remember a computation that remained "one-off".12.9 Modifications and ImprovementsAfter a program has been used to solve problems, deficiencies will almost certainly become apparent. Theinput methods may be clumsy or error-prone.