Go to USC home page USC Logo Computer Science & Engineering
UNIVERSITY OF SOUTH CAROLINA
CSE Home Page | CSE Research | CSE Site Map | CSE Faculty
CSCE 206
Scientific Applications
Programming Assignments
CSCE 206 web page

Caveat


This page will be changing throughout the semester as programming assignments are added.

Programming Assignment 1

Due date: 20 January 2005, noon

Your first assignment will test your ability to edit a program, compile the program, get the expected answer, and then submit the program into the departmental dropbox. The real reason for this assignment is not to test your ability to write programs, but to make sure that you gone through the process of writing and submitting programs done once correctly.

This assignment will not have the same point value as any of the other assignments, but it will have some point value. You cannot get credit for assignments that you can't get submitted, so this is your chance to practice the process and get credit for your effort.

First, create a program1 directory in your home directory on some unix machine.

Go to the sample programs directory, right click on the helloworld link, and download the helloworld program. Then right click on the makefile link, and download the makefile.

Move the downloaded sample program and the makefile into your new program1 directory. (Trust me--you will want to do each programming assignment in a different directory just to keep things neat and tidy.) ((A "directory" in unix is the same thing as a "folder" in Windows.))

Due to a braindamaged notion that Windows has about filename conventions, it is highly likely that the file you thought was named makefile has instead been named makefile.txt by the Windows system as the file was downloaded. (Windows has the mistaken notion that one of the immutable laws of the universe says that all filenames have a dot extension, so it adds the dot txt extension when it sees a filename without an extension.)

In Unix, to change the name of a file, you actually "move" the file using the mv command. Do this by issuing the command mv makefile.txt makefile. All unix commands like this are of the form

do_something_to_a_file from_filename to_filename.

You should now be able to compile and run the sample program. All you need to do now is to edit out my name from the program and insert your name so that your name gets printed instead of mine, and change the code so that you compute the square root of 20.25 instead of the square root of 64.0. (The correct square root is 4.5.)

Now use the CSE departmental dropbox to send your program and the makefile (do not forget the makefile) for grading.

RULES FOR SUBMITTING THINGS TO THE DROPBOX: As a general rule, you should submit to the dropbox whatever you think would justify your having a program that could be graded. If you submit only the C program, and in fact your makefile has some necessary but non-standard feature, then I won't be able to tell that that is the case unless you submit the makefile. If you use a file as test data, submit that as well. Things that get sent to the dropbox have a timestamp on them, and the dropbox has a close date, so this allows you to prove if necessary that you had a complete and running package before the submission date.


Programming Assignment 2

Due date: Friday 4 Feb 2005 noon

You are to write a program that will

  1. Read in lines of triples of values from a file. Each line of the file will have three floating point numbers in it. The last line of the file should contain the three sentinel values
    -9999.0 -9999.0 -9999.0
    that will cause your program to terminate normally.
  2. You should interpret the three input values as a, b, and c in a quadratic polynomial
    a x**2 + b x + c
  3. If the value of a is zero, then skip all three values, print a message that you are skipping the values (make sure you print the values themselves so you will know why you are skipping them), and go on to the next line.
  4. Use the quadratic formula to compute the two roots of the quadratic polynomial.
  5. Except that if the radicand of which you would take the square root is negative, then you can't take the square root. In this case, print the coefficient values and the value of the radicand, say that you are skipping on to the next line, and then skip to the next line.
  6. Assuming that you have managed to get this far, print a message with the three coefficients and the two roots.

You may cannibalise liberally from any of the cosine law programs that were used as examples. The only changes you should need to make to the cosine law program are to change the use of the cosine law to the use of the quadratic formula and to change the tests for what sorts of things to skip.


Programming Assignment 3

Text of programming assignment 3 Due date: Monday 21 Feb 2005 midnight

This is almost verbatim the programming assignment 5 from page 303 of the text.

The square root of a number N can be approxmiated by repeated calculation using the formula NG = 0.5 *( LG + N/LG) where NG stands for "next guess" and LG stands for "last guess." Write a function that calculates the square root R of a number N using this method. The difference between NG and LG should be checked to see whether these two guesses are almost identical. If they are, then NG is accepted as the square root and returned to the calling program as R.

If the difference between NG and LG is not "small" then the current "next guess" value should be assigned to the "last guess" variable and the formula should be iterated to come up with a new "next guess."

By "almost identical" we mean that the difference in absolute value is less than some value "epsilon" which is read in from the input file. You may take epsilon to be 0.0001.

Your input file should consist of the following. The first line should be the double-precision value of epsilon. The succeeding "some number" of lines should each contain the double-precision number of which to take the square root and the double-precision initial guess for the square root. If you have no clue as to what the square root should be, then use an initial guess of 1.0.

Your outer (main) program should read the input file and pass to the square-root-finding program the three parameters of epsilon, the number whose square root is to be computed, and the initial guess. The function should return the double-precision value of the square root.

The main program should print N and R and also check the square root to make sure that it really is a close approximation to the square root. If the absolute value of N - R^2 is greater than 5.0*epsilon then an appropriate message should be printed.

Issues to think about:

  • All parameters passed in should be passed by value, not by reference.
  • This function only has one value to return, so it can use the value of the function for that purpose. If you were returning two values and not one, you'd need to use call by reference for the values coming back to the calling program.
  • How much intermediate output do you wish to print from the square root function? How much is enough?
  • Your root-finding program is approximating the square root. If in fact you didn't have the sqrt function available, you'd have no way to tell whether your root was good except to test whether it squared to be close to the value of N. But testing whether N - R^2 is small is different from testing whether your last guess and next guess are close to one another.
  • How many iterations does it take to converge to a good value for the square root? How does this depend on the size of the number? How does this depend on the goodness of the initial guess?

SAMPLE INPUT AND OUTPUT EXISTS LINKED OFF THE SAMPLE PROGRAMS WEB PAGE.


Programming Assignment 4

Text of programming assignment 4 Due date: Friday 4 Mar 2005 noon

This assignment is very similar to problem 8, page 231 of the text.

The pressure of a gas changes as the volume and the temperature of the gas vary. Write a program that uses the van der Waals equation of state for a gas

(P + a*n^2/V^2) * (V - b*n) = n * R * T

to display in tabular form the relationship between the pressure and the volume of n moles of carbon dioxide at a constant absolute temperature T. The variable P is the pressue in atmospheres and V is the volume in liters. The van der Waals constants for carbon dioxide are

a = 3.592 L^2 * atm/mol^2

and

b = 0.0427 L/mol

Use

0.08206 L*(atm/mol)*K for the gas constant R. Inputs to the program include n, the Kelvin temperature, the initial and final volumes in milliliters, and the volume increment between lines of the table. Your program will display a table that varies the volume of the gas from the initial to the final volume in steps prescribed by the volume increment.

A sample set of input data and its corresponding output are available off the sample programs link.

IN THIS PART THE ASSIGNMENT DIFFERS FROM THAT IN THE BOOK. Your program should read lines of input data until no more data is found (that is, until EOF is encountered. For a sample of how to do this, look at the read3.c sample program in the list of programs that show how to read data in loops. Be careful with doing your reads this way, however. When you read two (say) variables in the scanf function, if the number of input items isn't even, then you'll have the last scan complete after scanning the last (and odd-numbered) value but the other variable will probably have a value left over from the previous scan.

Your output should be formatted as a table with a sufficient number of decimal places to be meaningful.

Your program should read the data in a main program and then pass the input data to a function (perhaps called printtable that does the computation and printing of the table.

Note that the book's problem uses (or seems to use) integer variables for the volume. You should instead be using double variables. Note, however, that there is a slight bug in the sample output in the last table. The increment is 0.1, and the last line, for 401.0 milliliters volume, is missing. This is due to a standard sort of problem in repeated addition of floating point values. We'll talk about this in class.

The data on which I run the program for grading will not have floating point increments of volume, so you don't have to get this tricky little detail done right...

NOTE: Many of you are still not taking this "programming" stuff seriously and are delaying the start of a programming assignment until the last minute. To control such behavior, I am instituting a new policy as of this programming assignment. The assignment is due at noon on Friday 4 March. Beginning noon on the previous Wednesday 2 March, I will answer no questions regarding the programming assignment except from students who have emailed me by noon on Tuesday 1 March a reasonable first draft of their program. That is, if you want to have access to answers from me subsequent to noon Wednesday, you must have started the assignment prior to noon Tuesday. You should consider this analogous to your English teacher's insistence on your turning in an outline for a term paper some weeks before the paper itself is due.


Programming Assignment 5

Text of programming assignment 5 Due date: Monday 21 Mar 2005 midnight

You are to write a program that will read in an array of data, use that data as the values of a function f(x) and then compute the area under the curve for f(x) using the Trapezoid Rule.

Your program must open a file presented as a command line argument to use as the data file. This can be done, and in fact should be done, exactly as in the commandlineargbetter.c sample program that you can find in the sample programs page. When your program is run for a grade, I will use files of my own choosing, with names of my own choosing, as input data.

Therefore please pay VERY CAREFUL attention to the way in which you open and close these data files. This is not hard, but it must be done carefully in order to be done right. And if you can't get this part right, you will lose about half credit on the assignment because your code won't do what it is supposed to do.

The input file will be as follows.

  • one data item, that we will call xbegin, that is the initial value of x
  • one data item, that we will call xinc, that is the increment value for x
  • one data item that is the number n of values of f(x) that follow
  • finally, there will be n lines each with a single value of f(x)

The interpretation of the data is that

  • the first of the n values of f(x) will be the y value for the pair (xbegin,f(xbegin)),
  • the second of the n values of f(x) will be the y value for the pair (xbegin + xinc,f(xbegin + xinc)),
  • the third of the n values of f(x) will be the y value for the pair (xbegin + 2*xinc,f(xbegin + 2*xinc)),
and so forth.

The Trapezoid Rule is a way to approximate the area under a function f(x). Given two pairs of data points with successive x-values, namely

    (xbegin + (k-1)*xinc,f(xbegin + (k-1)*xinc))
and
    (xbegin + k*xinc,f(xbegin + k*xinc)),

we can approximate the area under the curve by the trapezoid with corners at

    (xbegin + (k-1)*xinc,0))
    (xbegin + (k-1)*xinc,f(xbegin + (k-1)*xinc))
    (xbegin + k*xinc,f(xbegin + k*xinc)),
    (xbegin + k*xinc,0))

Since the area of a trapezoid is half the sum of the lengths of the two parallel sides times the perpendicular distance between the parallel sides, the area of this trapezoid is

    (1/2) * xinc * (f(xbegin + (k-1)*xinc) + f(xbegin + k*xinc))

The entire area under the curve is approximated by summing up all the trapezoidal areas for all the data points in the array. Take care with the fencepost errors.

With any program of this sort, it is helpful to be able to debug with data for which you know the correct answer. In this case, the data points of the input files xdata1, xdata2, and xdata3 come from the function x^2 + 3.0 * x + 5.0 sampled from 1 to 11 in increments of 1, 1/2, and 1/4, respectively. For those of you who have had integral calculus, the exact answer for the area is 673.333.

A second set of data files, ydata1, ydata2, and ydata3, contain data for the function exp(-x^2) whose integral. This function is always positive, and the area under this curve, taken from minus infinity to plus infinity, can be shown to be

    sqrt(pi/2).

(Note that in order for the Trapezoid Rule to work correctly you have to be careful about whether the function is positive or negative over a particular increment of delta-x. The functions we use here are always positive on the interval over which we are computing area.)

SAMPLE INPUT AND OUTPUT EXISTS LINKED OFF THE SAMPLE PROGRAMS WEB PAGE.


Programming Assignment 6

Due date: Thursday 31 Mar 2005 midnight

This is a generalization on the previous programming assignment in two ways.

First, the previous assignment had you read in a one-dimensional array of data that was the list of the dependent variable y = f(x) values for a sequence of equally spaced values of the independent variable x. In that program, the values of x weren't ever really "present"; they were merely implied. That is, the zero-th value of x is the value of xbegin which is actually xbegin + 0 * xinc, and the k-th value of x is actually xbegin + k * xinc. However, your program never actually needs to compute xbegin + k * xinc; that value is merely implied to exist in the k-th iteration of the loops.

Requiring your data to have been sampled at equally spaced x values may be too stringent.

This program requires you to read in coordinate pairs (x,y) and to store them in a two-dimensional array. Since you are reading in the exact values for the coordinates, you no longer need to read in the xbegin and xinc values; your input data consists exactly of the number of points in the first line followed by that many lines of floating point values two per line.

You should declare the 2-d array with fixed sizes in the main program and then pass the array as a parameter to the various functions that will need to use it. I recommend that you dimension the array to handle as many as 101 pairs of values. The second coordinate needs only two elements, one for the x and one for the y.

The second change from the previous program to the current program is that instead of approximating the area under the curve between TWO successive points with a trapezoid, you should approximate the area under the curve defined by THREE successive points using a quadratic polynomial.

Note that this requires the number of points to be ODD. Your first approximation will use points 0, 1, and 2 (three points). The second approximation will use points 2, 3, and 4 (total of five points). And so forth. A sophisticated program for computing area under a curve would take this into account and adjust for not having the "right" number of points. Your program should check to verify that the number of points is odd and instead should terminate if the number of points given is even.

In the sample programs location there is a template for much of what you will need for this program. There are also two input data files and corresponding output files.

Note 1: The function I have provided for finding the coefficients a, b, and c of the quadratic polynomial that passes through three data points (x1,y1), (x2,y2), and (x3,y3) uses a method known as Lagrange interpolation. We will go over this in class.

Note 2: Given a quadratic polynomial a*x^2 + b*x + c, that is always positive in an interval x1 to x3, the area under the quadratic over that interval is given by a*x3^3/3 + b*x3^2/2 + c*x3 - (a*x1^3/3 + b*x1^2/2 + c*x1). That is also given in a function in the sample code.


Programming Assignment 7

Due date: Friday 22 Apr 2005 midnight

This is a program aimed to give you experience reading and writing records, using a structure, from a file too big to sift through by hand. The data file is at xtestdata.

The data file consists of "some number" of records, one record per line. The record format is

  • The first line is the number N of records
  • Then are then N lines each with
    • label, 16 characters long
    • x, double floating point
    • y, double floating point
    • mean, double floating point
    • pertinence, long
    • irrelevance, long
    • obfuscation, double floating point

You are to write a program to read this file, using a structure for the record. Open the file and read the entire file. Then close the file. You may assume that there are no more than 1000 records in the entire file.

Then call a function to find the maximum and minimum values of the mean.

Then compute a tolerance value that is 3% of the absolute value of the maximum value of the mean.

Then compute an average mean value that is the arithmetic average of the minimum and maximum values of the mean.

Now go back through the array and print in formatted fashion. You should now be printing exactly those records for which the absolute value of the difference between the mean in the record and the average mean is less than the absolute value of tolerance. Further, if, for these records you are printing out, the irrelevance is less than or equal to 1000, you should print a star (asterisk) at the end of the output line. Sample output can be found at xtestout.

As a partial way of checking that your program is working, you can also add a multiplier to the tolerance. That is, instead of setting diff to be the difference of means and testing
if(diff <= fabs(tolerance))
you could write this as
if(diff <= mult*fabs(tolerance)).
With mult set to 1.0, you have the problem as posed above. With mult set to 1.5, you should get the sample output xtestout2.

Note that I have also printed out the successive min and max values as they have been computed.

You need to label the columns, and your output should indicate the absolute record count.

The following are some of the issues you will have to address in this programming assignment.

  • You will have to declare a new structure data type to hold one record, and then you will have to declare an array of this data type.
  • You would be advised first to try to reproduce the input data file with your own printing function. If you can create a copy of the input file, then you are probably reading that file correctly. If you cannot create a copy of the input, then you are probably not getting the input data read properly.
  • You will have to read up a little on formatting to make sure that you can print as needed.
  • You will have to read character strings. Note that there is one nasty little inconvenience in C that you may run up against. When you read formatted input (such as long or double variables) from a file in C, the file pointer is placed at the byte just beyond the end of the data you just read. If you read a line as formatted data, and you then wish to read characters, it can happen that the "next" character you read is the newline character at the end of a line of input. In order to read the next genuine line of data, it sometimes happens that you first have to read and throw away the newline character.
  • More such will appear here as I think of them.

Bonus Programming Assignment 8

Due date: 3 May 2005 2pm

A standard predator-prey model of biological populations is this. We assume an initial population of predator animals (foxes, for example) and an initial population of prey animals (rabbits, for example). If the net birth rate (births minus natural deaths) of the rabbits is B , then the differential equation of rabbits over time should be
d rabbit / d t = B * rabbit
That is, the instantaneous rate of change of rabbit is the constant net birth rate B times the current population rabbit . However, all else is not equal, and the rabbits face predation, so the actual rate of change of the rabbit population is
d rabbit / d t = B * rabbit - A * fox * rabbit ,
where A is a constant. That is, the number of encounters between foxes and rabbits is assumed to be dependent on the number of each, and some constant fraction A of those encounters results in death to the rabbit.

Now, on the other hand, besides four fingers and a thumb, we have a rate of change of the fox population. Assuming that the fox is not itself prey to some other animal up the food chain, the rate of change of the fox population can be approximated as
d fox / d t = A * fox * rabbit - C * fox .
That is, for every rabbit animal eaten by a fox , there is one more fox born, but of course the foxes are subject to a natural death rate C . (Yes, we could assume a different birth rate for foxes based on eating of rabbits, but for simplicity we will just use the A * fox * rabbit value instead of something more complicated.)

What we have, then, are two differential equations

d rabbit / d t = B * rabbit - A * fox * rabbit .
d fox / d t = A * fox * rabbit - C * fox .

In general, then, the obvious possibilities exist. More rabbits, then more food for foxes, so more foxes born. But more foxes means more rabbits eaten, so fewer rabbits, so fewer foxes born. Depending on the constants A,B,C we get stable (but usually oscillatory) populations of foxes and rabbits or else a catastrophic explosion in one or the other population. If the model stays stable, then the model may well continue to reflect reality long into the future. If the model explodes, of course, then at some point it no longer models the real world because we move outside the bounds over which the assumptions are valid. This basic coupling of two competing equations, however, is the simple version of virtually all modelling of real world events.

You are to write a program to run a predator-prey model. Assume an initial population (view populations as array variables over time) of
rabbit[0] = 10000
and an initial population of
fox[0] = 1000 .
Assume constants B = 0.005 , A = 6 * 10^(-6) , and C = 0.05 . These constants should be read in from a file. A sample file is xdata and sample output can be found at xsampleout.

Now start your simulation at time t = 0 . Your program will resemble the trapezoid rule integration program in the following sense. In the first time step from t = 0 to t = 1 , the rate of change of rabbits, for example, will be
B * rabbit[0] - A * fox[0] * rabbit[0]
so that the new value for the rabbit population at time t = 1 will be
rabbit[1] = rabbit[0] + (B * rabbit[0] - A * fox[0] * rabbit[0])
Similarly, you can compute for the fox population
fox[1] = fox[0] + (A * fox[0] * rabbit[0] - C * fox[0]) .

Now you are at time t = 1 and you have newly updated values for the fox and rabbit populations.

Do it again.

Run the model for 1000 time steps and print the values as you go. For the above constants, the model oscillates and is stable.

You should also try other constant values to verify that in fact your program can handle the two situations in which either the fox population or the rabbit population explodes.

Note: You do not necessarily need to use array variables for the fox and rabbit values. As long as you keep your timestepping correct, you can update the two and keep only an old and a new value for each. (You will need an old value and a new value because when you update the rabbit value you probably need to be using the old value and not the updated value in the calculation of the updated fox value.)

Note: All such simulations have a statistical probability of going berserk. If you run this out to time step 38430, the rabbit population goes negative.