Projecting Programs On Specifications Definitions and Applications
Projecting Programs On Specifications Definitions and Applications
Jules Desharnais
Département d’informatique et de génie logiciel, Université Laval, Québec, Canada
[email protected]
Nafi Diallo
New Jersey Institute of Technology, Newark, NJ
[email protected]
Wided Ghardallou
Faculté des Sciences de Tunis, El Manar, Tunisia
[email protected]
Ali Mili
New Jersey Institute of Technology, Newark, NJ
[email protected]
Abstract
Given a specification R, it is common for a candidate program P to be doing
more than R requires; this is not necessarily bad, and is often unavoidable, due
to programming language constraints or to otherwise sensible design decisions.
In this paper, we introduce a relational operator that captures, for a given
specification R and candidate program P , the functionality delivered by P that
is relevant to R. This operator, which we call the projection of P over R (for
reasons we explain), has a number of interesting properties, which we explore
in this paper.
Keywords: absolute correctness, relative correctness, refinement, projection,
lattices.
2
2. Mathematical Background
3
The following laws of relation algebra are used in the sequel. The first two
are laws of Boolean algebra; other laws of Boolean algebra will be invoked by
the simple mention “Boolean algebra”.
P ⊆ R ⇒ P R ⊆ QR,
P ⊆ R ⇒ RP ⊆ RQ.
4
RL ∩ R ∪ RL ∩ R′
= {(6) and hypothesis RL ∩ R′ ⊆ R}
R.
Hence R′ refines R.
Proof of Necessity. Let R′ refine R; we must prove RL ⊆ R′ L and RL ∩R′ ⊆
R. For the first clause, we proceed as follows:
RL
= {hypothesis and Definition 1}
(RL ∩ R′ L ∩ (R ∪ R′ ))L
= {(10)}
RL ∩ R′ L ∩ (RL ∪ R′ L)
= {RL ∩ R′ L ⊆ RL ∪ R′ L}
′
RL ∩ R L.
Hence (by set theory) RL ⊆ R′ L. For the second clause, we proceed as follows:
RL ∩ R′
⊆ {monotonicity of product}
RL ∩ (R ∪ R′ )
= {since RL ⊆ R′ L}
RL ∩ R L ∩ (R ∪ R′ )
′
5
• Two relations R and R′ have a least upper bound if and only if they
have an upper bound. Consequently, if R and R′ satisfy the consistency
condition and R refines Q and R′ refines Q′ then a fortiori Q and Q′ satisfy
the consistency condition. Conversely, as we refine R and R′ , we make it
less and less likely that they satisfy the consistency condition.
• The empty relation is the universal lower bound of this ordering.
• This ordering admits no universal upper bound. Total deterministic rela-
tions are the maximal elements of this ordering.
The way we model specifications, programs, refinement and correctness dif-
fer from traditional models, such as Hoare’s Unified Theory of Programming
[9], Hehner’s Practical Theory of Programming [7], Morgan’s Programming from
Specifications [17], and others. The simplest and most concise, though not neces-
sarily the most precise, way to characterize our programming model by contrast
with traditional models is to consider how a (pre-condition/post-condition) pair
is mapped into a relational specification. We consider a precondition under the
forms of a unary predicate P (s) on S and a post-condition under the form of
a binary predicate Q(s, s′ ) on S. Whereas traditional models interpret this
(P (s), Q(s, s′ )) pair as the relation
{(s, s′ )|P (s) ⇒ Q(s, s′ )},
we interpret it instead as the relation
R = {(s, s′ )|P (s) ∧ Q(s, s′ )}.
Consequently, in our model P (s) is actually redundant: if we redefine the post-
condition as Q′ (s, s′ ) ≡ P (s) ∧ Q(s, s′ ) then the precondition is merely the
characteristic predicate of the domain of R.
This distinction is important because, not surprisingly, it has an impact on
the way that refinement is defined. Any definition of refinement must acknowl-
edge the contravariant role of the pre-condition and the post-condition: Indeed,
one makes a specification more-refined by weakening the pre-condition and(or)
by strengthening the post-condition. In traditional models, the contravariance
is built into the relational form of the specification (by the ⇒ connective);
hence refinement takes the simple form of logical implication. By contrast, in
our model the contravariance is expressed by the definition of refinement: In
fact the two terms of the formula RL ⊆ R′ L ∧ RL ∩ R′ ⊆ R express exactly
the property that the pre-condition of R′ is weaker and the post-condition is
stronger.
The absence of a miracle specification stems from the same decision as
above: Because we map a pre/post specification (P (s), Q(s, s′ )) into the rela-
tion {(s, s′ )|P (s) ∧ Q(s, s′ )}, we have no way to distinguish between the miracle
specification (true, f alse) and the trivial/ bottom specification (f alse, true). In
our model, the bottom specification is the empty relation, but there is no top/
miracle specification, as no relation can be total (i.e. have S for a domain) and
yet assign no image to the elements of its domain. Maximal elements in our
refinement ordering are total deterministic relations.
6
3. Absolute Correctness and Relative Correctness
7
This definition is consistent with traditional definitions of partial and total cor-
rectness [4, 5, 6, 8, 14]. Whenever we want to contrast correctness with partial
correctness, we may refer to it as total correctness. The definition of partial
correctness in Definition 2 links it to total correctness. The traditional defini-
tion of partial correctness is that program p is partially correct with respect to
specification R if and only if RL ∩ P ⊆ R. Proposition 1 then displays the link
in a different manner by showing that total correctness is partial correctness
plus the constraint that the domain of the program is at least as large as that
of the specification.
The following proposition, due to [16], gives a simple characterization of
correctness for deterministic programs.
Proposition 2. Program p is correct with respect to specification R if and only
if (R ∩ P )L = RL.
Note that because (R ∩ P )L ⊆ RL is a tautology (by Boolean algebra and
monotonicity of product), the condition above can be written as: RL ⊆ (R ∩
P )L; by (7), this condition can be written as R ⊆ (R ∩ P )L. Note also that
the condition set forth in this proposition holds only because P is deterministic;
in general, (R′ ∩ R)L = RL is not equivalent to R′ ⊒ R. From Definition 2
and Proposition 2 we infer that program p is partially correct with respect to
specification R if and only if (R ∩ P )L = RL ∩ P L. Interestingly, this condition
is equivalent to: P and R satisfy the consistency condition.
8
R P P′
0 :
0 0 XXX 0 0 :
0
XX
XXX
z
1 XXX :
1 1 XXX 1 1 :
1
X
X
X XX
XXX
XX
z z
2 XXX :
2 2 XXX 2 2 :
2
X
X
X XX
XXX
XX
z z
3 XXX :
3 3 XXX 3 3 :
3
X
XX
XX
XXX
XX
z z
4 XXX :
4 4 XXX 4 4 :
4
X
XX XX
XXX
XX
z z
5 5 5 XXX 5 5 :
5
XX
XXX
z
6 6 6 6 6 6
(R ∩ P ′ )L = {1, 2, 3, 4, 5} × S,
where S = {0, 1, 2, 3, 4, 5, 6}. Hence p′ is more-correct than p with respect to R.
In order to highlight the contrast between relative correctness and absolute
correctness, we consider the specification R on the space S of natural numbers
R = {(s, s′ )|s2 ≤ s′ ≤ s3 },
and we consider the following programs, where along with each program we
indicate its function, then its competence domain with respect to R:
p0 : abort. P0 = φ. CD0 = ∅.
p1 : s:=0. P1 = {(s, s′ )|s′ = 0}. CD1 = {0}.
p2 : s:=1. P2 = {(s, s′ )|s′ = 1}. CD2 = {1}.
p3 : s:=2*s**3-8. P3 = {(s, s′ )|s′ = 2s3 − 8}. CD3 = {2}.
p4 : skip. P4 = I. CD4 = {0, 1}.
p5 : s:=2*s**3-3*s**2+2. P5 = {(s, s′ )|s′ = 2s3 − 3s2 + 2}. CD5 = {1, 2}.
p6 : s:=s**4-5*s. P6 = {(s, s′ )|s′ = s4 − 5s}. CD6 = {0, 2}.
p7 : s:=s**2. P7 = {(s, s′ )|s′ = s2 }. CD7 = S.
p8 : s:=s**3. P8 = {(s, s′ )|s′ = s3 }. CD8 = S.
s2 +s3
p9 : s:=(s**2+s**3)/2. P9 = {(s, s′ )|s′ = 2 }. CD9 = S.
Figure 2 shows how these ten programs are ordered according to their relative
correctness with respect to R; in this sample, programs P7 , P8 , P9 are (abso-
lutely) correct while programs P0 , P1 , P2 , P3 , P4 , P5 , P6 are incorrect because
their competence domain is strictly smaller than the domain of R, which is S.
Of the latter, only P0 is partially correct.
9
P7 , P8 , P9
@
@
@
@
@
@
@
@ @
P6 @ @
P4 @ @ P5
@ @
@ @
@ @
@ @
@ @
@ @
P1 @ P3
@ @
@ @ P2
@ @
@ @
@
@
@
@
@
@
P0
10
3.4. Relative Correctness: Non-Deterministic Programs
In this section we extend the definition of relative correctness to non-deter-
ministic program. There are several reasons why this is important/useful:
• Non-determinacy is a convenient means to model deterministic programs
whose detailed behavior is difficult to capture, unknown, or irrelevant to
a particular analysis.
(R ∩ P )L ⊆ (R ∩ P ′ )L
and
(R ∩ P )L ∩ R ∩ P ′ ⊆ P.
Interpretation: P ′ is more-correct than P with respect to R if and only if
it has a larger competence domain, and for the elements in the competence
domain of P , program P ′ has fewer images that violate R than P does. As an
illustration, we consider the set S = {0, 1, 2, 3, 4, 5, 6, 7} and we let R, P and P ′
be defined as follows:
R = {(0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (2, 1), (2, 2), (2, 3), (3, 2), (3, 3), (3, 4),
(4, 3), (4, 4), (4, 5), (5, 4), (5, 5)}
P = {(0, 2), (0, 3), (1, 3), (1, 4), (2, 0), (2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (5, 2),
(5, 3)}
P ′ = {(0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 3), (3, 1), (3, 4), (4, 2), (4, 5), (5, 2),
(5, 3)}.
From these definitions, we compute:
R ∩ P = {(2, 1), (3, 2)},
(R ∩ P )L = {2, 3} × S,
R ∩ P ′ = {(1, 2), (2, 3), (3, 4), (4, 5)},
(R ∩ P ′ )L = {1, 2, 3, 4} × S,
(R ∩ P )L ∩ P ′ = {(2, 0), (2, 3), (3, 1), (3, 4)},
(R ∩ P )L ∩ R ∩ P ′ = {(2, 0), (3, 1)}.
11
0 XXX R - P P′
:0 H H
0Z 0 0Z 0
X
X
XX
H
ZH
* H
ZHH
*
X- ZHH
1X
XX
z
X
:1 1ZH ZH :
1 1X Z H
HXXZHH 1
X H H*
HX *
XXX
Z
H Z
H>
H X
ZX X
H
X-
z
X
ZH Z H
H
j H
HZZXX
j
H
z
X
2 XX
:2 2 Z H
Z
:2 2XX
X HH 2
X
H*
X *
XXX Z
Z
H
>
~
Z
XX Z
H
X
>
~
Z
X-
z
X
Z j
H j
H
XX
z
X
3 XX
:3 3
Z
Z 3 3XX
X 3
X
X * X
XX *
XXXX
Z
~ XXX
4X
XX
z
-
:4 4 XX
z
X
4
4 X
X
4
XXXX X XXXX
z
X z
5 - 5 5 5 5 5
12
Since ⊒R is reflexive and transitive, it is a preorder; we use this preorder to
define an equivalence relation, as follows:
Definition 5. Two programs P and P ′ are said to be equally correct with re-
spect to specification R (abbrev: P ≡R P ′ ) if and only if P ⊒R P ′ and P ′ ⊒R P .
For deterministic relations P and P ′ , equal correctness simply means having
the same competence domain; the following proposition characterizes equal cor-
rectness for arbitrary (not necessarily deterministic) programs.
Proposition 4. Let R be a specification on space S, and let P and P ′ be can-
didate programs on S. Then
(P ≡R P ′ ) ⇔ (R ∩ P )L = (R ∩ P ′ )L ∧ (R ∩ P )L ∩ R ∩ P = (R ∩ P ′ )L ∩ R ∩ P ′ .
Proof. From P ≡R P ′ we infer readily that P and P ′ have the same competence
domain with respect to R. Also, from (R ∩ P )L ∩ R ∩ P ′ ⊆ P and (R ∩ P )L =
(R ∩ P ′ )L we infer:
(R ∩ P ′ )L ∩ R ∩ P ′ ⊆ (R ∩ P )L ∩ R ∩ P.
By interchanging P and P ′ and combining the two results, we find:
(R ∩ P ′ )L ∩ R ∩ P ′ = (R ∩ P )L ∩ R ∩ P.
The converse implication is trivial, if we replace equality by inclusion, and note
that an intersection is a subset of its terms. qed
13
Proposition 5. The projection of a program P on a specification R (viewed as
a function of P ) is idempotent, i.e. ΠR (ΠR (P )) = ΠR (P ).
Proof.
ΠR (ΠR (P ))
= {definition of ΠR }
(R ∩ ΠR (P ))L ∩ (R ∪ ΠR (P ))
= {definition of ΠR }
(R ∩ (R ∩ P )L ∩ (R ∪ P ))L ∩ (R ∪ (R ∩ P )L ∩ (R ∪ P ))
= {Boolean algebra}
((R ∩ P )L ∩ R)L ∩ (R ∪ (R ∩ P )L ∩ P )
= {(11)}
(R ∩ P )L ∩ RL ∩ (R ∪ (R ∩ P )L ∩ P )
= {monotonicity of product and Boolean algebra}
(R ∩ P )L ∩ (R ∪ (R ∩ P )L ∩ P )
= {Boolean algebra}
(R ∩ P )L ∩ (R ∪ P )
= {definition of ΠR }
ΠR (P ) qed
Whereas P and P ′ may fail to have a join (due to divergent designs), their
projections on R do not (since they only reflect subspecifications of R).
14
Corollary 2. Given a specification R and a candidate program P , the projec-
tion of P over R is refined by the meet of P and R, i.e. R ⊓ P ⊒ ΠR (P ). In
addition, if P and R satisfy the consistency condition, then R ⊓ P = ΠR (P ).
15
(R ∩ P )L = (R ∩ P ′ )L ∧ (R ∩ P ′ )L ∩ P ′ ⊆ R ∪ P
⇒ {(R ∩ P )L = (R ∩ P ′ )L and Boolean algebra}
(R ∩ P )L ⊆ P L ∧ (R ∩ P )L ∩ P ′ ⊆ (R ∩ P )L ∩ (R ∪ P )
′
16
R P P′
0 XXX -
:0 :0
0H 0 0H
X
X ZH @HH
XXXX ZHH
@H
1X
XX
z
-
:1
1X Z
HXXZHH -1 1H @ HH-
:1
XX HHXX H
ZXX HH H
XXXX
z H Z XHH
j
z
X
@
H@
Hj
H
2 XXX -
:2
2XHXX HHZ - 2 2H H -
:2
XX HHXXXHZ H
HH
H
XXXX H
XX>
~
Z @ HH
z
- H j
H
X
z HH @ -
j
3 XXX
:3 3XHXX HH - 3 3H
H
@:
3
X
X HHXXXH
* HH *
H@
R
XXXX X
H
H X-j
H Hj
H
4 XXX
z
- XX H H
z
X H
H -
X
:4
4 XX
X H
4
4
HH
4
X
XX XXH H
X-
z
X j
H
XX
z j
H
5 5 5 5 5 5
ΠR (P ) = ΠR (P ′ )
0
:0
1X -
HXX
HHXX
:1
XX
H XX
z
2HXX HH-
X :2
HHX H
XX H
HH XX j
H
z
X
3X
HXX H
-
:
3
HHXX
H
X HH
H XXj
z
X
-
XXX HH
4
XXXH
4
HH
XXj
z
X
5 5
17
⇔ {definition of ⊒R }
P ′ ⊒R P . qed
Figure 5 captures the result of Proposition 10, along with that of Corollary 2
in graphic form. The chart on the left shows the configuration of a specification
R and a candidate program P when they are unrelated; in that case, according
to Corollary 2, the meet of R and P refines the projection of P on R. The
chart in the middle shows the configuration of R and P when they meet the
consistency condition; for a deterministic program P , the consistency condition
18
R, P arbitrary P partially correct wrt R P (totally) correct wrt R
R P R P P
• • • • •
A@ @
A@ @
A @ @
A @R ⊓ P @
A @• @•
A R ⊓ P = ΠR (P )
A
A
A
A• •
ΠR (P ) R = R ⊓ P = ΠR (P )
19
66
R D
-
6 E
Equivalence class,
modulo ≡R
ΠR (P ) P
not fulfilled by P ). The oval in this figure represents programs that are equally
correct, as they all have the same projection on R; the least-refined element of
each oval is the projection (Proposition 8); farther elements may be refinements
of the projection, but they are not more-correct than the projection.
20
∩ {(s, s′ )|x′ = x + y ∧ z < z ′ }
= {simplification}
{(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ z < z ′ }.
P1 = {(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z + 1}
∪ {(s, s′ )|y < 0 ∧ x′ = x ∧ y ′ = y ∧ z ′ = z + 1}.
21
R
=ΠR (P2 )
6
6 P2
ΠR (P0 )
*
=ΠR (P1 )
6 P1 P0
ΠR (P3 ) :
6 P3
ΠR (P4 )
- P4
22
We find that the projection of P3 on R is less-refined than the projection of
P0 and P1 on R, hence we conclude that P0 and P1 are both more-correct than
P3 with respect to R. See Figure 7.
Finally, we consider the following program:
while (y!=0) {x:=x+1; y:=y-1}
The function of this program is:
23
5.1. Refining a Projection
Proposition 9 provides that a program P ′ is more-correct than a program
P with respect to some specification R if and only if the projection of P ′ on
R refines the projection of P on R. But in practice, we find it convenient to
reason about relative correctness on the basis of a lower bound of P ′ , rather
than a lower bound of the projection of P ′ . The following proposition provides
this lower bound.
where the fist step uses (12) and (9), the second one Boolean algebra and mono-
tonicity of product, the third one the assumption of determinacy of P and
monotonicity of product, and the last one Boolean algebra. Thus, by Boolean
algebra,
(R ∩ P )L ∩ (R ∪ P ) = (R ∩ P )L ∩ R ∪ (R ∩ P )L ∩ P ⊆ R ∪ R = R.
24
5.2. Program Merger
Given a specification R and two candidate programs P and P ′ , imagine that
each of P and P ′ delivers some (but not all) of the functionality mandated by
R, and we are interested to derive a program that delivers all of the relevant
functionality of P and all of the relevant functionality of P ′ ; we refer to this
composite program as the merger of P and P ′ .
Definition 7. Given a specification R and two candidate programs P and P ′ ,
a merger of programs P and P ′ is a program P ′′ that is more-correct than P
and more-correct than P ′ with respect to R.
The first step in deriving the merger P ′′ of P and P ′ is to compute the specifi-
cation that P ′′ must satisfy. A naive approach would be to let the specification
of the merger be the join of P and P ′ . But this approach ought to be ruled out
for several reasons:
• The join of P and P ′ may not exist; we show an example below of such a
situation.
• When the join of P and P ′ does not exist, it is usually because of an
incompatibility between the design of P and the design of P ′ ; it is never
due to an incompatibility between specification-relevant behaviors of P
and P ′ .
A more interesting approach to the merger is to let the specification of the
merger be the join of the projections of P and P ′ over R; this approach has the
following advantages:
• According to Corollary 1, the projections of P and P ′ over R satisfy the
consistency condition, hence they necessarily admit a join.
• According to Proposition 6, the projections of P and P ′ over R are less-
refined than, respectively, P and P ′ . Less-refined specifications are easier
to satisfy because they impose fewer/weaker requirements.
• The projections of P and P ′ on R only capture requirements information
that is relevant to R, and exclude any information that may stem from
design decisions that have been taken in the derivation of P and P ′ .
• According to Proposition 11, if P ′′ refines the projections of P and P ′ on
R, then it is more-correct than P and P ′ .
• According to lattice theory, in order for P ′′ to refine the projections of P
and P ′ on R, it suffices that P ′′ refines their join.
We consider the following example: Let S be the space defined by variables x,
y and z of type integer, and let R be the following specification on S:
R = {(s, s′ )|x′ = x + y ∧ z 6= z ′ }.
25
We let p and p′ be the following candidate programs on S:
p : z:=z+1; while (y!=0) {x:=x+1; y:=y-1},
p′ : z:=z-1; while (y!=0) {y:=y+1; x:=x-1}.
The functions of p and p′ are, respectively:
P = {(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z + 1}
P ′ = {(s, s′ )|y ≤ 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z − 1}
We compute the projections of P and P ′ on specification R. We find:
ΠR (P )
= {definition of ΠR , substitution and simplification}
{(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z + 1} ◦ L ∩ (R ∪ P )
= {computing the domain}
{(s, s′ )|y ≥ 0} ∩ (R ∪ P )
= {since P ⊆ R}
{(s, s′ )|y ≥ 0} ∩ R
= {substitution}
{(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ z ′ 6= z}.
Likewise, we find:
ΠR (P ′ )
= {definition of ΠR , substitution and simplification}
{(s, s′ )|y ≤ 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z − 1} ◦ L ∩ (R ∪ P ′ )
= {computing the domain}
{(s, s′ )|y ≤ 0} ∩ (R ∪ P ′ )
= {since P ′ ⊆ R}
′
{(s, s )|y ≤ 0} ∩ R
= {substitution}
{(s, s′ )|y ≤ 0 ∧ x′ = x + y ∧ z ′ 6= z}.
We know, by Corollary 1, that these two projections satisfy the consistency
condition, hence we need not check it; we proceed directly with computing their
join. We compute in turn the three terms of the join:
ΠR (P ) ∩ ΠR (P ′ ) ◦ L
= {substitution, computing the domain and simplification}
{(s, s′ )|y > 0 ∧ x′ = x + y ∧ z ′ 6= z}.
The second term:
ΠR (P ′ ) ∩ ΠR (P ) ◦ L
= {substitution, computing the domain and simplification}
{(s, s′ )|y < 0 ∧ x′ = x + y ∧ z ′ 6= z}.
The third term:
ΠR (P ) ∩ ΠR (P ′ )
= {substitution and simplification}
{(s, s′ )|y = 0 ∧ x′ = x ∧ z ′ 6= z}.
To satisfy the union of these three terms, we write the following program:
z:=z+1; // from P, contradicts P’,
// but compatible with projection of P’
if (y>0) {while (y!=0) {x:=x+1; y:=y-1}} // from P
else {while (y!=0) {y:=y+1; x:=x-1}} // from P’.
26
This program delivers all the functionality of P and all the functionality of P ′ ,
and while it differs from P ′ in its effect on variable z, it is compatible with the
projection of P ′ over R, which is sufficient; it constitutes a merger of P and
P ′ , i.e. a program that is more-correct than P and more-correct than P ′ with
respect to R.
Note that if we had tried to compute the join of P and P ′ (rather than their
projections on R), we would have failed: To check the consistency condition
between P and P ′ , we proceed as follows:
P L = {(s, s′ )|y ≥ 0}. P ′ L = {(s, s′ )|y ≤ 0}.
Hence
P L ∩ P ′ L = {(s, s′ )|y = 0}.
On the other hand,
(P ∩ P ′ )L
= {substitution}
{(s, s′ )|y = 0 ∧ x′ = x + y ∧ y ′ = 0 ∧ z ′ = z + 1 ∧ z ′ = z − 1} ◦ L
= {contradiction and simplification}
φL
= {(3)}
φ.
Because this is different from P L∩P ′ L, we conclude that P and P ′ have no join.
But we notice that the failure to satisfy the consistency condition does not stem
from requirements mandated by R; rather it stems from design decisions taken
in P and P ′ that turned out to be irreconcilable (whereas program P satisfies
specification z 6= z ′ by incrementing z, program P ′ satisfies it by decrementing
z). So that by trying to take the join of P and P ′ , we are trying to combine, not
only specification-relevant features of P and P ′ , but also design-based features
that stem from arbitrary design decisions taken in the process of deriving P
and P ′ . Such design decisions are not only irrelevant for our purposes, they also
run the risk of creating inconsistencies between P and P ′ that preclude us from
taking their join.
We summarize:
27
Typically, R is a massive/complex specification (e.g. the specification of an
enterprise data processing application) and Q is a small feature that we want to
add to P (e.g. a new report format); the upgrade of P by Q consists in fulfilling
requirements Q without degrading the relative correctness of P with respect to
R. According to Proposition 11, P ′ is more-correct than P with respect to R if
and only if P ′ refines the projection of P over R. According to lattice theory,
program P ′ refines Q and ΠR (P ) if and only if it refines their join. On the other
hand, the join of Q and ΠR (P ) exists if and only if Q and ΠR (P ) satisfy the
consistency condition. If they do not satisfy the consistency condition, then no
program can satisfy requirement Q while preserving (relative) correctness with
respect to R; in other words, any attempt to make P correct with respect to Q
will necessarily make it less-correct with respect to R. We summarize this as
follows:
28
We now compute ΠR (P ), then the join of ΠR (P ) with Q.
ΠR (P )
= {definition of ΠR (P ) and substitution}
{(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y ′ = 0} ◦ L ∩ (R ∪ P )
= {taking the domain in the first term, simplifying the second}
{(s, s′ )|y ≥ 0 ∧ x′ = x + y}.
To check the consistency condition between Q and ΠR (P ), we compute the
intersection of their domains, then the domain of their intersection.
QL = L.
ΠR (P ) ◦ L = {(s, s′ )|y ≥ 0}.
(Q ∩ ΠR (P )) ◦ L = {(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y > y ′ } ◦ L = {(s, s′ )|y ≥ 0}.
The consistency condition is satisfied, hence we now compute the join of Q and
ΠR (P ), and we find, for the first term:
QL ∩ ΠR (P ) = L ∩ ΠR (P ) = φ.
The second term:
ΠR (P )L ∩ Q = {(s, s′ )|y ≥ 0} ∩ Q = {(s, s′ )|y < 0 ∧ y > y ′ }.
The third term:
Q ∩ ΠR (P ) = {(s, s′ )|y ≥ 0 ∧ x′ = x + y ∧ y > y ′ }.
The join can then be written as:
29
5.4. Program Documentation
Documentation is an important aspect of software engineering practice; pro-
fessional standards of software engineering dictate that one must document soft-
ware products by commenting on design features and/or by providing informa-
tion about the programmer’s intent; traditionally, this has meant documenting
the function of the program. The trouble with documenting the function of
the program is that typically, the function of the program reflects two separate
sources of information: the requirements that stem from the specification and
the functional features that stem from the design of the product. We argue
that it is important to distinguish between these, which the projection does,
since it captures only the former. We illustrate this contrast by a very simple
example: consider a space S defined by a single integer variable x, and consider
the specification
R = {(x, x′ )|x < x′ }.
Let p be a candidate program (i.e. a program written to satisfy R) that raises x
to power 2. We give below the function of P of p and the projection of P over
R:
• P = {(x, x′ )|x′ = x2 }.
• ΠR (P )
= {definition of ΠR }
(R ∩ P )L ∩ (R ∪ P )
= {substitution}
{(x, x′ )|x < x′ ∧ x′ = x2 } ◦ L ∩ {(x, x′ )|x < x′ ∨ x′ = x2 }
= {computing the domain}
{(x, x′ )|x < 0 ∨ x > 1} ∩ {(x, x′ )|x < x′ ∨ x′ = x2 }
= {since (x < 0 ∨ x > 1) ⇒ x < x2 }
{(x, x )|(x < 0 ∨ x > 1) ∧ x < x′ }.
′
30
• The third alternative is to comment this program with the projection of
P over R: x=x*x; // (x<0 || x>1) && x<x’. This comment captures
the essence of what program P does to satisfy specification R; it captures
neither the functional deficit of P (the fact that P does not satisfy R for x
between 0 and 1) nor the functional excess of P (the fact that P satisfies
R by raising x to power 2).
In light of this discussion, we argue that while documenting the projection of a
program on a specification is not necessarily always the best way to comment
on a piece of code, it is nevertheless a competitive option. Indeed, commenting
on a software product by means of its function may be unnecessary (i.e. provide
more information than needed) whereas commenting on it by means of its target
specification may be insufficient (i.e. recording what a program must do, rather
than what it actually does). We summarize our finding as follows:
6. Related Work
We are not aware of any other researchers who have studied program pro-
jections; therefore, we compare our work ot other researchers who have studied
various forms of relative correctness, which is the closest topic to what we are
discussing in this paper.
In [13] Logozzo et al. introduce a technique for extracting and maintaining
semantic information across program versions. The focus of their analysis is
the condition under which programs P and P ′ can execute without causing an
abort. They implement their approach in a system called VMV (Verification
Modulo Versions) whose goal is to exploit semantic information about P in the
analysis of P ′ , and to ensure that the transition from P to P ′ happens without
regression; in that case, they say that P ′ is correct relative to P . The definition
of relative correctness of Logozzo et al. [13] is different from ours, for several
reasons: whereas [13] talk about relative correctness between an original pro-
gram and a subsequent version in the context of adaptive maintenance, we talk
about relative correctness between an original (faulty) software product and a
revised version of the program (possibly still faulty yet more-correct) in the
context of corrective maintenance with respect to a fixed requirements specifi-
cation; whereas [13] use a set of assertions inserted throughout the program as
a specification, we use a relation that maps initial states to final states; whereas
[13] represent program executions by execution traces, we represent program
executions by functions mapping initial states to final states; finally, whereas
31
Logozzo et al. define a successful execution as a trace that satisfies all the rele-
vant assertions, we define it as an initial state/final state pair that satisfies the
relational specification.
In [11] Lahiri et al. introduce a technique called Differential Assertion Check-
ing for verifying the relative correctness of a program with respect to a previous
version of the program. Lahiri et al. explore applications of this technique as a
tradeoff between soundness (which they concede) and lower costs (which they
hope to achieve). Also, they define relative correctness between programs P and
P ′ as the property that P ′ has a larger set of successful traces and a smaller set
of unsuccessful traces than P ; and they introduce relative specifications as spec-
ifications that capture functionality of P ′ that P does not have. By contrast,
we use input/output (or initial state/final state) relations as specifications, we
represent program executions by functions from initial states to final states,
we characterize correct executions by initial state/final state pairs that belong
to the specification, and we make no distinction between abort-freedom (a.k.a.
safety, in [11]) and normal functional properties. Another important distinction
with [11] is that we do not view relative correctness as a compromise that we
accept as a substitute for absolute correctness; rather we argue that in many
cases, we ought to test programs for relative correctness rather than absolute
correctness, regardless of cost. In other words, whereas Lahiri et al. use rela-
tive correctness as a compromise solution whenever absolute correctness is too
expensive/ impractical, we use relative correctness in specific contexts because
that is the exact property that we want to consider.
In [12], Logozzo and Ball introduce a definition of relative correctness whereby
a program P ′ is correct relative to P (an improvement over P ) if and only if
P ′ has more good traces and fewer bad traces than P . Programs are modeled
with trace semantics, and execution traces are compared in terms of executable
assertions inserted into P and P ′ ; in order for the comparison to make sense,
programs P and P ′ have to have the same (or similar) structure and/or there
must be a mapping from traces of P to traces of P ′ . When P ′ is obtained
from P by a transformation, and when P ′ is provably correct relative to P , the
transformation in question is called a verified repair. Like the work cited above
([11, 13]), Logozzo and Ball model programs by execution traces and distinguish
between two types of failures: contract violations, when functional properties
are not satisfied; and run-time errors, when the execution causes an abort; for
the reasons we discuss above, we do not make this distinction, and model the
two aspects with the same relational framework.
Most of the work cited in this section is due to the software research group
at Microsoft Research; their main motivation for introducing and discussing
relative correctness is different from ours. Whereas we introduced relative cor-
rectness as a way to define software faults [15], they introduce it in the context
of implementing practical automatic verification tools, as part of a tool chain
that already uses trace and assertion-based semantics. This explains, in partic-
ular, the contrasts that we have alluded to throughout this section between our
work and theirs.
32
7. Conclusion
33
of the programs on the specification. By focusing on projections rather
than on the original program, we ensure that we only deal with relevant
information (i.e. information that pertains to the specification, rather than
information that stems from design decisions), we ensure that we deal with
minimal specifications (that are easier to solve), and we ensure that the
programs can be combined (the join of the projections is defined).
• Program Upgrade. Given a specification R and a candidate program P ,
and given a new feature Q, we model the upgrade of P by Q as the problem
of producing a program that is correct with respect to Q and more-correct
than P with respect to R. We find that the upgrade can be obtained by
refining the join of Q with the projection of P on R; we also find that if
the join does not exist, then the upgrade is not possible without degrading
the relative correctness of P with respect to R.
We are currently exploring the use of this concept to model such software en-
gineering processes as: software design, software evolution, agile programming,
and test driven software design [18, 10].
Acknowledgements
The authors are very impressed by the rigor, precision and insightfulness of
the reviewers’ comments, and are very grateful to the reviewers for the care and
meticulousness with which they have read, analyzed and assessed this paper.
References
[1] Boudriga, N., Elloumi, F., Mili, A., 1992. The lattice of specifications:
Applications to a specification methodology. Formal Aspects of Computing
4, 544–571.
[2] Brink, C., Kahl, W., Schmidt, G., 1997. Relational Methods in Computer
Science. Springer Verlag.
[3] Desharnais, J., Diallo, N., Ghardallou, W., Frias, M.F., Jaoua, A., Mili, A.,
2015. Relational mathematics for relative correctness, in: Relational and
Algebraic Methods in Computer Science, 2015, Springer Verlag, Lisbon,
Portugal. pp. 191–208. doi:10.1007/978-3-319-24704-5\_12.
[4] Dijkstra, E., 1976. A Discipline of Programming. Prentice Hall.
[5] Gries, D., 1981. The Science of Programming. Springer Verlag.
doi:10.1007/978-1-4612-5983-1.
[6] Hehner, E., 1993. A Practical Theory of Programming. Springer-Verlag.
[7] Hehner, E.C., 1992. A Practical Theory of Programming. Prentice Hall.
doi:10.1007/978-1-4419-8596-5.
34
[8] Hoare, C., 1969. An axiomatic basis for computer programming. Commu-
nications of the ACM 12, 576–583. doi:10.1145/363235.363259.
[9] Hoare, T., 1997. Unified theories of programming, in: Mathematical Meth-
ods in Program Development, Springer-Verlag. pp. 313–367.
[10] Janzen, D., Saiedian, H., 2005. Test driven development: Concepts, tax-
onomy and future direction. IEEE Computer 38, 43–50.
[11] Lahiri, S.K., McMillan, K.L., Sharma, R., Hawblitzel, C., 2013. Dif-
ferential assertion checking, in: Proceedings, ESEC/FSE, pp. 345–355.
doi:10.1145/2491411.2491452.
[12] Logozzo, F., Ball, T., 2012. Modular and verified automatic program repair,
in: Proceedings, OOPSLA, pp. 133–146. doi:10.1145/2384616.2384626.
[13] Logozzo, F., Lahiri, S., Faehndrich, M., Blackshear, S., 2014. Verification
modulo versions: Towards usable verification, in: Proceedings, PLDI, pp.
294–304. doi:10.1145/2594291.2594326.
[14] Manna, Z., 1974. A Mathematical Theory of Computation. McGraw-Hill.
[15] Mili, A., Frias, M., Jaoua, A., 2014. On faults and faulty programs, in:
Hoefner, P., Jipsen, P., Kahl, W., Mueller, M.E. (Eds.), Proceedings, RAM-
ICS: 14th International Conference on Relational and Algebraic Meth-
ods in Computer Science, Springer, Marienstatt, Germany. pp. 191–207.
doi:10.1007/978-3-319-06251-8\_12.
[16] Mills, H.D., Basili, V.R., Gannon, J.D., Hamlet, R.G., 1987. Principles of
Structured Programming: A Mathematical Approach. Allyn and Bacon,
Boston, Ma.
[17] Morgan, C.C., 1998. Programming from Specifications, Second Edition.
International Series in Computer Sciences, Prentice Hall, London, UK.
[18] Perelman, D., Gulwani, S., Grossman, D., Provost, P., 2014. Test driven
synthesis, in: Proceedings, 35th ACM SIGPLAN Conference, PLDI, Edin-
burgh, UK. pp. 408–418.
[19] Schmidt, G., Ströhlein, T., 1993. Relations and Graphs. Springer Verlag.
35