🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.ai
Article #1182

Semantics & Provability

#1182
From: Mark William Hopkins
Date: Tue, 16 Jan 1990 02:55
200 lines
6493 bytes
     This is another forwarded response to a letter, which I feel might be of
general interest (the mail to this user bounced too).

From: gateley@m2.csc.ti.com (John Gateley)
Date: Mon, 15 Jan 90 10:20:15 CST
Subject: Re: Program verification is a proven concept

Hi Mark,

In article <1888@uwm.edu> you write:
>I must've missed the boat: I always prove my programs correct.  Pathologies
>in provability (which are theoretically guaranteed) almost always indicate
>flaws in design.  Therefore undecibeability is actually an AID in program
>verification, not an obstacle.

I am very curious: which language(s) do you program in, and could you
send me an example of a program plus proof?

Thanks,

john
gateley@m2.csc.ti.com

------------------------------------------------------------

The imperative languages I program in are C, and Pascal (and also the
assembly for the Intel 8051 family).

I'll send you a proof of a program segment illustrating some very basic rules:

PROVE:
N = 2; X = 4;
for (I = 0, Y = 1; I < N; I++; Y *= X);
printf("%d", Y);

PRINTS OUT THE VALUE 16.

(1) A for-loop in C is equivalent to a while loop (as specified in the K&R
reference).  Making the transformation specified in the source here gives:

N = 2; X = 4; I = 0; Y = 1;
while (I < N) {I++; Y *= X;}
printf("%d", Y);

(2) Under certain conditions (not to be delineated here) as assignment
                              V op= C
is equivalent to
                             V = V op C
These conditions are met here.  Likewise I++ transforms to I = I + 1 in this
context.  This results in:

N = 2; X = 4; I = 0; Y = 1;
while (I < N) {I = I + 1; Y = Y * X;}
printf("%d", Y);

The conditions, or course, relate to the possibility to side-effects, such as
in
			      V += V++ - --V;

An algebraic rule to handle this would be implementation dependent.  For
example, if a compiler evaluates from left-to right, the assignment above
might be reducible successively to:

       x1 = V++;            x2 = --V;          V += x1 - x2;

   x1 = V; V = V + 1;   V = V - 1; x2 = V;    V =  V + x1 - x2;

	x1 = V;                x2 = V;          V = V + x1 - x2;
(notice the cancellation)

		           V = V + V - V;

			       V = V;

				 ; (the null statement)

where x1, and x2 are variables not occurring elsewhere in the program.

(3) A while-loop is equivalent to an INFINITELY nested sequence of
if-statements expressed recursively by the following rule:

while (B) do S  ==  if (B) {S; while (B) do S}
i.e.
      if (B) {S; if (B) {S; if (B) {S; ...}}}

This rule will be used in the following reductions below.

(4) The following are equivalent:

if (B) S1; else S2; T  ==  if (B) {S1; T} else {S2; T}

applied in the case of the sequence:

while (I < N) {I = I + 1; Y = Y * X;}
printf("%d", Y);

this produces an infinitely-nested series of branches defined recursively by:

xx = if (I < N) {I = I + 1; Y = Y * X; xx} else printf("%d", Y);

(5) A rule analogous to the BETA REDUCTION rule applies for assignment
statements of the form: Simple-Variable = Expression.  When used on the
sequence:

N = 2; X = 4; I = 0; Y = 1; xx

(with xx defined as above), this gives the successive reductions:

N = 2; X = 4; I = 0; Y = 1; xx
->
X = 4; I = 0; Y = 1; xx'
->
I = 0; Y = 1; xx''
where xx', xx'' are defined by

xx' = if (I < 2) {I = I + 1; Y = Y * X; xx'} else printf("%d", Y);
xx'' = if (I < 2) {I = I + 1; Y = Y * 4; xx''} else printf("%d", Y);

I = 0; Y = 1; xx''
->
Y = 1; if (0 < 2) {I = 0 + 1; Y = Y * 4; xx''} else printf("%d", Y);
->
if (TRUE) {I = 1; Y = 1 * 4; xx''} else printf("%d", 1);
->
I = 1; Y = 4; xx''
->
Y = 4; if (1 < 2) {I = 1 + 1; Y = Y * 4; xx''} else printf("%d", Y);
->
if (TRUE) {I = 2; Y = 4 * 4; xx''} else printf("%d", 4);
->
I = 2; Y = 16; xx''
->
Y = 16; if (2 < 2) {I = 2 + 1; Y = Y * 4; xx''} else printf("%d", Y);
->
if (FALSE) {I = 3; Y = 16 * 4; xx''} else printf("%d", 16);
->
printf("%d", 16);
->
printf("16");

These are very fine-grained steps, however.  In their place, and based directly
on the rules used in manipulating the loop, there is a more general theorem
that can be used to generate a system of Diophantine equations from this
loop. 
   More generally, the rules only provide a theoretical foundation, and are
not to be used on a practical level -- so there are more powerful tools of
analysis that can be developed, based directly on them, that can be used in
their stead.
   For example (3), (4) and other identities involving control-constructs can
be used as the basis for transforming and optimizing control-constructs.  I've
used this once to transform a C code segment from:

NameInsert(N, Head, Tail)
struct NameList *N, **Head, **Tail;
{
   if (*Tail == 0) {
      N->Prev = N->Next = 0; *Head = *Tail = N;
   } else {
      (*Head)->Prev = N; N->Prev = 0;
      N->Next = *Head; *Head = N;
   }
}

NameDelete(N, Head, Tail)
struct NameList *N, **Head, **Tail;
{
   if (N->Prev == 0)
      if (N->Next) {
         *Head = N->Next; N->Next->Prev = 0;
      } else *Tail = *Head = 0;
   else if (N->Next == 0)
      if (N->Prev) {
         *Tail = N->Prev; N->Prev->Next = 0;
      } else *Tail = *Head = 0;
   else {
      N->Prev->Next = N->Next; N->Next->Prev = N->Prev;
   }
}

to:

NameInsert(N, Head, Tail)
NameList N, *Head, *Tail;
{
   if (*Tail == 0) *Tail = N; else (*Head)->Prev = N;
   N->Prev = 0; N->Next = *Head;
   *Head = N;
}

NameDelete(N, Head, Tail)
NameList N, *Head, *Tail;
{
   if (*Head == N) *Head = N->Next; else N->Prev->Next = N->Next;
   if (*Tail == N) *Tail = N->Prev; else N->Next->Prev = N->Prev;
}

The software this came from was a 100k teleconferencing program, which I
optimized to under 50k and verified, there were a couple other (valid)
assumptions that were needed to make the transformation above.
Technical Details
Message-ID: <1908@uwm.edu>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uwm.edu!csd4.csd.uwm.edu!markh
References: <18883@bcsaic.UUCP> <1863@osc.COM> <1623@castle.ed.ac.uk>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uwm.edu!csd4.csd.uwm.edu!markh
From: markh@csd4.csd.uwm.edu (Mark William Hopkins)
Newsgroups: comp.ai
Subject: Semantics & Provability
Keywords: meaning, symbol, understanding
Message-ID: <1908@uwm.edu>
Date: 16 Jan 90 02:55:13 GMT
References: <18883@bcsaic.UUCP> <1863@osc.COM> <1623@castle.ed.ac.uk>
Sender: news@uwm.edu
Reply-To: markh@csd4.csd.uwm.edu (Mark William Hopkins)
Organization: University of Wisconsin-Milwaukee
Lines: 200