\documentclass[11pt,twoside]{scrartcl}
%opening
\newcommand{\lecid}{15-414}
\newcommand{\leccourse}{Bug Catching: Automated Program Verification}
\newcommand{\lecdate}{} %e.g. {October 21, 2013}
\newcommand{\lecnum}{6}
\newcommand{\lectitle}{Invariants for Arbitrary Loops}
\newcommand{\lecturer}{Matt Fredrikson}
\usepackage{lecnotes}
\usepackage[irlabel]{bugcatch}
\begin{document}
\maketitle
\thispagestyle{empty}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Introduction}
The previous lecture provided axioms for compositional reasoning about deterministic sequential programs.
All the axioms compositionally reduce the truth of a postcondition of a more complex program to a logical combination of postconditions of simpler programs.
All axioms?
Well, all the axioms but one: those about loops.
But putting loops aside for the moment, these axioms completely tell us what we need to do to understand a program.
All we need to do is to identify the top-level operator of the program and apply the corresponding axiom from its left hand side to its structurally simpler right hand side, which will eventually reduce the property of a program to first-order logic with arithmetic but without programs.
This process is completely systematic.
So except for the (nontrivial) fact that we will have to hope that an SMT solver will be able to handle the remaining arithmetic, our ``only'' problem is what we could possibly to with a loop.
The unwinding axioms from the previous lecture were only partially helpful, which is why this lecture investigates more comprehensive reasoning techniques for loops.
We follow an entirely systematic approach~\cite[Chapter 7]{Platzer17} to understanding loop invariants, an induction technique for loops, which is of central significance for program verification.
We will also experience our share of the important phenomenon of loop invariant search.
\section{Derived Soundness}
Recall the axioms that we introduced in the last lecture.
Writing down axioms is one thing.
Making use of them for proofs is quite helpful, too.
But if the axioms are wrong, then that would not help making the programs any more correct.
Consequently, it is imperative that all axioms we adopt are indeed sound, so only allow us to prove formulas that are actually valid.
An axiom is sound iff all its instances are valid formulas, so true in all states.
The notes from the previous lecture give some examples of how to show this by referring to the semantics of Dynamic Logic, in a similar way to how the soundness of proof rules for propositional logic were established.
The \irref{unfold} axiom can be justified to be sound in another way.
Rather than arguing by semantics, which would work, too, we can derive it with a sequent calculus proof from the other axioms.
After all other axioms are proved to be sound the \emph{derived axiom} \irref{unfold} is thus sound too.
\begin{lemma}
The following axiom is a \dfn[axiom!derived]{derived axiom}, so can be proved from the other axioms in sequent calculus, and is, thus, sound:
\[
\cinferenceRule[unfold|$\dibox{\text{unfold}}$]{unfold while loop}
{\linferenceRule[equiv]
{(\ivr\limply\dbox{\ausprg}{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}) \land (\lnot\ivr\limply\ausfml)}
{\axkey{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}}
}{}%
\]
\end{lemma}
\begin{proof}
The axiom \irref{unfold} can be proved from the other axioms by using some of them in the backwards implication direction:
\begin{sequentdeduction}[array]
\linfer[composeb]
{\linfer[ifb]
{\linfer[whileiterateb]
{\lclose}
{\lsequent{} {{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}\lbisubjunct
{\dbox{\pifs{\ivr}{\plgroup\ausprg;\pwhile{\ivr}{\ausprg}\prgroup}}{\ausfml}}}}
}
{\lsequent{} {{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}\lbisubjunct
{(\ivr\limply\dbox{\ausprg;\pwhile{\ivr}{\ausprg}}{\ausfml}) \land (\lnot\ivr\limply\ausfml)}}}
}
{\lsequent{} {{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}\lbisubjunct
{(\ivr\limply\dbox{\ausprg}{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}) \land (\lnot\ivr\limply\ausfml)}}}
\end{sequentdeduction}
\end{proof}
Every time we need the derived axiom \irref{unfold}, we could instead write down this sequent proof to prove it.
It just won't be very efficient, so instead we will settle for deriving axiom \irref{unfold} in the sequent calculus once and then just believing it from then on.
This gives us two ways of establishing the soundness of an axiom.
Either by a mathematical proof from the semantics of the operators.
Or as a derived axiom by a formal proof in sequent calculus from other axioms and proof rules that have already been proved to be sound.
Of course, the first time a new operator is mentioned in any of our axioms, we cannot derive it yet but have to work from its semantics.
But the second time, it may become possible to argue as in a derived axiom.
\section{Recall: Loop the Loop}
Recall the two (equivalent) axioms for handling while-loops by unwinding the loop:
\begin{calculus}
\cinferenceRule[whileiterateb|$\dibox{\text{unwind}}$]{unfold while loop}
{\linferenceRule[equiv]
{\dbox{\pifs{\ivr}{\plgroup\ausprg;\pwhile{\ivr}{\ausprg}\prgroup}}{\ausfml}}
{\axkey{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}}
}{}%
\cinferenceRule[unfold|$\dibox{\text{unfold}}$]{unfold while loop}
{\linferenceRule[equiv]
{(\ivr\limply\dbox{\ausprg}{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}) \land (\lnot\ivr\limply\ausfml)}
{\axkey{\dbox{\pwhile{\ivr}{\ausprg}}{\ausfml}}}
}{}%
\end{calculus}
Especially the \irref{unfold} axiom makes it very apparent that the deficiency with both axioms is that, when used from left to right, they reduce a property of a while loop to some logic and then the same property of the same loop again.
While the isolated $\ausprg$ loop body can be handled with the other axioms, the \m{\pwhile{\ivr}{\ausprg}} loop is still remaining and could be handled by another \irref{unfold} but then the same issue persists.
This principle of successively unrolling the loop is still perfectly helpful for loops that terminate right away or that always terminate after 1 rounds or after 2 rounds or after some other fixed finite maximum number of iterations such as 5.
But ``most'' loops are not like that.
If the loop terminates after a very large number of loop iterations, or if we cannot know ahead of time after which fixed natural number of loop iterations it terminates, then unrolling the loop does not help, because there will always be a conjunct referring to what happens if the loop repeats again.\footnote{
There is a very subtle argument why such unrolling is still enough progress to prove properties of loops \cite{DBLP:journals/tocl/Platzer15}, but this is beyond the scope here.
}
%%%%%%%%%%%%%%%%%%%%
\section{Loops and Nondeterministic Repetition}
In order to resolve these issues with how to prove loops, we will follow a completely systematic approach to develop compositional proof principles for loops.
Successive loop unrolling with the \irref{unfold} axiom ran into the difficulty that it had to predict perfectly when the loop stops because the loop condition $\ivr$ is false.
The number of iterations for a while loop is hard to predict.
It was of course defined exactly in the semantics:
\begin{enumerate}
\addtocounter{enumi}{4}
\item \m{\iaccess[\pwhile{\ivr}{\asprg}]{\I} = \big\{(\iget[state]{\I},\iget[state]{\It}) \with}
there are an $n$ and states
\(\iget[state]{\Iz[0]}=\iget[state]{\I},\iget[state]{\Iz[1]},\iget[state]{\Iz[2]},\dots,\iget[state]{\Iz[n]}=\iget[state]{\It}\)
such that for all $0\leq i