oplss2024/bourgeat/notes.typ

111 lines
3.3 KiB
Plaintext

#import "../common.typ": *
#import "@preview/prooftrees:0.1.0": *
#show: doc => conf("Rule-based languages from modular design to modular verification", doc)
#import "@preview/finite:0.3.0" as finite: automaton
== Lecture 1
*Definition (module).* $(S."type", {R}_(i in S), {v m}, {a m})$
- States
- $R subset S times S$. these are transitions, very similar to automata
- $a m subset S times NN times S$. argument methods. One argument always, type natural number. "If I'm in a state, and then I call some action, then I end up in a new state"
- $v m subset S times NN times NN$. value methods are the only way to observe anything in the system. Observations are always of type nat for now.
*Example (coffee-tea machine).*
#automaton(
layout: finite.layout.snake.with(columns: 3),
(
q1: (q2: "put"),
q2: (q3: "coffee", q4: "tea"),
q3: (q3: "see"),
q4: (q4: "see"),
)
)
This is encoded as:
$({1, 2, 3, 4}, {}, {
"getTea" = {(2, star, 4)},
"getCoffee" = {(2, star, 3)},
"putMoney" = {(1, 1, 2)},
}, {
"see" = {(3, star, "coffee"), (4, star, "tea")}
})$
Similarity to automata
- Finite states
Differences from automata
- Sliced transitions between things that change the state of the system and ones that observe the state of the system
We are interested in modeling the basic blocks of hardware as this kind of machine.
We will write a language to plug together these modules into bigger modules.
*Example (register).*
$ (NN, {}, &{"write" = {(x, y, y) | forall x, y in NN^2}} \
&{"read" = {(x, z, x) | forall x, z in NN^2}}) $
Infinite transitions are ok but there needs to be a finite number of them.
*Example (infinite atomic memory).* This can't be expressed in hardware.
$ (NN -> NN, {}, &{"write" = {(f, ("idx", v), f') | forall y. "idx" = j -> f j = f' j, f' "idx" = v}}, \
&{"read" = {(f, "arg", f("arg")) | forall f, "arg"}})
$
*Example (queue).* $([NN], {}, {"enqueue", "dequeue"}, {"first"})$
== #strike[Equivalence] Refinement
If both sides can be refined into each other then they are equivalent.
- One way is to construct the language of the automata
*Definition (traces of a module/behaviors).*
Silent transition: $s_0 mapsto s_1$
Observations about the state must be added to the trace as well.
Trace looks like $["enqueue" (1), "first" () -> 1]$ for a queue.
*Definition (Refinement).* A module $M$ refines $M'$ iff $db(M) subset.eq db(M')$.
*Definition (weak simulation).* A module $M$ simulates $M'$
$ M op(subset.sq.eq)_phi M'$
s.t $phi : S_M times S_M'$ (relation between state of $M$ and state of $M'$).
$phi$ witnesses that $M'$ simulates $M$ iff $(m_0, m'_0) in phi$
#let arg = "arg"
#let sset = "set"
- Base case: $forall v in cal(V), forall arg, forall sset, (m_0, arg, sset) in v ==> (m'_0, arg, sset)$
- Inductive case: $forall m in S_M, m' in S_M', (m, m') in phi ==> forall "am" in a_m, forall arg, m mapsto^("am"(arg)) m_2 ==> (m' mapsto^("am"(arg)) m'_2)$
$ (M op(subset.sq.eq)_phi M') ==> db(M) subset db(M') $
=== Composing
Compose $M_1$, $M_2$, and $M_3$ into a bigger module.
#tree(
axi[$(m, f("arg"), m') in "enq"_M$],
uni[$m."enqE"("arg") --> m'$],
)
#tree(
axi[$(m, f("arg"), m') in "enq"_M$],
uni[$m."deq"("arg") --> m'$],
)
#pagebreak()
== Lecture 2
- Language Definition
- Compilation to circuits
- Example weak simulation + refinement theorem