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
-
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.
-
You should interpret the three input values as
a,
b,
and c
in a quadratic polynomial
a x**2 + b x + c
-
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.
-
Use the quadratic formula to compute the two roots of the quadratic
polynomial.
-
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.
-
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,f(xbegin + (k-1)*xinc))
(xbegin + k*xinc,f(xbegin + k*xinc)),
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
(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.
|
|
|
|
|