Program Correctness Proofs in a
Computer Literacy Course
David Arnow
Department of Computer
and Information Science
Brooklyn College City
University of New York
Brooklyn, New
York 11210
e-mail: arnow@sci.brooklyn.cuny.edu
Abstract. Program correctness proofs have recently been
successfully added to Brooklyn College's required course on mathematical
and computer literacy for the general student. This topic significantly
integrates the mathematics topic of the course (logic) with one of the computer
science topics (programming).
The students are prepared mathematically for studying correctness proofs
through a treatment of elementary sentential logic that is presented both
in the context of and in contrast to everyday reasoning. Included in this
treatment are elementary logic proofs and problem-solving strategies appropriate
for constructing proofs.
Before doing program correctness proofs, students also study a very small
subset of a programming language, essentially consisting of assignment,
iteration and simple input/output. Iteration is always restricted to the
while loop, which is explained both operationally and, in an informal way,
axiomatically. Loop invariants are introduced from the outset. So far two
different languages have been used in this effort: Pascal and the Bourne
Shell language. Both seem to be equally effective.
The inclusion of program correctness proofs in the curriculum has been deemed
a success because testing and homework assignments show that all students
are able to understand what a program correctness proof is; most students
are able to fill in blank pieces of proofs that are partially done; about
a quarter of the students are able to write their own. The students are
for the most part urban working-class students, roughly 45% minority. Many
are immigrants from third world or eastern European countries.
This success has important lessons not just for computer literacy instruction
but for computer science instruction as a whole: students with weak academic
backgrounds can approach and appreciate this material, if it is presented
in the right way and if they are given the necessary prerequisite ideas.
Publication Information: This Brooklyn College Technical
Report was presented at the November 1992 IEEE Frontiers in Education conference
and appeared in the conference proceedings: Program Correctness Proofs in
a Computer Literacy Course. Proceedings of the IEEE Frontiers in Education
'92 Conference. Nashville, Tennesse, November, 1992.
Acknowledgment of Support: This work was made possible
by an undergraduate curriculum development grant from the National Science
Foundation , CISE Division (USE-9150719).
INTRODUCTION.
The goal of this project has been to incorporate a treatment of program
correctness proofs into a required general education course on mathematics
and computer science for non-science, non-math/computer science majors.
There were two reasons for undertaking this. First, although an earlier
version of this course successfully presented a number of important ideas
from computer science, it leaned far too much in presenting a strictly operational
view of programming. It was therefore desirable to balance this with a formal
or axiomatic view. Second, the mathematics part of the course is sentential
logic. It was useful apply the latter in an arena that the students had
not yet encountered (as distinct from logic proofs or geometry) but in one
that the students could quickly become familiar with in an informal way.
The population. The Brooklyn College students reflect an urban, ethnically
heterogeneous working-class population. The College ranks fourth in the
nation (including degrees issued from historically black colleges) in awarding
baccalaureate degrees to African-Americans. 21% of the undergraduates are
African-American, 11% are Hispanic and 11% are Asian. Many students are
immigrants and English is not the native tongue for many. 55% of our freshmen
are required to take remedial courses to correct skills deficits in mathematics,
reading or writing.
Most of our students have specific weaknesses that make the task appear
daunting. The students have very little experience with abstraction. The
course implementation has to take this into account in every topic. Every
abstraction, whether it is a rule of inference or an algorithm for multiplying
must first be introduced and afterwards reinforced with numerous concrete
examples. In teaching very elementary programming this is a situation that
is fraught with danger. That's because the most casual kind of concrete
approach to explaining programming language constructs and programs leads
very readily to a strictly operational view of the subject. The challenge
then is to be pedagogically concrete without having one's curricular goals
subverted.
Prior to this course most students have no experience with writing, reading
or understanding proofs or programs. Most do not know what a proof is and
have only a vague idea of what a program is.
The student population does, however, have special strengths of its own
that make the task easier to approach than it might be in other contexts.
First, there are no "hackers" (in the good sense of the word),
that is there are no students who see themselves as nearly expert programmers.
Such students typically have no patience with a disciplined approach to
programming, but rather are on the lookout in their classes for extra tricks
or hand-holding through new technology. Although some of our students are
often eager to write and run programs, none are in so much of a hurry that
they are unwilling to make what others might consider detours. Nor does
this population feel it has nothing to gain by learning about a systematic
approach- these students know they need all the help they can get in writing
programs.
The absence of experience with programming in general means that the students
are not wedded intellectually to the operational perspective in understanding
programs and programming language constructs. Only those who have attempted
to teach an axiomatic approach to students with years of operational-only
instruction can appreciate what an advantage this is. These students are
open to both approaches.
The majority of this population by definition will not take additional math
or computer science courses. This frees the course designer from the constraint
of coverage- there aren't a dozen topics that must be covered in preparation
for the next course. Thus, if a topic, such as program correctness proofs,
is deemed important, as much time as necessary may be taken to teach it
properly.
Furthermore, the rest of the course can be geared, at least in part, as
preparation for this topic.
PROGRAM CORRECTNESS PROOFS IN CS EDUCATION.
Since there is no consensus on the proper role of program correctness proofs
in computer science and software engineering, it not too surprising that
the place for this topic within the CS curriculum is disputed. Still, even
if it turned out that these proofs themselves have no value in day-to-day
practice, it is quite possible that the perspective that their study offers
would be of practical value. However, even if that were not the case, it
is still possible that their study by someone outside the field could clarify
the outsider's view of CS. That is the view that I take in this work. Furthermore,
the experience from this course has some bearing on the debate concerning
the place of correctness proofs in the CS curriculum. For, the success of
this work shows that teaching this material is possible, and so the debate
must center strictly on the value of the material, not its pedagogical feasibility.
CORRECTNESS PROOFS IN A GENERAL EDUCATION COURSE.
The course in question is an attempt appropriate place for mathematics and
computer science within Brooklyn College's widely recognized Core Curriculum
[for example, see Cheney, 1989], a set of specifically designed general
education courses that are required of all students at the college. In fact,
the design of this course was in part inspired by that of the required courses
in classics, history, music, political science and other liberal arts [Arnow,
1991]. Our main purpose is to offer the general student ideas from our discipline
that are interesting and of enduring value. This is the best way to
- attract undecided students to the fields of mathematics and computer
science,
- prepare those students as best as possible for future work in these
areas,
- encourage students who will enter scientific disciplines other than
mathematics and computer science to explore computer science further, and
- educate those students who will not go on to scientific or technical
fields to be able to make intelligent judgments about technically-based
issues.
Organization and topics of the course. The first half of the course
is a study of elementary propositional logic which emphasizes the connections
and differences between logic and "everyday" reasoning, the significance
of language and language issues such as ambiguity, the utility of symbolic
and formal methods, and the distinction between form and content. Though
that constitutes the mathematics component of the course, these themes are
repeated in the second half of the course, the computer science component.
The first part of the computer science component of the course includes
a discussion of machine representation of information, numeral systems,
logic gates and circuits. Here the students apply the logic introduced earlier
and learn to use Disjunctive Normal Form as a means of methodically designing
circuits.
Following this, the students are taught a tiny subset of the Pascal language:
integer variables, the readln, writeln, while statements, and comments.
This subset is taught in a relatively formal fashion. The tokens and token
classes are first introduced. After this, the syntax is introduced, and
then the semantics of the subset are explained. The concept of an invariant
is taught immediately, though informally, and the meaning of the while statement
is explained with an eye to the correctness proofs later in the course.
A number of programs which build on the theme of achieving complexity by
repetition of simple operations are developed. These invariably include
addition by repeated counting, multiplication by repeated addition, etc.
Since the student already has seen how hardware can add, he or she has a
vision of how operations as complicated as logarithms and exponents can
be carried out and how they ultimately are based on a few very elementary
primitives. These programs also serve as good examples for building programs
by identifying loop invariants.
In this context it is easy to see how important a discussion of correctness
proofs can be. For, on the one hand the first part of the computer component
shows the students how formal methods (truth tables, DNF, etc.) can be used
to design hardware. Failure to similarly put formal methods to good use
in the programming part would lead to the mistaken idea that programming
is a hit-or-miss affair or at least that program correctness is strictly
an empirical matter.
Correctness proofs also provide a good opportunity to demonstrate the importance
of mathematics. Students tend to accept computers as important because they
are highly visible. As was achieved in the discussion of circuits, correctness
proofs offer a concrete example of the utility of mathematics to other fields.
Finally, for this particular course, a discussion of program correctness
proofs offers a nice way of tying the various themes and ideas of the course
together. The students' understanding of proofs is reinforced in a new,
but accessible, context. The theme of building complex structures from simpler
ones (proofs from lemmas) and formalizing that which we understand formally
reoccur.
ACHIEVING SUCCESS.
To successfully teach this material it is necessary to ensure that the students
have the necessary intellectual background, to motivate the students and
alert them to the material's significance and to develop the material in
a step-by-step fashion so that the instructor is always communicating at
the level of the student.
Prerequisites. In the end we identified three areas that the students
needed to be familiar with in order to approach program correctness proofs.
First, they had to be familiar with logical connectives, negation, rules
of inference, and proofs. These concepts were already covered in the beginning
of the course, before correctness proofs were introduced into the curriculum.
Second, it turned out to be useful to explicitly discuss problem-solving
strategies in the context of writing proofs. In particular, the students
needed to learn to "work backwards", that is, given a desired
conclusion and a set of axioms and rules of inference, they had to be able
to construct the steps of a proof going from conclusion "backwards"
to axioms. This is essential is working with the assignment statement for
example. Before the inclusion of correctness proofs, the logic proofs handled
in the logic part of the course sufficiently simple that little explicit
attention was paid to strategy. Now we prepare students for working backwards
from the beginning of the logic part of the course by giving them "missing
premise" problems such as:
(1) If the polls are right then the challenger will win.
(2) missing premise
Conclusion: The polls were wrong.
Directions: Identify the (missing) premise that will make this a
valid argument.
So, by modifying the logic part of the course to rectify that omission,
the students were better prepared for correctness proofs.
Finally, students needed to be accustomed to making informal arguments about
the correctness of programs prior to being introduced to a more formal approach.
The idea of a loop invariant and the semantics of a while statement had
to be "second nature" to them. In order to guarantee this, the
part of the course that teaches elementary programming had to be modified
[Arnow, 1991].
Motivation. All students, even "motivated" students, need
challenging material to have a motivation. Motivating correctness proofs
is relatively easy. It is not hard to come up with famous example of software
catastrophes that students have either heard of or can readily appreciate.
Along with a brief discussion of society's increasing dependence on computer
software, this clearly underscores the importance of correct programs. The
inadequacy of (at least casual) testing for these student can be related
to fallacies they have learned earlier in the course:
If the program is correct then the test will succeed.
The test succeeds.
The program is correct. (Fallacy of Affirming the Consequent.)
And it is not hard to come up with examples that illustrate this.
Development of the material. Most important is the way the material
itself is taught. The material must be presented in small, easily digested
pieces. Students must have the opportunity to become familiar with essential
concepts and terminology before additional demands are made. A useful aid
for the instructor and the student, to ensure that these microsteps are
indeed microsteps and to verify that they have been mastered is the use
of checkpoint exercises. The remainder of this section describes the small
steps that we take and gives examples of checkpoint exercises for those
steps.
Acquaintance with correctness proofs. Before developing the topic
in any significant way, the students are introduced to the format we use
and to the idea of assertions about the values of variables at specific
points in the program text.
checkpoint exercise:
Given the following program fragment: #2 x:=5;
(for reference, statements are #3 y:=x+1;
numbered with sharp signs) #4 x:=x+y
and the proof fragment below, identify those assertions in the proof that
you would agree with
(ignoring the reason given for each step):
step assertion reason
(4) x<8 right after #2 [#2,1: rule]
(5) x>8 right after #3 [#3,1: rule]
(6) x>8 right after #4 [#4,1: rule]
(7) y=6 right before #3 [#3,1: rule]
(8) y<9 right after #3 [#3,1: rule]
Assignment statement structure. The student is reminded of the distinction
between the left and right hand sides of the assignment statement and is
introduced to the terminology "target" and "expression".
checkpoint exercise:
For each of the assignment statements below, identify the target and the
expression:
...
sum := a+b
...
The Assignment Rule. The student is introduced to the Assignment
Rule:
(1) assertion P involving expression e is true before statement
#N
(2) statement #N is x:=e
(conclusion) after statement #N any assertion Q is true provided that
Q can be transformed to P by replacing every mention of x with e.
terminology: the assertion with e in (1) is called the precondition
the assertion with x in the conclusion is called the post condition.
checkpoint exercise:
For each argument below, indicate whether or not it is a valid application
of the
Assignment Rule and explain.
...
(1) total=prod right before #3
(2) #3 is x:=y
(conclusion) total=prod right after #3
(1) x=z+w right before #8
(2) #8 is y:=x
(conclusion) y=z+w right after #8
(1) big<6 right before #9
(2) #9 is bigger:=big+1
(conclusion) bigger<7 right after #9
(1) y=z+4 right before #8
(2) #8 is y:=x
(conclusion) x=z+4 right after #8
Missing premise problems. The student has been familiar with this
type of problem from the beginning of the course. Now it is applied to the
assignment rule in preparation for developing proofs later on.
checkpoint exercise:
Missing Premise Problems. In the example below, there is a missing premise
(the precondition). Replace the question marks ??? with the missing premise
to
make the argument a valid application of the Assignment Rule.
(1) ???
(2) #8 is side1:=side2
(conclusion) side1>side3 right after #8
Checking proofs by examples. In this step, a rule is given for making
assertions about statements that are consecutive and the student is introduced
(again) to small proof fragments (concerning fragments of programs that
contain just assignment statements). This time however, the student is taught
to verify that the proof argument is a valid application of the assignment
and consecutive statements rules.
checkpoint exercise:
Given the following program fragment: #1 a := 1;
#2 b := 1;
#3 c := a+b;
check each step that involves the Assignment Rule by writing the step in
unabbreviated form and verifying that it is a proper application of the
rule:
Step Assertion Justification
(1) 1+1=2 before #1 [Kindergarten]
(2) a+1=2 right after #1 [#1,1: Assignment Rule]
(3) a+b=2 right after #2 [#2,2: Assignment Rule]
(conclusion) c=2 right after #3 [#3,3: Assignment Rule]
Writing small proof fragments. Having become familiar enough with
the assignment rule and the consecutive statements rule, and having become
experienced in checking proofs, the student starts to write her own.
checkpoint exercises:
Given the following program fragment: #1 count := 12;
#2 num := 0
prove that count+num=12 after #2
Given the following program fragment: #4 count := count-1;
#5 num := num+1
what precondition for #4 is required in order for count+num=12 right after
#5
Loop Invariants. The student has already been introduced to loop
invariants in the programming part of the course. In fact, students are
encouraged to use loop invariants to help guide them in writing their code.
Students are required to identify relevant loop invariants in any program
they submit. In this step, the students are given the "invariant rule"
which formally defines what is required for an assertion to be a loop invariant.
In practice, for the examples here, it means essentially writing two mini-proof
fragments: one to show that the assertion is true before the while statement,
the other to show that if it is true before the loop body, then it will
also be true after the loop body. We don't however yet demand that they
identify the loop invariant themselves (although many probably could already
do so.)
checkpoint exercise:
Given program fragment
prod:=0;
count:=0;
while count<a do begin
prod:=prod+b;
count:=count+1
end
show that prod=count*b is a loop invariant.
Loops. The "while rule" is given in this step: after the while
statement all loop invariants are true and the loop condition is false.
This is just a formalization of what the students have learned when the
while statement was introduced to them during the programming part of the
course.
checkpoint exercise:
In an earlier exercise you proved that quot*a+rem=b is a loop invariant
in:
quot:=0;
rem:=b;
while rem>a do begin
quot:=quot+1;
rem:=rem-a
end
Use that result as a lemma to prove that at the end of this fragment if
rem is equal to 0, quot=b/a.
DEFINING SUCCESS.
In teaching program correctness proofs, the naive, material-oriented definition
of success might be the ability of the student to be given a program and
write a correctness proof for it or to develop a correctness proof concurrently
with a program. However, in a project like this, it is important that success
be defined in a student-oriented way, that is in a way that takes into account
the students' needs and the purpose for providing them this material.
The students in this course for the most part will not be programmers and
computer scientists. They will certainly not need to write correctness proofs,
whether in conjunction with program development or not. The purpose for
including this material in the course is to present the formal view of programs,
to demonstrate the application of mathematics in computer science, and to
provide examples of proofs outside the areas that they have already experienced
(logic proofs in this course, possibly geometry proofs from earlier study).
To verify that these goals have been reached, it is not necessary to test
whether or not a student can develop a proof concurrently with a program.
PROBLEMS
The course in question is offered by the Math and Computer Science departments.
The latter, even with the nation-wide drop in computer science majors is
still understaffed with respect to its undergraduate and graduate programs.
Although the original mandate for the Brooklyn College Core Curriculum demanded
that only full-time faculty from an appropriate department teach the course,
fiscal and personnel realities force the department to staff the course
with adjunct instructors, graduate students and faculty from other departments
as well.
CONCLUSION
Mathematics and Computer Science. In Brooklyn College, the marriage
between mathematics and computer science in the general education course
has been an uneasy one. Some faculty (primarily from the math department)
have viewed the course as one where the computer is a tool for illustrating
mathematical concepts. Others (also from the math department) sought to
use the computer as an alternative approach to problem solving (simulation
vs. analysis). Neither view is appealing to computer science faculty who
want to provide a non-cookbook view of their field.
The success we have had in treating this topic indicates that another avenue
is available. That is, computer science can be treated mathematically, even
at this level. Again, illustration of mathematical ideas (proof, axioms,
etc.) is involved. However, the benefit to the teaching of mathematics but
goes beyond illustration: the students themselves are active and write proofs
(or parts thereof). They get an opportunity to apply these ideas to an area
that is both new to them but also concrete.
The benefit of this approach from a computer science point of view is clear.
Having studied programs from both an operational and a formal approach,
the students leave the course with a vision of computer science as both
an engineering and a mathematical discipline.
Feasibility of the topic. The experience at Brooklyn College shows
that teaching program correctness in a general education course is feasible
even for relatively weak students, provided that:
- attention has been given to providing the necessary background
- the topic has been presented in a sufficiently step-by-step fashion
- a student's success is not defined necessarily as the ability to develop
program and correctness proofs together from scratch (though many students
can do that) but rather as the ability to complete partially written proofs
and answer questions about proofs in a way that demonstrates an understanding
of the formal approach to programming.
These results also are important for the debate concerning the formal approach
among teachers of undergraduate computer science. For surely if the students
in the general education course can master this material, there is no question
that, if properly approached, computer science majors can as well. Feasibility
is not an issue; the debate must focus strictly on the merits of the formal
approach itself. For myself, just as I would find it regrettable for the
general education student to miss a chance to see both the formal and operation
approach, I find it unpardonable for computer science majors to lose that
opportunity.
Undertaking to teach program correctness proofs in this course would have
been impossible were it not for a conscious decision to take a principles-based
approach to the subject advocated by REFERENCE, and modified as described
in [Arnow, 1991]. This view of computer literacy, therefore, continues to
be rewarding both to instructor and student. The rewards, however, do not
have to stop here. Computer science and its intersection with mathematics
is an intellectually rich area that has only begun to be mined for the general
public. We are limited only by the finite number of credits in our courses
and by our relative inexperience in arranging and presenting the subject
matter.
Acknowledgments. Carroll Zahn of the Computer Science Department (Pace University)
first suggested to the author that a discussion of program correctness might
be appropriate for the general education course. Paula Whitlock of the Department
of Computer and Information Science (Brooklyn College) was foremost among
the Brooklyn College faculty in introducing this material in her classes
and in giving useful feedback on student response to the material.
References
[1] Alan W. Bierman, "An Overview Course in Academic Computer Science:
A New Approach for Teaching Nonmajors", The Proceedings of the Twenty-first
SIGCSE Technical Symposium on Computer Science Education, Louisville,
Kentucky, (March, 1990).
[2] Lynne V. Cheney, "50 Hours- A Core Curriculum for College Students",
National Endowment for the Humanities, (October, 1989).
[5] C. Van Dyke, "Taking 'Computer Literacy' Literally", Comm.
ACM, 30, 5, (May, 1987).
[3] J. Paul Myers, Jr., "The New Generation of Computer Literacy",
The Proceedings of the Twentieth SIGCSE Technical Symposium on Computer
Science Education, Louisville, Kentucky, (February, 1989).
[4] J. Paul Myers, Jr., "The Central Role of Mathematical Logic in
Computer Science", The Proceedings of the Twenty-first SIGCSE Technical
Symposium on Computer Science Education, Louisville, Kentucky, (March,
1990).
[5] C. Van Dyke, "Taking 'Computer Literacy' Literally", Comm.
ACM, 30, 5, (May, 1987).
[6] The National Commission on Excellence in Education, A Nation at Risk:
The Imperative of Educational Reform, U.S. Government Printing Office
(1983).
[7] National Research Council, Everybody Counts: A Report to the Nation
on the Future of Mathematics Education, National Academy Press (1989).
[8] Phyllis Keller, Getting at the Core: Curricular Reform at Harvard,
Harvard University Press (1982).
[9] William Dunham, A 'Great Theorems' Course in Mathematics, American
Mathematical Monthly (Dec. 1986).
[10] Alan Bierman, Great Ideas in Computer Science, MIT Press (1990).
[11] Evelyn Raskin and David R. Owen, Evaluation of the Core Curriculum,
Brooklyn College of the City University of New York (1988).
[12] Undergraduate Science, Mathematics and Engineering Education, National
Science Board, Pub. No. NSB 86-100 (1986).
[13] Report on the NSF Disciplinary Workshops on Undergraduate Education,
National Science Foundation, Pub. No. NSF 89-3 (1989).
[14] Report on the NSF Workshop on Undergraduate Science, Engineering and
Mathematics Education in Two Year Colleges, National Science Foundation,
Pub. No. NSF 89-50 (1989).
[15] Albert Y. Pang and William A. Malmgren, Experiments in Logic and
Computer Design, Prentice-Hall (1984).
[16] John Passafiume and Michael Douglas, Digital Logic Design: Tutorials
and Laboratory Exercises, Harper and Row (1985).
[17] David Arnow, The Iliad and the WHILE Loop,
SIGCSE (1991).
[18] Jean Buddington Martin and Kenneth E. Martin, A Profile of Today's
Computer Literacy Students: An Update, The Proceedings of the Nineteenth
SIGCSE Technical Symposium on Computer Science Education, (February,
1989).
[19] Antony Halaris and Lynda Sloan, Towards a Definition of Computing Literacy
for the Liberal Arts Environment, The Proceedings of the Fifteenth SIGCSE
Technical Symposium on Computer Science Education, (February, 1985).
[20] Shiela Tobias, They're Not Dumb, They're Different: a New Tier of Talent
for Science, Change 22, 4 (1990).
[21] David Gries and Dorothy Marsh, The 1989 Taulbee Report, Comm. ACM,
33, 9, (Sept., 1990).
Back to David Arnow's CS Education Page.
tc