175 lines
5.1 KiB
Text
175 lines
5.1 KiB
Text
|
#import "../common.typ": *
|
||
|
#import "@preview/prooftrees:0.1.0": *
|
||
|
#show: doc => conf(doc)
|
||
|
|
||
|
#let tru = $"true"$
|
||
|
#let fls = $"false"$
|
||
|
|
||
|
= Program Analysis with Kleene Algebra with Tests
|
||
|
|
||
|
== Mon Jun 3 \@ 15:40
|
||
|
|
||
|
#quote(block: true)[
|
||
|
Kleene algebra with tests is an algebraic framework that can be used to reason about imperative programs. It has been applied across a wide variety of areas including program transformations, concurrency control, compiler optimizations, cache control, networking, and more. In these lectures, we will provide an overview of Kleene Algebra with Tests, including the syntax, semantics, and the coalgebraic theory underlying decision procedures for program equivalence. We will illustrate how it can be used as a core framework for program verification, including successful extensions and fundamental limitations.
|
||
|
]
|
||
|
|
||
|
#table(
|
||
|
columns: (1fr, auto, 1fr),
|
||
|
align: (auto, center, auto),
|
||
|
|
||
|
```
|
||
|
while a & b do
|
||
|
p;
|
||
|
while a do
|
||
|
q;
|
||
|
while a & b do
|
||
|
p;
|
||
|
```,
|
||
|
|
||
|
$eq.quest$,
|
||
|
|
||
|
```
|
||
|
while a do
|
||
|
if b then
|
||
|
p;
|
||
|
else
|
||
|
q;
|
||
|
```
|
||
|
)
|
||
|
|
||
|
Study equivalence of uninterpreted simple imperative programs.
|
||
|
|
||
|
=== Regular expressions
|
||
|
|
||
|
Basic elements
|
||
|
|
||
|
$e ::= 0 | 1 | a in A | ...$
|
||
|
|
||
|
where $A$ is finite.
|
||
|
|
||
|
$e ::= ... | e ; e | e + e | e *$
|
||
|
|
||
|
Set of words:
|
||
|
|
||
|
#rect[$db(e) : 2^(A^*) = cal(P)(A^*)$]
|
||
|
|
||
|
- $db(0) = emptyset$
|
||
|
- $db(1) = {epsilon }$
|
||
|
- $db(a) = {a }$
|
||
|
- For every symbol there's also an expression that's the same thing.
|
||
|
This is an abuse of notation
|
||
|
- $db(e + f) = db(e) union db(f)$
|
||
|
- $db(#[$e ; f$]) = db(e) circle.filled db(f)$
|
||
|
- $forall (U, V : 2^(A^*)) U circle.filled V = { u v | u in U , v in V }$
|
||
|
- this is word concatenation
|
||
|
- $db(e^*) = union.big_(n in bb(N)) db(e)^n$
|
||
|
|
||
|
These are the denotational semantics of regular expressions.
|
||
|
|
||
|
Examples:
|
||
|
|
||
|
- $(1 + a) ; (1 + b) mapsto {epsilon , a , b, a b }$
|
||
|
- $(a + b)^* mapsto {a , b}^*$
|
||
|
- $(a^* b)^* a^* mapsto {a , b}^*$
|
||
|
|
||
|
These last two are equal $(a + b)^* equiv (a^* b)^* a^*$ because they have the same denotational semantics.
|
||
|
This is _denesting_.
|
||
|
These denesting rules can also be applied to programs such as the example at the start.
|
||
|
|
||
|
For regular expressions and extensions of regular expressions, you can come up with some finite number of 3-bar equations to prove any equivalence between regular expressions.
|
||
|
|
||
|
#rect[
|
||
|
*Definition (Kleene's Theorem).*
|
||
|
Let $L$ be a regular language.
|
||
|
Then the following are equivalent:
|
||
|
|
||
|
1. $L = db(e)$ for some regexp $e$
|
||
|
2. $L$ is accepted by a DFA
|
||
|
]
|
||
|
|
||
|
Regular languages do not include things like $A^n B^n$.
|
||
|
See: #link("https://en.wikipedia.org/wiki/Chomsky_hierarchy")[Chomsky Hierarchy of languages].
|
||
|
|
||
|
- Regular sets are constructed with a similar construction as regular expressions.
|
||
|
|
||
|
Proof:
|
||
|
|
||
|
- #[
|
||
|
Direction 1 -> 2 first.
|
||
|
|
||
|
https://en.wikipedia.org/wiki/Brzozowski_derivative
|
||
|
|
||
|
($L = db(e)$ for some regexp $e$) $arrow.r$ ($L$ is accepted by a DFA)
|
||
|
|
||
|
Build an automaton directly from the expression. Use _derivatives_ as if it was a function.
|
||
|
|
||
|
DFA :
|
||
|
- S : finite set of states
|
||
|
- $F : S arrow.r bb(2)$
|
||
|
- $t : S arrow.r S^A$
|
||
|
- this must be deterministic
|
||
|
|
||
|
To construct a DFA out of an expression, construct 2 functions:
|
||
|
|
||
|
1. #[
|
||
|
$E : "RE" arrow.r bb(2)$
|
||
|
|
||
|
E stands for "empty word", this asks "is there an empty word"? Because this will indicate where you can stop
|
||
|
|
||
|
- $E(0) = 0$
|
||
|
- $E(1) = 1$
|
||
|
- $E(a) = 0$
|
||
|
- $E(e ; f) = E(e) times E(f)$
|
||
|
- $E(e + f) = E(e) or E(f)$
|
||
|
- $E(e^*) = 1$
|
||
|
]
|
||
|
|
||
|
2. #[
|
||
|
$L : cal(P)(A^*)$
|
||
|
- $L_a = { u | a u in L }$
|
||
|
|
||
|
$D_a : "RE" arrow.r "RE"^A$
|
||
|
|
||
|
- Note: $X arrow.r X^A equiv (X arrow.r X)_(a in A)$
|
||
|
|
||
|
Definition:
|
||
|
|
||
|
- $D_a (0) = 0$
|
||
|
- $D_a (1) = 0$
|
||
|
- $D_a (a) = 1$
|
||
|
- $D_a (b) = 0$
|
||
|
- $D_a (e ; f) = (D_a (e) ; f) + (E(e) ; D_a (f))$
|
||
|
- If $E(e)$ did not have the empty word, then $E(e) = 0$, then $0 + A = A$.
|
||
|
This is the case as the case split:
|
||
|
|
||
|
$cases(#[$D_a (e) ; f "if" E(e) = 0$], #[$D_a (e) ; f + D_a (f) "if" E(e) = 1$])$
|
||
|
|
||
|
- $D_a (e + f) = D_a (e) + D_a (f)$
|
||
|
- $D_a (e^*) = D_a (e) ; e^*$
|
||
|
]
|
||
|
|
||
|
This is not a DFA yet, because it needs to be shown that it's finite.
|
||
|
Pick a *start state*.
|
||
|
You can pick $e$ as your start state.
|
||
|
From there, collect states you can reach.
|
||
|
Then, argue that the states you can reach are finite.
|
||
|
|
||
|
It's not actually true that this is finite!
|
||
|
|
||
|
- If $e = (a^*)^*$, then $D_a (e) = (1 ; a^*) ; (a^*)^*$
|
||
|
- Then $D_a (D_a (e)) = (0;a^* + 1;a^*) ; (a^*)^* + (a^*) ; (a^*)^*$
|
||
|
- TODO: This isn't completely right but the point is that it expands infinitely and there is a common part
|
||
|
|
||
|
Need to look at the equivalent classes of derivatives, since $D$ only understands syntax and keeps around a lot of unnecessary baggage.
|
||
|
ACI (associativity, commutativity, I? (TODO))
|
||
|
|
||
|
This isn't completely necessary to show finiteness, since the repeating term is the same.
|
||
|
Delete unnecessary $(+ f)$ terms in the $+$ case.
|
||
|
This will give you finiteness.
|
||
|
]
|
||
|
|
||
|
Merge states of a non-deterministic finite automaton, using the peanut approach.
|
||
|
|
||
|
Alternative #link("https://en.wikipedia.org/wiki/Thompson%27s_construction")[*Thompson's construction*]
|
||
|
|