Nearly final version

This commit is contained in:
Théophile Bastian 2016-08-20 20:00:32 +02:00
parent 4bcd8dba6f
commit 1fedc0b668
1 changed files with 151 additions and 47 deletions

View File

@ -173,15 +173,18 @@ considered ``failed'' without reducing to $0$ (in case of deadlock).
The syntax is pretty straightforward to understand: $0$ and $1$ are base
processes; $\parallel$ executes in parallel its two operands; $\cdot$ executes
sequentially its two operands (or synchronizes on a channel if its left-hand
operand is a channel); $(\nu a)$ creates a new channel $a$ on which two
processes can be synchronized. Here, the ``synchronization'' simply means that
a call to the channel is blocking until its other end has been called as well.
operand is a channel); $(\nu a)$ creates two new channels, $a$ and $\bar{a}$,
on which two processes can be synchronized. Here, the ``synchronization''
simply means that a call to the channel is blocking until its dual channel has
been called as well.
The language is simply typed as in figure~\ref{fig:lccs:typing}. Note that
binary operators split their environment between their two operands, ensuring
that each identifier is used at most once, and that no rules (in particular the
axiom rules) ``forget'' any part of the environment, ensuring that each
identifier is used at least once.
identifier is used at least once. For instance, in $\Gamma =
\left[p:\proc,\,q:\proc\right]$, $0$ cannot be typed (\ie{} $\overline{\Gamma
\vdash 0 : \proc}$ is not a valid rule).
\begin{figure}[h]
\begin{align*}
@ -238,12 +241,12 @@ The $\tau_a$ reduction scheme may sound a bit unusual. It is, however,
necessary. Consider the reduction of $(\nu a) (a \cdot 1 \parallel \bar{a}
\cdot 1)$: the inner term $\tau_a$-reduces to $1$, thus allowing the whole term
to reduce to $1$; but if we replaced that $\tau_a$ with a $\tau$, the whole
term would reduce to $(\nu a) 1$, which has no valid types since $a$ and
$\bar{a}$ are not consumed. Our semantics would then not satisfy subject
reduction.
term would reduce to $(\nu a) 1$, which has no valid type since $a$ and
$\bar{a}$ are not consumed (linearity). Our semantics would then not satisfy
subject reduction.
Switching to an \emph{affine} \linccs{} while keeping it wrapped in a
\emph{linear} \lcalc{} was considered, but yielded way too much problems, while
\emph{linear} \lcalc{} was considered, but yielded way too many problems, while
switching to a fully-affine model would have modified the problem too deeply.
\subsection{Lifting to the higher order: linear \lcalc}
@ -252,8 +255,7 @@ In order to reach the studied language, \llccs, we have to lift up \linccs{} to
a \lcalc. To do so, we add to the language the constructions of
figure~\ref{fig:llam:syntax}, which are basically the usual \lcalc{}
constructions slightly transformed to be linear (which is mostly reflected by
the typing rules). In particular, the only base types are only $\proc$ and
$\chan$.
the typing rules). In particular, the only base types are $\proc$ and $\chan$.
\begin{figure}[h]
\begin{minipage}[t]{0.55\textwidth}
@ -274,9 +276,16 @@ $\chan$.
\caption{Linear \lcalc{} terms and types}\label{fig:llam:syntax}
\end{figure}
To enforce the linearity, the only typing rules of the usual \lcalc{} that
have to be changed are the $(\textit{Ax})$ and $(\textit{App})$ presented in
figure~\ref{fig:llam:typing}. The $(\textit{Abs})$ rule is the usual one.
To keep the language simple and ease the implementation, the
$\lambda$-abstractions are annotated with the type of their abstracted
variable. The usual $\rightarrow$ symbol was also changed to $\linarrow$, to
clearly remind that the terms are \emph{linear}.
\smallskip
In order to enforce the linearity, the only typing rules of the usual \lcalc{}
that have to be changed are the $(\textit{Ax})$ and $(\textit{App})$ presented
in figure~\ref{fig:llam:typing}. The $(\textit{Abs})$ rule is the usual one.
\begin{figure}[h]
\begin{align*}
@ -313,7 +322,21 @@ To lift the operational semantics to \llccs, we only need to add one rule:
\item Deadlock: $T_2 \eqdef \newch{a} (a \cdot \bar{a} \cdot 1)$. This term
does not reduce at all: no reduction is possible under the $\nu$.
\item \todo{More examples?}
\item Simple function call: $T_3 \eqdef ((\lambda x^P \cdot x) 1)
\parallel 1$ reduces to $1 \parallel 1$.
\item Channel passing: $T_4 \eqdef
\newch{f}\newch{g} \left(f \cdot 1 \parallel \left(\left(
\lambda a^C \cdot \lambda b^C \cdot \lambda c^C
\cdot \left(\left(a \cdot 1\right) \cdot \left(b \cdot 1\right)\right)
\parallel \left(c \cdot
1\right)\right)\,\bar{f}\,\bar{g}\,g\right)\right)$, which
$\beta$-reduces (and thus $\tau$-reduces) to
$\newch{f}\newch{g} \left(\left(f\cdot1\right) \parallel
\left(\left(\left(\bar{f} \cdot 1\right) \cdot
\left(\bar{g} \cdot 1\right)\right) \parallel \left(g \cdot 1\right)
\right)\right)$. Note that the function has no idea whether two
channels are dual or not.
\end{itemize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -328,10 +351,10 @@ the often-used tree-like games.
The traditional approach to concurrent games is to represent them as
\emph{tree-like games}. If the considered game consists in three moves, namely
$A$, $B$ and $C$, where $A$ can be played by Opponent and the others by Player
\emph{after} Opponent has played $A$, that means that the states of the game
will be $\epsilon$, $A$, $A \cdot B$ and $A \cdot C$, which corresponds to the
game tree
$A$, $B$ and $C$, where $A$ can be played by Opponent and either one of the
others by Player \emph{after} Opponent has played $A$, that means that the
states of the game will be $\epsilon$, $A$, $A \cdot B$ and $A \cdot C$, which
corresponds to the game tree
\[
\begin{tikzpicture}
@ -346,9 +369,9 @@ game tree
\]
This can of course be used to describe much larger games, and is often useful
to reason concurrently, since the causal histories appear clearly: the possible
states of the game can be read easily by concatenating the events found along a
path from the root of the tree.
to reason concurrently, since the causal histories appears clearly: the
possible states of the game can be read easily by concatenating the events
found along a path from the root of the tree.
But it also has the major drawback of growing exponentially in size: let us
consider a game in which Opponent must play $A$ and $B$ in no particular order
@ -371,7 +394,7 @@ before Player can play $C$. The corresponding tree-like game would be
\]
This goes even worse with less structure: since there is $n!$ % chktex 40
permutations for $n$ elements, the tree can grow way bigger.
permutations for $n$ elements, the tree can grow way larger.
This problem motivated the use of \emph{event structures} as a formalism to
describe such games~\cite{rideau2011concurrent}. Informally, an event structure
@ -476,7 +499,27 @@ For instance, one could imagine a game modeling the user interface of a coffee
machine: Player is the coffee machine, while Opponent is a user coming to buy a
drink.
\begin{example}[Process game]
\begin{example}[coffee machine]
A game describing a coffee machine could be the following one:
\[ \begin{tikzpicture}
\node (1) at (2,1.5) [draw=red, ellipse] {coin};
\node (2) at (-1,1.5) [draw=red, ellipse] {getCoffee};
\node (3) at (5,1.5) [draw=red, ellipse] {getTea};
\node (4) at (0,0) [draw=green, ellipse] {giveCoffee};
\node (5) at (4,0) [draw=green, ellipse] {giveTea};
\end{tikzpicture}
\]
Note that there are no edges at all. Indeed, we are here describing the
\emph{game}, that is, giving a structure on which we can model any software
that would run on the hardware of the coffee machine. Nothing is hardwired
that would make it mandatory to insert a coin before getting a coffee: the
\emph{software} decides that, it is thus up to the \emph{strategy} --- of
which we will talk later on --- to impose such constraints.
\end{example}
\begin{example}[process game]
We can represent a process by the following game:
\[
\begin{tikzpicture}
@ -489,11 +532,14 @@ drink.
The ``call'' event will be triggered by Opponent (the system) when the
process is started, and Player will play ``done'' when the process has
finished, if it ever does. The relation $\text{call} \leq \text{done}$
means that a process cannot finish \emph{before} it is called.
means that a process cannot finish \emph{before} it is called: unlike what
happened in the previous example, it is here a ``hardwired'' relation that
the software cannot bypass.
\end{example}
\begin{definition}[pre-strategy]
A \emph{pre-strategy} on the game $A$, $\sigma: A$, is an ESP such that
A \emph{pre-strategy} on the game $A$, written $\sigma: A$, is an ESP such
that
\begin{enumerate}[(i)]
\item $\sigma \subseteq A$;
\item $\config(\sigma) \subseteq \config(A)$;
@ -501,6 +547,9 @@ drink.
\end{enumerate}
\end{definition}
In particular, (ii) imposes that $\leq_A$ restrained to $\sigma$ is included in
$\leq_\sigma$.
\begin{example}[processes, cont.]
A possible \emph{pre-strategy} for the game consisting in two processes put
side by side (in which the game's events are annotated with a number to
@ -524,7 +573,26 @@ drink.
This would describe two processes working in parallel. The process $0$
waits before the process $1$ is called to terminate, and the process $1$
never returns.
never returns. Assuming that \lstc{called} is an initially false boolean
shared between the two processes, this could for instance be written
\begin{minipage}[T]{0.45\textwidth}
\begin{center}\textit{Process 0}\end{center}
\begin{lstlisting}[language=C++]
int main() {
while(!called) {}
return 0;
}\end{lstlisting}
\end{minipage}
\begin{minipage}[T]{0.45\textwidth}
\begin{center}\textit{Process 1}\end{center}
\begin{lstlisting}[language=C++]
int main() {
called=true;
while(true) {}
// never returns.
}\end{lstlisting}
\end{minipage}
\end{example}
But as it is defined, a pre-strategy does not exactly capture what we expect of
@ -552,7 +620,8 @@ unrealistic. We then have to restrict pre-strategies to \emph{strategies}:
(\ref{def:receptive}) captures the idea that we cannot prevent Opponent from
playing one of its moves. Indeed, not including an event in a strategy means
that this event \emph{will not} be played. It is unreasonable to consider that
a strategy could forbid Opponent to play a given move.
a strategy could forbid Opponent to play a given move, unless the game itself
forbids that as well.
(\ref{def:courteous}) states that unless a dependency relation is imposed by
the games' rules, one can only make one of its moves depend on an Opponent
@ -574,10 +643,10 @@ that in the original formalism~\cite{castellan2016concurrent}, games,
strategies and maps between them form a bicategory in which these operations
play special roles.
In this whole section, unless stated otherwise, $E$ and $F$ denotes ESPs, $A$,
$B$ and $C$ denotes games, $\sigma: A$ and $\tau: B$ denotes strategies.
In this whole section, unless stated otherwise, $E$ and $F$ denotes ESPs; $A$,
$B$ and $C$ denotes games; $\sigma: A$ and $\tau: B$ denotes strategies.
\begin{definition}[Parallel composition]
\begin{definition}[parallel composition]
The \emph{parallel composition} $E \parallel F$ of two ESPs is an ESP
whose events are $\left(\set{0} \times E\right) \sqcup \left(\set{1} \times
F\right)$ (the disjoint tagged union of the events of $E$ and $F$), and
@ -589,7 +658,9 @@ $B$ and $C$ denotes games, $\sigma: A$ and $\tau: B$ denotes strategies.
\end{definition}
In the example before, when talking of ``two processes side by side'', we
actually referred formally to the parallel composition of two processes.
actually referred formally to the parallel composition of two processes, in
which we took the liberty of renaming the events for more clarity (which we
will often do).
\smallskip
@ -597,7 +668,7 @@ Given two strategies on dual games $A$ and $A^\perp$, it is natural and
interesting to compute their \emph{interaction}, that is, ``what will happen if
one strategy plays against the other''.
\begin{definition}[Closed interaction]
\begin{definition}[closed interaction]
Given two strategies $\sigma : A$ and $\tau : A^\perp$, their
\emph{interaction} $\sigma \wedge \tau$ is the ESP
$\sigma \cap \tau \subseteq A$ from which causal loops have been removed.
@ -606,7 +677,7 @@ one strategy plays against the other''.
${(\leq_\sigma \cup \leq_\tau)}^\ast$ (transitive closure) that may not
respect antisymmetry, that is, may have causal loops. The event structure
$\sigma \wedge \tau$ is then obtained by removing all the elements
contained in such loops from $\sigma \cap \tau$.
contained in such loops from $\sigma \cap \tau$, yielding a regular order.
\end{definition}
\textit{This construction is a simplified version of the analogous one
@ -623,13 +694,14 @@ causal loop).
We might now try to generalize that to an \emph{open} case, where both
strategies don't play on the same games, but only have a common part. Our
objective here is to \emph{compose} strategies: indeed, a strategy on $A^\perp
goal here is to \emph{compose} strategies: indeed, a strategy on $A^\perp
\parallel B$ can be seen as a strategy \emph{from $A$ to $B$}, playing as
Opponent on a board $A$ and as Player on a board $B$. This somehow looks like a
function, that could be composed with another strategy on $B^\perp \parallel
C$.
C$ (as one would compose two mathematical functions $f$ and $g$ into $g \circ
f$).
\begin{definition}[Compositional interaction]
\begin{definition}[compositional interaction]
Given two strategies $\sigma : A^\perp \parallel B$ and $\tau : B^\perp
\parallel C$, their \emph{compositional interaction} $\tau \strInteract
\sigma$ is an event structure defined as $(\sigma \parallel C) \wedge
@ -637,7 +709,9 @@ C$.
\end{definition}
The idea is to put in correspondence the ``middle'' states (those of $B$) while
adding ``neutral'' states for $A$ and $C$.
adding ``neutral'' states for $A$ and $C$, which gives us two strategies
playing on the same game (if we ignore polarities), $A \parallel B \parallel
C$.
$\tau \strInteract \sigma$ is an \emph{event structure} (\ie, without
polarities): indeed, the two strategies disagree on the polarities of the
@ -647,7 +721,7 @@ over $\set{+,-,?}$.
From this point, the notion of composition we sought is only a matter of
``hiding'' the middle part:
\begin{definition}[Strategies composition]
\begin{definition}[strategies composition]
Given two strategies $\sigma : A^\perp \parallel B$ and $\tau : B^\perp
\parallel C$, their \emph{composition} $\tau \strComp \sigma$ is the ESP
$(\tau \strInteract \sigma) \cap (A^\perp \parallel C)$, on which the
@ -656,9 +730,11 @@ From this point, the notion of composition we sought is only a matter of
\end{definition}
It is then useful to consider an identity strategy \wrt{} the composition
operator. This identity is called the \emph{copycat} strategy:
operator. This identity is called the \emph{copycat} strategy: on a game $A$,
the copycat strategy playing on $A^\perp \parallel A$ replicates the moves
the other player from each board on the other.
\begin{definition}[Copycat]
\begin{definition}[copycat]
The \emph{copycat strategy} of a game $A$, $\cc_A$, is the strategy on the
game $A^\perp \parallel A$ whose events are $A^\perp \parallel A$ wholly,
on which the order is the transitive closure of $\leq_{A^\perp \parallel A}
@ -696,10 +772,14 @@ $\sigma : A$, $\sigma$ is a strategy $\iff$ $\cc_A \strComp \sigma = \sigma$.
(12) edge (11)
(22) edge (21)
(31) edge (32)
(31) edge (11)
% (31) edge (11)
(32) edge (12);
\end{tikzpicture}
\]
Note that the edge $C \rightarrow A$ in the upper row is no longer needed,
since it can be obtained transitively and we only represent the transitive
reduction of the partial order.
\end{example}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -837,17 +917,17 @@ games, in this order.
We will now prove the major result of this study, the \emph{adequacy} of the
game semantics.
\begin{theorem}[Adequacy]
\begin{theorem}[adequacy]
The previous interpretation is \emph{adequate} with the operational
semantics, that is
\[ \forall P \textit{ st. } \vdash P : \proc,~
\[ \forall P \textit{ st. } \left(\vdash P : \proc\right),~
\left(P \Downarrow\right) \iff \left(\seman{P} = \seman{1}\right) \]
\end{theorem}
In order to prove the theorem, a few intermediary definitions and results are
required.
\begin{definition}[Evaluation in a context]
\begin{definition}[evaluation in a context]
For $l$ a list of channels and $P$ a term, the evaluation of $P$ in the
context $l$, $\seman{P}_l$, is defined by induction by $\seman{P}_{[]}
\eqdef \seman{P}$ and $\seman{P}_{h::t} \eqdef \seman{(\nu h)P}_t$.
@ -880,10 +960,13 @@ required.
\end{enumerate}
\end{lemma}
The previous lemma's proof mostly consists in technical, formal reasoning on
event structures, but it is essentially intuitive.
The theorem is mostly a consequence of the following lemma:
\begin{lemma}
$\forall P \redarrow{x} Q, \forall l \in \validctx_{P \redarrow{x} Q}$,
$\forall P \redarrow{x} Q,~\forall l \in \validctx_{P \redarrow{x} Q}$,
\begin{enumerate}[(i)]
\item if $x = \tau$, then $\seman{P}_l = \seman{Q}_l$;
\item if $x = a: \chan$, then $\seman{P}_l = \seman{a \cdot Q}_l$;
@ -924,9 +1007,15 @@ The theorem is mostly a consequence of the following lemma:
We prove its contrapositive judgement, $P \neq 1\,\&\,\seman{P} =
\seman{1} \implies \exists Q\,:\,P \redarrow{\tau} Q$ by induction over the
syntax of \linccs{} (\wlogen, we can assume that $P
\not\longrightarrow_\beta$, thus the terms are in \linccs). \todo{?}
\not\longrightarrow_\beta$, thus the terms are in \linccs): for each
syntactic construction, we prove that under the induction hypotheses, there
is such a $Q$.
\end{proof}
This proves the adequacy of our semantics, giving some credit to the game
semantics we provided: indeed, in order to decide whether a term converges, we
can compute its associated strategy and check whether it is $\seman{1}$.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Implementation of deterministic concurrent games}
@ -953,6 +1042,21 @@ represented as a DAG in memory. The actual representation that was chosen is a
set of nodes, each containing (as well as a few other information) a list of
incoming and outgoing edges.
\subsection{Generic operations}
The software --- apart from a few convenience functions used to input and
output games and strategies, as well as the \llccs{} handling --- mostly
consists in graph handling functions (mostly used internally) and the
implementation of the operations on games and strategies previously described.
This allows to compute the result of any operation on a deterministic strategy,
and is modular enough to make it possible to implement non-determinism on the
top of it later on (even without having to understand the whole codebase).
Those operations can be used directly from the OCaml toplevel, conveniently
initialized with the correct modules loaded with \lstbash{make toplevel}; but
it is mostly intended to be a backend for higher level interfaces, such as the
\llccs{} interface.
\subsection{Modelling \llccs}
The modelling of \llccs{} required to implement a lexer/parser for the
@ -976,7 +1080,7 @@ isomorphism) of $\parallel$, but in the code, each use of the associativity
must be explicit, leading to a large amount of code.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Conclusion}
\section{Conclusion}
During this internship, I have established deterministic game semantics for a
simple concurrent language. Although the language is fairly simple, it should