Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
skip to main content
research-article
Open access

Types for Complexity of Parallel Computation in Pi-calculus

Published: 15 July 2022 Publication History

Abstract

Type systems as a technique to analyse or control programs have been extensively studied for functional programming languages. In particular, some systems allow one to extract from a typing derivation a complexity bound on the program. We explore how to extend such results to parallel complexity in the setting of pi-calculus, considered as a communication-based model for parallel computation. Two notions of time complexity are given: the total computation time without parallelism (the work) and the computation time under maximal parallelism (the span). We define operational semantics to capture those two notions and present two type systems from which one can extract a complexity bound on a process. The type systems are inspired both by sized types and by input/output types, with additional temporal information about communications.

1 Introduction

The problem of certifying time complexity bounds for programs is a challenging question, related to the problem of statically inferring time complexity, and it has been extensively studied in the setting of sequential programming languages. One particular approach to these questions is that of type systems, which offers the advantage of providing an analysis that is formally grounded, compositional, and modular. In the functional framework several rich type systems have been proposed, such that if a program can be assigned a type, then one can extract from the type derivation a complexity bound for its execution on any input (see, e.g., References [4, 9, 23, 24, 25, 28]). The type system itself thus provides a complexity certification procedure, and if a type inference algorithm is also provided one obtains a complexity inference procedure. This research area is also related to implicit computational complexity, which aims at providing type systems or static criteria to characterize some complexity classes within a programming language (see, e.g., References [6, 7, 16, 18, 21, 27, 36]) and which have sometimes in a second step inspired a complexity certification or inference procedure.
However, while the topic of complexity certification has been thoroughly investigated for sequential programs, both for space and time bounds, there only have been a few contributions in the settings of parallel programs and distributed systems. In these contexts, several notions of cost can be of interest to abstract the computation time. First, one can wish to know what the total cumulated computation time on all processors is during a program execution. This is called the work of the program. Second, one can wonder if an infinite number of processors were available, what would be the execution time of the program when it is maximally parallelized. This is called the span or depth of the program.
In Reference [26], the authors addressed the problem of analysing the time complexity of programs written in a parallel first-order functional language. In this language one can spawn computations in parallel and use the resulting values in the body of the program. This allows one to express a large bunch of classical parallel algorithms. Their approach is based on amortized complexity and builds on a line of work in the setting of sequential languages to define type systems, which allow one to derive bounds on the work and the span of the program. However, the language they are investigating does not allow communication between those computations in parallel. Our goal is to provide an approach to analyse the time complexity of programs written in a rich language for communication-based parallel computation, allowing the representation of several synchronization features. We use for that \(\pi\) -calculus, a process calculus that provides process creation, channel name creation and name-passing in communication [37, 38]. An alternative approach could be to use a language described with session types, as in References [12, 13]. We will discuss the expressivity of both languages in Section 5.3.
We want to propose methods that, given a parallel program written in \(\pi\) -calculus, allow one to derive upper bounds on its work and span. Let us mention that these notions are not only of theoretical interest. Some classical results provide upper bounds, expressed by means of the work (w) and span (s), on the evaluation time of a parallel program on a given number p of processors. For instance, such a program can be evaluated on a shared-multiprocessor system (SMP) with p processors in time \(O(\max (w/p,s))\) (see, e.g., Reference [22]).
Our goal in this article is essentially fundamental and methodological, in the sense that we aim at proposing type systems that are general enough, well-behaved, and provide good complexity properties. We also show intuitively how to relate our type systems to already existing type inference procedures for sized types, as in Reference [4], but we do not focus on automatization of type inference in this article.
We want to be able to derive complexity bounds that are parametric in the size of inputs, for instance, which depend on the length of a list. For that it will be useful to have a language of types that can carry information about sizes, and for this reason we take inspiration from sized types [9, 29]. So data-types will be annotated with an index that will provide some information on the size of values. Our approach then follows the standard approach to typing in the \(\pi\) -calculus, namely, typing a channel by providing the types of the messages that can be sent or received through it. Actually a second ingredient will be necessary for us, input/output types. In this setting a channel is given a set of capabilities: it can be an input, an output, or have both input/output capabilities. This distinction between outputs and inputs is especially useful for subtyping, a very important notion in sized types as it gives more flexibility. Indeed, an input channel and an output channel do not have the same behaviour with regard to subtyping.
Outline of the article. First, we describe in Section 3 a \(\pi\) -calculus with an explicit \(\mathtt {tick}\) construction; this allows one to specify several cost models, instead of only counting the number of reduction steps. We then describe in Section 4 a definition of the work of a process, design a type system, and establish a soundness theorem: If a process is well-typed in this type system, then its type provides an expression that, for its execution on any input, bounds the work. We also provide some hints on a type inference algorithm for this type system. Then, in Section 5, we give a formal definition of parallel complexity (span) in \(\pi\) -calculus. Next, we design another type system and again establish a soundness theorem but for span. Afterwards, we describe in Section 6 an example of parallel algorithm that can be analysed by this type system for span: bitonic sort. Finally, in Section 7, we compare our notion of span with the causal complexity from the literature.
This article is an extended version of the conference paper [5]. With respect to this previous paper, we give two additional results—one toward type inference for the work type system (Section 4.6) and another relating our definition of span to the notion of causal complexity (Section 7). We also give more details on the proofs of lemmas and theorems stated in the conference paper, and more detailed examples to illustrate the notions.
Discussion. Note that even though one of the main usages of \(\pi\) -calculus is to specify and analyse concurrent systems, the present article does not aim at analysing the complexity of arbitrary \(\pi\) -calculus concurrent programs. Indeed, some typical examples of concurrent systems, like semaphores, will simply not be typable in the system for span (see Section 5.3) because of linearity conditions. As explained above, our interest here is instead focused on parallel computation expressed in the \(\pi\) -calculus, which can include some form of cooperative concurrency. We believe the analysis of complexity bounds for concurrent \(\pi\) -calculus is another challenging question, which we want to address in future work.
A comparison with related works will be done in Section 8.

2 The Pi-calculus and Informal Introduction to Sized Types

In this work, we consider the \(\pi\) -calculus as a model of parallelism. The main points of \(\pi\) -calculus are that processes can be composed in parallel, communication between processes happens with the use of channels, and channel names can be created dynamically.

2.1 Syntax of Pi-calculus

We present here a classical syntax for the asynchronous \(\pi\) -calculus. More details about \(\pi\) -calculus and variants of the syntax can be found in Reference [38]. We define the sets of variables, expressions, and processes by the following grammar:
\begin{align*} {v}& := x,y,z \; {|}\;a,b,c \qquad e := {v}\; {|}\;\mathtt {0}\; {|}\;\mathtt {s}(e) \; {|}\;\lbrack \rbrack \; {|}\;e::e^{\prime }, \\ P,Q &:= {\odot }\; {|}\;(P \mathbin {\,|\,}Q) \; {|}\;! a(\widetilde{{v}}).P\; {|}\;a(\widetilde{{v}}).P \; {|}\;\overline{a}\langle {\widetilde{e}}\rangle \; {|}\;(\nu a)P \; {|}\;\mathtt {tick}.P \\ &\phantom{:= } \; {|}\;\mathtt {match}~e~\lbrace \mathtt {0}\mapsto P ;;~ \mathtt {s}(x) \mapsto Q \rbrace \; {|}\;\mathtt {match}~e~\lbrace \lbrack \rbrack \mapsto P ;;~ x::y \mapsto Q \rbrace . \end{align*}
Variables \(x,y,z\) denote base type variables, they represent integers or lists. Variables \(a,b,c\) denote channel names. The notation \(\widetilde{{v}}\) stands for a sequence of variables \({v}_1,{v}_2,\dots ,{v}_k\) . In the same way, \(\widetilde{e}\) is a sequence of expressions. This syntax relies on binders; for example, in \(a(\widetilde{{v}}).P\) , the variables in \(\widetilde{{v}}\) are bound in P, and similarly in \(\mathtt {match}~e~\lbrace \lbrack \rbrack \mapsto P ;;~ x::y \mapsto Q \rbrace\) , the variables x and y are bound in Q. We work up to \(\alpha\) -renaming (renaming of bound variables), and we write \(P [\widetilde{{v}} := \widetilde{e}]\) to denote the substitution of the free variables \(\widetilde{{v}}\) in P by \(\widetilde{e}\) .
Intuitively, \({\odot }\) represents the empty process, \(P \mathbin {\,|\,}Q\) stands for the parallel composition of P and Q, \(a(\widetilde{{v}}).P\) represents an input: it stands for the reception on the channel a of a tuple of values identified by the variables \(\widetilde{{v}}\) in the continuation P. The process \(! a(\widetilde{{v}}).P\) is a replicated version of \(a(\widetilde{{v}})\) ; it behaves like an infinite number of \(a(\widetilde{{v}})\) in parallel. Such a channel a in a replicated input will often be called a server. The process \(\overline{a}\langle {\widetilde{e}}\rangle\) represents an output: It sends a sequence of expressions on the channel a. A process \((\nu a)P\) dynamically creates a new channel name a and then proceeds as P. We also have classical pattern matching on data types, and finally, in \(\mathtt {tick}.P\) , the tick incurs an additional cost of one, and this process has the same semantic behaviour as P. This constructor is the source of time complexity in a program. It can represent different cost models and it is more general than only counting the number of reduction steps. For example, by adding a \(\mathtt {tick}\) after each input, we can count the number of communications in a process. By adding it after each replicated input on a channel a, we can count the number of calls to a. If we want to count the number of reduction steps, then we can add a \(\mathtt {tick}\) after each input and pattern matching.

2.2 Informal Introduction to the Semantics and Type Systems

As for the semantics, we design two semantics depending on the kind of complexity we want to consider. First, we consider the work of a process, corresponding to the total number of \(\mathtt {tick}\) in a computation. The important rules are:
where the subscript indicates the complexity cost of this reduction step. So removing a \(\mathtt {tick}\) has complexity one, and the other reduction steps have complexity zero. With this, we can define the work as the sum of the subscripts in a reduction path. As the \(\pi\) -calculus is non-deterministic, we consider a worst-case analysis.
Second, we consider another complexity, the span, corresponding to maximum parallel complexity. Informally, it means that all computations that are put in parallel can be done simultaneously, as if we had an infinite number of processors. In practice, it means that any number of \(\mathtt {tick}\) in parallel should be removed simultaneously. So, for example, \(\mathtt {tick}. {\odot }\mathbin {\,|\,}\mathtt {tick}. {\odot }\mathbin {\,|\,}\mathtt {tick}. {\odot }\) should have span complexity 1 (whereas its work is 3).
To define span formally, we introduce annotations in the \(\pi\) -calculus: a new constructor \(n \mathbin {:}P\) , where n is an integer. Intuitively, \(n \mathbin {:}P\) represents the process P with n ticks before, or alternatively, a process P that would be ready after n units of time. The important rules are
So intuitively, we have the same rules as before but with additional information in the annotations. When doing a communication between an input and an output, in order for the continuation \(P [\widetilde{{v}} := \widetilde{e}]\) to be available, both the input and the output should be ready. As they take, respectively, n and m units of time to be ready, the continuation is available after \(\max (m,n)\) units of time. As to the last rule, it expresses the fact that the annotations indeed count the number of \(\mathtt {tick}\) . From this, the span of a process is defined as the maximal annotation seen in all reduction paths from \(0 \mathbin {:}P\) .
Example 2.1.
We illustrate those semantics on a toy example simulating the recursive calls of the Fibonacci function. This is described in Figure 1.
Fig. 1.
Fig. 1. Toy example simulating the Fibonnaci recursive calls.
Intuitively, on an input n, the channel toyfib behaves in such a way that if \(n = \mathtt {0}\) or \(n=1\) , then the computation stops (because of the empty process \({\odot }\) ). Otherwise, the channel does two recursive calls to itself with value \(n {-}1\) and \(n {-}2\) . In this example, the \(\mathtt {tick}\) constructor is used to count the number of calls to the server. Let us describe one possible reduction for work complexity when we do a call to this server with \(n = 3\) :
\begin{align*} &\phantom{\rightarrow _0} P \mathbin {\,|\,}\overline{toyfib}\langle {3}\rangle \rightarrow _0P \mathbin {\,|\,}\mathtt {tick}. \mathtt {match}~3~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \rightarrow _1P \mathbin {\,|\,}\mathtt {match}~3~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \\ &\rightarrow _0^* P \mathbin {\,|\,}\overline{toyfib}\langle {2}\rangle \mathbin {\,|\,}\overline{toyfib}\langle {1}\rangle \rightarrow _0^* P \mathbin {\,|\,}\mathtt {tick}. \mathtt {match}~2~\cdots \mathbin {\,|\,}\mathtt {tick}. \mathtt {match}~1~\cdots \\ &\rightarrow _1^2 P \mathbin {\,|\,}\mathtt {match}~2~\cdots \mathbin {\,|\,}\mathtt {match}~1~\cdots \rightarrow _0^* P \mathbin {\,|\,}\overline{toyfib}\langle {1}\rangle \mathbin {\,|\,}\overline{toyfib}\langle {0}\rangle \mathbin {\,|\,}{\odot }\\ &\rightarrow _0^* P \mathbin {\,|\,}\mathtt {tick}. \mathtt {match}~1~\cdots \mathbin {\,|\,}\mathtt {tick}. \mathtt {match}~\mathtt {0}~\cdots \mathbin {\,|\,}{\odot }\rightarrow _1^2 P \mathbin {\,|\,}\mathtt {match}~1~\cdots \mathbin {\,|\,}\mathtt {match}~\mathtt {0}~\cdots \mathbin {\,|\,}{\odot }\rightarrow _0^* P \mathbin {\,|\,}{\odot }\mathbin {\,|\,}{\odot }\mathbin {\,|\,}{\odot }. \end{align*}
All the other reduction sequences are similar, only the order can change. Overall, if we count the number of \(\rightarrow _1\) , then we obtain a work of 5, which indeed corresponds to the number of calls to the function in Fibonacci of 3.
As for the span, we again look at a reduction but with annotated processes:
\begin{align*} &\phantom{\Rightarrow } 0 \mathbin {:}P \mathbin {\,|\,}0 \mathbin {:}\overline{toyfib}\langle {3}\rangle \Rightarrow 0 \mathbin {:}P \mathbin {\,|\,}0 \mathbin {:}\mathtt {tick}. \mathtt {match}~3~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \Rightarrow 0 \mathbin {:}P \mathbin {\,|\,}1 \mathbin {:}\mathtt {match}~3~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \\ &\Rightarrow 0 \mathbin {:}P \mathbin {\,|\,}1 \mathbin {:}\overline{toyfib}\langle {2}\rangle \mathbin {\,|\,}1 \mathbin {:}\overline{toyfib}\langle {1}\rangle \Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}1 \mathbin {:}\mathtt {tick}. \mathtt {match}~2~\cdots \mathbin {\,|\,}1 \mathbin {:}\mathtt {tick}. \mathtt {match}~1~\cdots \\ &\Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}2 \mathbin {:}\mathtt {match}~2~\cdots \mathbin {\,|\,}2 \mathbin {:}\mathtt {match}~1~\cdots \Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}2 \mathbin {:}\overline{toyfib}\langle {1}\rangle \mathbin {\,|\,}2 \mathbin {:}\overline{toyfib}\langle {0}\rangle \mathbin {\,|\,}2 \mathbin {:}{\odot }\\ &\Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}2 \mathbin {:}\mathtt {tick}. \mathtt {match}~1~\cdots \mathbin {\,|\,}2 \mathbin {:}\mathtt {tick}. \mathtt {match}~\mathtt {0}~\cdots \mathbin {\,|\,}2 \mathbin {:}{\odot }\Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}3 \mathbin {:}\mathtt {match}~1~\cdots \mathbin {\,|\,}3 \mathbin {:}\mathtt {match}~\mathtt {0}~\cdots \mathbin {\,|\,}2 \mathbin {:}{\odot }\\ &\Rightarrow ^* 0 \mathbin {:}P \mathbin {\,|\,}3 \mathbin {:}{\odot }\mathbin {\,|\,}3 \mathbin {:}{\odot }\mathbin {\,|\,}2 \mathbin {:}{\odot }. \end{align*}
Again, all the other reduction sequences are similar. The span is then 3, because the maximal annotation seen in this reduction is 3. And it indeed corresponds to the number of calls to the Fibonacci function under maximal parallelism, that we can also see as the depth of the tree of calls to the function.
To analyse the complexity of processes, we design two type systems, one for work and one for span. Because the complexity can depend on the size of some values, such as the toyfib server whose complexity depends on the value of n, we use sized types to keep track of the sizes of values in a process. We use integer expressions, called indices, to represent intervals. So, for instance, \(\mathsf {Nat}[I,J]\) represents integers between I and J, where I and J are indices. As we do not always know the actual size of an integer, we may use index variables. For example, in the process P, we do not know the actual value of n (as it depends on the context), so we will give it the type \(\mathsf {Nat}[i,i]\) , where i is an index variable representing the (unknown) size of n.
First, we explain the type system for work. A judgement has the shape \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K\) where \(\varphi\) is a set of index variables, \(\Phi\) a sef of constraints that we do not detail here, \(\Gamma\) a typing context, P a process and K an index representing the work complexity of K. The goal is to obtain the following theorem: if \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K,\) then K is a bound on the work of P. Some simple rules of this type system are
The (Par) rule expresses the fact that the work is summed over parallel composition, and the (Tick) rule expresses the fact that a \(\mathtt {tick}\) increases complexity by 1.
Let us detail briefly this type system on Example 2.1. The toyfib server would be given a type \(\forall i. \texttt {serv}^{F(i)}(\mathsf {Nat}[i,i])\) , expressing that for any index variable i representing the size of the input, the complexity of a call to this server is \(F(i)\) , where \(F(m)\) for any integer m is the function defined by
\begin{equation*} F(0) = F(1) = 1, \qquad F(m + 2) = 1 + F(m+1) + F(m). \end{equation*}
This equation exactly corresponds to the description of the number of calls to a Fibonacci function, and it can be obtained in the type system. Formally, we can derive the following judgement:
\begin{equation} i;\cdot ; toyfib \mathbin {:}\forall i. \texttt {serv}^{F(i)}(\mathsf {Nat}[i,i]), n \mathbin {:}\mathsf {Nat}[i,i] {|\!-_{\!\!\!\!{\text w}}}\mathtt {tick}. \mathtt {match}~n~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \triangleleft F(i). \end{equation}
(1)
And from this, we are able to deduce, in particular,
\begin{equation*} \cdot ;\cdot ; toyfib \mathbin {:}\forall i. \texttt {serv}^{F(i)}(\mathsf {Nat}[i,i]) {|\!-_{\!\!\!\!{\text w}}}P \mathbin {\,|\,}\overline{toyfib}\langle {3}\rangle \triangleleft F(3). \end{equation*}
As \(F(3) = 5\) , it is indeed a precise bound on the work. This typing derivation makes a good use of this unknown index i. Indeed, in the case where \(i \ge 2\) , the typing derivation for Equation (1) reaches a point where it has to type the subprocess \(\overline{toyfib}\langle {m}\rangle \mathbin {\,|\,}\overline{toyfib}\langle {p}\rangle\) . In this case, the type system relies on the type \(\forall i. \texttt {serv}^{F(i)}(\mathsf {Nat}[i,i])\) to say that, as m has size \(i {-}1\) , then the complexity of \(\overline{toyfib}\langle {m}\rangle\) is \(F(i {-}1)\) and similarly, the complexity of \(\overline{toyfib}\langle {p}\rangle\) is \(F(i {-}2)\) , and we recover the equation on the function F described above.
Now, for span, we also design a similar type system with judgements of the shape \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) , with again the property that if \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K,\) then K is a bound on the span of P. Intuitively, this type system corresponds to the previous one with additional information about time in types that we do not detail in this section. Some simple rules are
This time, the complexity of parallel composition is taken as the maximum, and for the (Tick) rule, we need a new operator \(\langle \Gamma \rangle _{{-}1}^{}\) on context that intuitively corresponds to reducing all time information by one, since the \(\mathtt {tick}\) makes time advance by one unit.
Similar to the work, we can derive the following judgement:
\begin{equation} i;\cdot ; toyfib \mathbin {:}\forall i. \texttt {serv}_{0}^{G(i)}(\mathsf {Nat}[i,i]), n \mathbin {:}\mathsf {Nat}[i,i] {|\!-_{\!\!\!\!{\text s}}}\mathtt {tick}. \mathtt {match}~n~\lbrace \mathtt {0}\mapsto {\odot } ;;~ \mathtt {s}(m) \mapsto \cdots \rbrace \triangleleft G(i), \end{equation}
(2)
where 0 is a time information indicating that the server is immediately ready to receive, and \(G(i)\) is the function defined by
\begin{equation*} G(0) = G(1) = 1, \qquad G(m + 2) = 1 + \max (G(m + 1), G(m)) = 1 + G(m + 1) = m + 2. \end{equation*}
As \(G(3) = 3\) , we again obtain a precise bound for span. Informally, we have the same main idea than before for work, but because of the rule for parallel composition, when considering the subprocess \(\overline{toyfib}\langle {m}\rangle \mathbin {\,|\,}\overline{toyfib}\langle {p}\rangle\) , the complexity is the maximum and not the sum.
In practice, this time information needed in the type system for span induces some important differences between the type system for work and for span, but this will be described in the body of the article.

3 Semantics of Pi-calculus

Let us define formally the semantics for \(\pi\) -calculus in this section. We first define on processes a congruence relation \(\equiv\) : This is the least congruence relation closed under
\begin{equation*} P \mathbin {\,|\,}{\odot }\equiv P \qquad P \mathbin {\,|\,}Q \equiv Q \mathbin {\,|\,}P \qquad P \mathbin {\,|\,}(Q \mathbin {\,|\,}R) \equiv (P \mathbin {\,|\,}Q) \mathbin {\,|\,}R \end{equation*}
\begin{equation*} (\nu a) (\nu b) P \equiv (\nu b) (\nu a)P \qquad (\nu a)(P \mathbin {\,|\,}Q) \equiv (\nu a) P \mathbin {\,|\,}Q~(\text{when } a \text{ is not free in } Q). \end{equation*}
Note that the last rule can always be applied from right to left by \(\alpha\) -renaming. Also, one can see that contrary to usual congruence relation for the \(\pi\) -calculus, we do not consider the rule for replicated input ( \(!P \equiv ~ !P \mid P\) ) as it will be captured by the semantics, and \(\alpha\) -conversion is not taken as an explicit rule in the congruence. By associativity, we will often write parallel composition for any number of processes and not only two. Another way to see this congruence relation is that, up to congruence, a process is entirely described by a set of channel names and a multiset of processes. Formally, we can give the following definition.
Definition 3.1 (Guarded Processes and Canonical Form).
A process G is guarded if it has one of the following shapes:
\begin{align*} G &:= ! a({v}).P\; {|}\;a({v}).P \; {|}\;\overline{a}\langle {\widetilde{e}}\rangle \; {|}\;\mathtt {tick}.P \\ &\phantom{:=} \; {|}\;\mathtt {match}~e~\lbrace \mathtt {0}\mapsto P ;;~ \mathtt {s}(x) \mapsto Q \rbrace \; {|}\;\mathtt {match}~e~\lbrace \lbrack \rbrack \mapsto P ;;~ x::y \mapsto Q \rbrace . \end{align*}
We say that a process is in canonical form if it has the form \((\nu \widetilde{a}) (G_1 \mathbin {\,|\,}\cdots \mathbin {\,|\,}G_n)\) with \(G_1,\dots ,G_n\) guarded processes.
Formally, we now show that all processes have a somewhat unique canonical form, as in Reference [34], Definition 4.1.2.
Lemma 3.2 (Existence of Canonical Form).
For any process P, there is a Q in canonical form such that \(P \equiv Q\) .
The proof is direct by induction on P.
To show the uniqueness of the canonical form, let us first introduce some notations. Recall that \(\alpha\) -renaming is not a rule of \(\equiv\) . We define the set \(\mathtt {name}\) of channel variables and the multiset \(\mathtt {gp}\) of guarded processes by:
\(\mathtt {name}({\odot }) = \emptyset\) and \(\mathtt {gp}({\odot }) = \emptyset\) ,
\(\mathtt {name}(P \mathbin {\,|\,}Q) = \mathtt {name}(P) \coprod \mathtt {name}(Q)\) and \(\mathtt {gp}(P \mathbin {\,|\,}Q) = \mathtt {gp}(P) {+}\mathtt {gp}(Q)\) ,
\(\mathtt {name}(P) = \emptyset\) and \(\mathtt {gp}(P) = \lbrack P \rbrack\) , when P is guarded,
\(\mathtt {name}((\nu a)P) = \mathtt {name(P)} \coprod \lbrace a \rbrace\) and \(\mathtt {gp}((\nu a)P) = \mathtt {gp}(P)\) ,
where \(\coprod\) denotes the usual disjoint union, \({+}\) denotes the usual union of multisets, and \([P]\) denotes the multiset corresponding to the singleton P with multiplicity 1. Then, we can easily show the following lemma by definition of the congruence relation.
Lemma 3.3.
If \(P \equiv Q,\) then \(\mathtt {name}(P) = \mathtt {name}(Q)\) and if \(\mathtt {gp}(P) = \lbrack P_1, \dots , P_n \rbrack\) and \(\mathtt {gp}(Q) = \lbrack Q_1, \dots , Q_m \rbrack\) , then \(m=n\) and for some permutation \(Q_1^{\prime },\dots ,Q_n^{\prime }\) of \(Q_1,\dots ,Q_n\) , we have \(P_i \equiv Q_i^{\prime }\) for all i.
From this lemma, we can easily deduce the uniqueness of canonical form:
Lemma 3.4 (Uniqueness of Canonical Form).
If
\begin{equation*} (\nu \widetilde{a}) (P_1 \mathbin {\,|\,}\cdots \mathbin {\,|\,}P_n) \equiv (\nu \widetilde{b}) (Q_1 \mathbin {\,|\,}\cdots \mathbin {\,|\,}Q_m), \end{equation*}
with \(P_1,\dots ,P_n,Q_1,\dots ,Q_m\) guarded processes, then \(m = n\) and \(\widetilde{a}\) is a permutation of \(\widetilde{b}\) . Moreover, for some permutation \(Q_1^{\prime },\dots ,Q_n^{\prime }\) of \(Q_1,\dots ,Q_n\) , we have \(P_i \equiv Q_i^{\prime }\) for all i.
We now define the usual reduction relation for the \(\pi\) -calculus, which we denote \(P \rightarrow _0Q\) . It is defined by the rules given in Figure 2. Remark that substitution should be well-defined to do some reduction steps: Channel names must be substituted by other channel names and base type variables can be substituted by any expression except channel names. However, when we will consider typed processes, this will always yield well-defined substitutions.
Fig. 2.
Fig. 2. Standard reduction rules.
For now, this relation cannot reduce a process of the form \(\mathtt {tick}.P\) . Therefore, we need to introduce a reduction rule for \(\mathtt {tick}\) . From this semantics, we will define a reduction corresponding to total complexity (work) and design a type system for this notion of complexity. Then, we will define parallel complexity (span) by taking an expansion of the standard reduction.
Let us give an example of process that will be of interest in the following. We express how to encode a usual recursive function in \(\pi\) -calculus by describing the Fibonacci function. Contrary to the function of Example 2.1, we use replicated input with a return channel to send the final value.
Example 3.5 (Fibonacci).
This representation of the Fibonacci function is described in Figure 3, where the actual process P corresponds to the parallel composition of those two servers add and fib.
Fig. 3.
Fig. 3. The Fibonacci function.
This example is similar to Example 2.1, but the differences are that we compute and return the value of the Fibonacci function using the return channel a. And so, when we do the recursive calls, we first create new channel names (b and c) and use them to recover the values of the two recursive calls.
Discussion. For the sake of simplicity, we consider only integers and lists as base types in our calculus, but the results can be generalized to other algebraic data-types. Moreover, we consider very simple expressions with only base constructors, but we could enrich the set of expressions with functions (such as addition on integers) and obtain the same results. Indeed, the core of our results lies in the parallel constructs, and the set of expressions has little impact on the theoretical results.

4 Work of A Process

4.1 Semantics for Work

We first describe a semantics for the work. The one-cost reduction relation \(\rightarrow _1\) is defined in Figure 4. Intuitively, this reduction removes exactly one tick at the top-level.
Fig. 4.
Fig. 4. Simple tick reduction rules.
Then from any process P, a sequence of reduction steps to Q is just a sequence of one-step reductions with \(\rightarrow _0\) or \(\rightarrow _1\) , and the work complexity of this sequence is the number of \(\rightarrow _1\) steps. In this article, we always consider the worst-case complexity so the work of a process is defined as the maximal complexity over all such sequences of reduction steps from this process.
Notice that with this semantics for work, adding \(\mathtt {tick}\) in a process does not change its behaviour: We do not create or erase reduction paths, we only modify the complexity.
Example 4.1 (Fibonacci).
If we consider the process P described in Example 3.5, then we can see that the work of \((\nu a) (P \mathbin {\,|\,}\overline{\text{fib}}\langle {10,a}\rangle)\) is \(F(10)\) where F is defined, as in Section 2, by
\begin{equation*} F(0) = 1, \qquad F(1) = 1, \qquad F(n + 2) = 1 {+}F(n + 1) {+}F(n). \end{equation*}

4.2 Sized Input/Output Types

We now define a type system to bound the work of a process. The goal is to obtain a soundness result: if a process P is typable then we can derive an integer expression K such that the work of P is bounded by K.
Our type system relies on the definition of indices to keep track of the size of values in a process. Those indices were, for example, used in Reference [9] and are greatly inspired by Reference [29]. The main idea of those types in a sequential setting is to control recursive calls by ensuring a decreasing in the sizes.
Definition 4.2.
The set of indices, representing natural numbers, is given by the following grammar:
\begin{equation*} I,J,K := i,j,k \; {|}\;f(I_1,\dots ,I_n). \end{equation*}
The variables \(i,j,k\) are called index variables. The set of index variables is denoted \(\mathcal {V}\) . The symbol f is an element of a given set of function symbols containing addition and multiplication. We also assume that we have subtraction as a function symbol, with \(n {-}m = 0\) when \(m \ge n\) . Each function symbol f of arity \(\mathtt {ar}(f)\) comes with an interpretation \([\![ f ]\!] _{}: \mathbb {N}^{\mathtt {ar}(f)} \rightarrow \mathbb {N}\) .
Given an index valuation \(\rho : \mathcal {V}\rightarrow \mathbb {N}\) , we extend the interpretation of function symbols to indices, noted \([\![ I ]\!] _{\rho }\) with
\begin{equation*} [\![ i ]\!] _{\rho } = \rho (i), \qquad [\![ f(I_1,\dots ,I_{\mathtt {ar}(f)}) ]\!] _{\rho } = [\![ f ]\!] _{} ([\![ I_1 ]\!] _{\rho },\dots ,[\![ I_{\mathtt {ar}(f)} ]\!] _{\rho }). \end{equation*}
In an index I, the substitution of the occurrences of i in I by J is denoted \(I \lbrace J / i \rbrace\) .
Definition 4.3 (Constraints on Indices).
Let \(\varphi \subset \mathcal {V}\) be a set of index variables. A constraint C on \(\varphi\) is an expression with the shape \(I \bowtie J\) where I and J are indices with free variables in \(\varphi\) and \(\bowtie\) denotes a binary relation on integers. Usually, we take \({\bowtie } \in \lbrace \le , \lt , =, \ne \rbrace\) . Finite sets of constraints are denoted by \(\Phi\) .
For a set \(\varphi \subset \mathcal {V}\) , we say that a valuation \(\rho : \varphi \rightarrow \mathbb {N}\) satisfies a constraint \(I \bowtie J\) on \(\varphi\) , noted \(\rho \vDash I \bowtie J\) when \([\![ I ]\!] _{\rho } \bowtie [\![ J ]\!] _{\rho }\) holds. Similarly, \(\rho \vDash \Phi\) holds when \(\rho \vDash C\) for all \(C \in \Phi\) . Likewise, we note \(\varphi ;\Phi \vDash C\) when for all valuations \(\rho\) on \(\varphi\) such that \(\rho \vDash \Phi\) we have \(\rho \vDash C\) . Remark that the order \(\le\) in a context \(\varphi ;\Phi\) is not total in general. For example, if \(\varphi = \lbrace i,j \rbrace\) , then \(\varphi ;\cdot \nvDash i \le ij\) and \(\varphi ;\cdot \nvDash ij \le i\) . As usual in type systems, we will use a sequence notation to represent sets, thus the set \(\lbrace i,j,k\rbrace\) could be represented, for example, by the sequence \((i,j,k)\) , where we can implicitly change the order in the sequence.
Definition 4.4.
The set of types and base types are given by the following grammars:
\begin{align*} T &:= \mathcal {B}\; {|}\;\texttt {ch}(\widetilde{T}) \; {|}\;\texttt {in}(\widetilde{T}) \; {|}\;\texttt {out}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {serv}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {iserv}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {oserv}^{K}(\widetilde{T}), \\ \mathcal {B}&:= \mathsf {Nat}[I,J] \; {|}\;\mathsf {List}[I,J](\mathcal {B}). \end{align*}
Intuitively, in the context \(\varphi ;\Phi\) , an integer n of type \(\mathsf {Nat}[I,J]\) must be such that \(\varphi ;\Phi \vDash I \le n \le J\) . Likewise, a list of type \(\mathsf {List}[I,J](\mathcal {B})\) must have a length between I and J. We may use \(\mathsf {Nat}[I]\) to denote the type \(\mathsf {Nat}[I,I]\) to gain some space, especially in examples of type derivations.
For channel types, we would like to allow for some flexibility by using a subtyping relation. For this reason, we choose to use input/output types [38]. Intuitively, in such a system, in addition to the type of expressions that can be sent and received through it, a channel is also given a set of capabilities: either it is both an input and output channel, or it has only one of those capabilities. This is especially useful for subtyping, as an input channel and an output channel do not behave in the same way with regard to subtyping, as we will explain in Section 4.3. Unlike in usual input/output types, in this work, we also distinguish two kinds of channels: the simple channels (that we will often call channels), and replicated channels (called servers).
The three different types for channels and servers correspond to the three different sets of capabilities. We note \(\mathsf {serv}\) when the server has both capabilities, \(\mathsf {iserv}\) when it only has input and \(\mathsf {oserv}\) when it only has output. Then, for servers, we have additional information: there is a quantification over index variables, and the index K stands for the complexity of the process spawned by this server. A typical example could be a server taking as input a list and a channel, and sending to this channel the sorted list, in time \(k \cdot n\) where n is the size of the list: \(P =~!a(x,b).\cdots \overline{b}\langle {e}\rangle\) where e represents at the end of the computation the list x sorted. Such a server name a could be given the type \(\forall i. \texttt {serv}^{k \cdot i}(\mathsf {List}[0,i](\mathcal {B}), \texttt {out}(\mathsf {List}[0,i](\mathcal {B})))\) . This type means that for all integers i, if given a list of size at most i and an output channel waiting for a list of size at most i, the process spawned by this server will stop at time at most \(k \cdot i\) . Those bounded index variables \(\widetilde{i}\) are especially useful for replicated input: as a replicated input is meant to be used several times with different values, it is necessary to allow for this kind of polymorphism on indices. Moreover, if a replicated input is used to encode a recursion, with this polymorphism, we can take into account the different recursive calls with different values and different complexities. This was briefly explained in Section 2 and it will be formally explained in Example 4.5.
We can now present the type system for work. A judgement for an expression has the shape \(\varphi ;\Phi ;\Gamma \vdash e \mathbin {:}T\) , where \(\varphi\) is a set of index variables, \(\Phi\) a set of constraints, \(\Gamma\) a typing context of the shape \({v}_1 \mathbin {:}T_1, \cdots {v}_m \mathbin {:}T_m\) , e is an expression and T is a type. The set of index variables \(\varphi\) is such that the free index variables in \(\Phi\) , \(\Gamma\) and T are included in \(\varphi\) . Intuitively, this typing means that if the constraints in \(\Phi\) are satisfied, then e has type T in the context \(\Gamma\) . In this work, almost all relations (such as, e.g., subtyping, typing relation) depend on a context \(\varphi ;\Phi\) , and \(\varphi\) always describes the set of usable free index variables, and \(\Phi\) a set of constraints on \(\varphi\) . Rules for expressions are given in Figure 5. We use the notation \(\varphi ;\Phi ;\Gamma \vdash \widetilde{e} \mathbin {:}\widetilde{T}\) for a sequence of typing judgements for expressions in the tuple \(\widetilde{e}\) . The rules are standard for a sized type system. We have the usual (Ax) rule, then both (Zero) and (Nil) rules indicate the values with size zero, and both (Succ) and (Cons) rules indicate that those constructors increase size by one. The (Sub) rule allows one to change the typing derivation according to the subtyping relation that will be defined in Section 4.3.
Fig. 5.
Fig. 5. Typing rules for expressions.
We now present the typing rules for processes. A judgement has the shape \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K\) , where K is an index, which means that under the constraints \(\Phi\) , in the context \(\Gamma\) , the process P is typable and its work complexity is bounded by K. The rules are described in Figures 6(a) and 6(b). Figure 6(b) describes rules specific to the work, whereas rules in Figure 6(a) will be reused for the span. Thus, we use the notation \(\vdash\) in Figure 6(a) instead of \({|\!-_{\!\!\!\!{\text w}}}\) to express that they are not specific to work.
Fig. 6.
Fig. 6. Typing rules for work.
The rules can be seen as a combination of input/output typing rules with rules found in a size type system for functional programs. The common rules that are used for both the span and work type systems are the rules for simple constructors of \(\pi\) -calculus and for sizes in pattern matching. The (Pzero) rule states that the empty process is typable, and it has complexity zero. The (Nu) rule allows one to add a new name in the context, without changing the complexity. The pattern matching rule for integers (Intpm) is a standard rule for sized types [9]. It says that if an integer e is between I and J, then in the first branch of the pattern matching, we can assume that \(I \ge 0,\) since e is equal to 0 in this branch. Similarly, in the second branch, we can assume that \(J \ge 1,\) since e should be greater than 1. In this case, the predecessor x has a size between \(I {-}1\) and \(J {-}1\) . The rule (Listpm) is similar. Then, we have again the usual (Sub) rule, which can also arbitrary increase the upper-bound on the complexity. This is especially important, because, if we look back at the (Intpm) rule, it considers that both branches must have the same complexity K, but in practice they may have different complexities \(K_1\) and \(K_2\) . However, thanks to the (Sub) rule, we can always consider a greater upper bound, in particular \(\max (K_1,K_2)\) . Thus, even if the branches have different complexities, we can always make them equal by considering the maximum with the (Sub) rule.
Rules that are specific to the work type system concern important constructors in the \(\pi\) -calculus. The (Par) rule expresses that the work of a parallel composition is the sum of the work of the two suprocesses. The (Tick) rules expresses that the \(\mathtt {tick}\) constructor increases complexity by 1. The (In) rule states that to type an input, the continuation P should be typable in a context where the variables \(\widetilde{{v}}\) are given the types \(\widetilde{T}\) , and the complexity of this input is the complexity of its continuation. Dually, in the (Out) rule, the expressions that are sent on this channel must have the expected types. As the complexity of a synchronization is already taken into account in the rule (In), the complexity in the (Out) rule is zero.
Finally, we have the rules for servers. In the rule (Iserv), the continuation P must satisfy the assumption given in the typing \(\forall \widetilde{i}. \texttt {iserv}^{K}(\widetilde{T})\) : with the new index variables \(\widetilde{i}\) , in a context where \(\widetilde{{v}}\) are given the expected types \(\widetilde{T}\) , the complexity of P must be K. Contrary to the (In) rule, this time the complexity K is captured in the type, but the bottom judgment has complexity zero. This is because in this case, we do now want a replicated input to have a non-zero complexity. Indeed, by definition of the reduction relation \(\rightarrow _0\) , a replicated input is never modified through a reduction. Thus, if a process has a replicated input, then this replicated input is retained in the normal form (if it exists). As a consequence, a non-zero complexity on an replicated input would always be an imprecise estimation of the complexity. Moreover, the complexity of a call to a server depends on the instantiation of \(\widetilde{i}\) that is decided by an output to the server. That is why, in the last rule (Oserv), we have to find an instantiation \(\widetilde{J}\) of the index variables \(\widetilde{i}\) such that the types of expressions correspond to this instantiation. The complexity then depends on this instantiation. A typical example is if a server represents a function with quadratic complexity in the size of its argument, with type \(\forall i. \texttt {serv}^{i^2}(\mathsf {Nat}[i,i])\) , and we call this server with the value 10, then we instantiate i by 10 and the overall complexity of this call to the server is \(10^2 = 100\) .

4.3 Subtyping

As explained before, with those types comes a notion of subtyping, to have some flexibility on bounds. Subtyping for base types is described by the rules of Figure 7(a). Both rules (Nat) and (List) express that we can always consider less precise bounds on the sizes.
Fig. 7.
Fig. 7. Subtyping.
Before explaining formally the rule for channel types, let us first introduce why input and output have different behaviours with regard to subtyping.
Let us consider, for the sake of the example, a type \(\mathsf {Nat}\) for integers, and a type \(\mathsf {Real}\) for real numbers, with \(\mathsf {Nat}\sqsubseteq \mathsf {Real}\) . Subtyping can be understood in the following way: in any process where a value v is used as a real, then it is safe to feed this process with an integer. So, if \(T \sqsubseteq U\) , then in a process that uses a value of type U, it is safe to consider that this value has type T instead.
Let us apply the same reasoning to channels. Consider a channel a that receives a message, in a process \(a(v).P\) . We suppose that the process uses the channel a as a channel working with real numbers. Then, v is used as a real number in P, so it is safe to use a value v of type \(\mathsf {Nat}\) instead. Overall, it is thus safe to assume this input is done on a value of type \(\mathsf {Nat}\) . So, for an input channel, we should have : \(\texttt {in}(\mathsf {Nat}) \sqsubseteq \texttt {in}(\mathsf {Real})\) .
Now, consider a channel a that sends a message, in a process \(\overline{a}\langle {e}\rangle\) . We suppose that the process uses the channel a as a channel working with integers. Then, the message e sent on this channel is an integer. In particular, it is also a real number. So, it is safe to assume that all messages sent on this channel are real numbers, and we should have \(\texttt {out}(\mathsf {Real}) \sqsubseteq \texttt {out}(\mathsf {Nat})\) .
If we look at the variance of the subtyping relation, then for an input channel, we have covariance, and for an output channel, we have contravariance. Then, a channel with both capabilities should have invariance. That is why it is important to make a distinction between input channels and output channels.
Formally, subtyping for server types is described in Figure 7(b), the rules for channel types can be deduced from the rules for servers. The first two rules (I/O to In) and (I/O to Out) state that we can always remove a capability from a type. Then, the (I/O) rule states that a type with both capabilities should be invariant in its type. The (In) rule expresses covariance for types. As for complexity, if the continuation has a complexity bounded by \(K^{\prime }\) then it is safe to bound it by K greater than \(K^{\prime }\) . Dually, the (Out) rule expresses contravariance for types. As for complexity, it does not harm the typing to consider that all calls to a server take less time than expected. Finally, the (Trans) rule allows for transitivity of the subtyping relation. This rule is only useful to combine the rules (I/O to In) and (In) or (I/O to Out) and (Out).
We also extend subtyping to contexts, and we write \(\Gamma \sqsubseteq \Delta\) when \(\Gamma\) and \(\Delta\) have the same domain and for each variable \({v}\mathbin {:}T \in \Gamma\) and \({v}\mathbin {:}T^{\prime } \in \Delta\) , we have \(T \sqsubseteq T^{\prime }\) .

4.4 Example

Example 4.5.
Let us take again the process for Fibonacci described in Example 3.5. We first give a typing for add. As there is no tick in add, this typing only shows how input/output types and sized types behave. A simplified version of this typing is given in Figure 8(a), where we ignore the easy premises, in particular for axioms (with rule (Ax)). For example, in the first rule (Iserv), there should be a premise
\begin{equation*} \cdot ;\cdot ; add \mathbin {:}\forall i,j. \texttt {serv}^{0}(\mathsf {Nat}[i],\mathsf {Nat}[j],\texttt {out}(\mathsf {Nat}[i {+}j])) \vdash add \mathbin {:}\forall i,j. \texttt {iserv}^{0}(\mathsf {Nat}[i],\mathsf {Nat}[j],\texttt {out}(\mathsf {Nat}[i {+}j])). \end{equation*}
But we ignore this as it is a simple derivation with the rules (Sub), (I/O to In) and (Ax). Also, recall that \(\mathsf {Nat}[I]\) denotes the type \(\mathsf {Nat}[I,I]\) . There are several things to notice in this typing. First, we can see a use of polymorphism. With the first (Iserv) rule, the variables \((n,m,a)\) are given the types \(\widetilde{U}(i,j)\) , but in the recursive call \(\overline{add}\langle {p,m,b}\rangle\) , those variables \((p,m,b)\) have the the types \(\widetilde{U}(i {-}1,j)\) , expressing that the size of the first argument decreases by one. Moreover, constraints on indices are important to this typing. Indeed, to prove the following subtyping relations:
\begin{equation*} \varphi ;(i \le 0) \vdash \mathsf {Nat}[j] \sqsubseteq \mathsf {Nat}[i {+}j], \qquad \varphi ;(i \ge 1) \vdash \mathsf {Nat}[(i {-}1) {+}j {+}1] \sqsubseteq \mathsf {Nat}[i {+}j], \end{equation*}
we have to prove
\begin{equation*} \varphi ;(i \le 0) \vDash j = i {+}j, \qquad \varphi ;(i \ge 1) \vDash (i {-}1) {+}j {+}1 = i {+}j. \end{equation*}
The first equality relies on the fact that \(i \le 0\) and so \(i = 0\) , and the second equality relies on \(i \ge 1,\) because, otherwise, we cannot deduce that \((i {-}1) {+}1 = i\) , since \(0 {-}1 = 0\) by definition. This behaviour of sizes in a type derivation is similar to the one in Reference [9] for functional programs.
Fig. 8.
Fig. 8. Work typing of Fibonacci.
We now describe the typing for the Fibonacci function. A simplified type derivation is given in Figure 8(b), and we detail here the important steps of this derivation. We use the Fibonacci function in indices, denoted \(Fib(I)\) , and we also use the function F defined in Example 4.1.
To begin with, we start with an (Iserv) rule, and we must prove that the continuation of the fib server has the expected complexity \(F(i)\) . As \(F(i)\) is always greater than 1, we have \(i;\cdot \vDash (F(i) {-}1) {+}1 = F(i)\) , and thus after the (Tick) rule, we have to prove that the remaining subprocess has complexity \(F(i) {-}1\) . We have then two pattern matchings. We ignore the case for zero and one but they are very similar to derivation for add: We can use the information \((i \le 0)\) or \((i\ge 1, i {-}1 \le 0)\) to show that the output to server has the expected type. In the main branch of pattern matching, we have the constraints \(\Phi := (i \ge 1, i {-}1 \ge 1)\) , which are equivalent to \((i \ge 2)\) , stating that the size of n is greater than 2.
Then, an important step is for the judgement
\begin{equation*} i;\Phi ;\Delta {|\!-_{\!\!\!\!{\text w}}}\overline{\text{fib}}\langle {m,b}\rangle \mathbin {\,|\,}\overline{\text{fib}}\langle {p,c}\rangle \mathbin {\,|\,}c(x). b(y). \overline{\text{add}}\langle {x,y,a}\rangle \triangleleft F(i) {-}1. \end{equation*}
We would like to use a (Par) rule, but to do that, we need a complexity with the shape of a sum. So, we use a (Sub) rule before to transform this complexity \(F(i) {-}1\) into \(F(i {-}1) + F(i {-}2) + 0\) , which comes from the definition of F given in Example 4.1. Now that we have a sum, with the (Par) rule, we obtain three independent premises. The first two premises correspond to a recursive call to fib, and we again use polymorphism: We show that as we took \((n,a)\) of types \(\widetilde{V}(i)\) , then we have \((m,b)\) of types \(\widetilde{V}(i {-}1)\) and \((p,c)\) of types \(\widetilde{V}(i {-}2)\) . Thus, the first recursive call \(\overline{\text{fib}}\langle {m,b}\rangle\) is a call to fib with size \(i {-}1\) , and it has then complexity \(F(i {-}1)\) and the second call \(\overline{\text{fib}}\langle {p,c}\rangle\) is a call to fib with size \(i {-}2\) and it has then complexity \(F(i {-}2)\) .
Finally, the third premise corresponds to adding the results of the previous recursive calls. We first recover those results with two (In) rules, and then we have to show that \(\overline{\text{add}}\langle {x,y,a}\rangle\) is a well-typed call to add. Again, we use polymorphism, and we show that \((x,y,a)\) has type \(\widetilde{U}(Fib(i {-}1),Fib(i {-}2))\) . Indeed, x has type \(\mathsf {Nat}[Fib(i {-}1)]\) , y has type \(\mathsf {Nat}[Fib(i {-}2)]\) , and so we only have to show that a has type \(\texttt {out}(\mathsf {Nat}[Fib(i {-}1) {+}Fib(i {-}2)])\) . As in \(\Delta ^{\prime }\) , we have the hypothesis \(a \mathbin {:}\texttt {out}(\mathsf {Nat}[Fib(i)])\) , we obtain this with subtyping, using the fact \(i;\Phi ; \vDash Fib(i {-}1) {+}Fib(i {-}2) = Fib(i)\) .

4.5 Soundness of the Type System

We now state the properties of this typing system. We do not detail the proofs as all proofs are a simpler version than the one for span that will be described in later sections. In this type system for work, we can easily obtain some properties such as weakening and strengthening and that index variables can be substituted by any index in a typing derivation. Finally, we have that substitution in processes preserves typing. With those properties, we obtain the usual subject reduction.
Theorem 4.6 (Subject Reduction).
If \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K\) and \(P \rightarrow _0Q,\) then \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text w}}}Q \triangleleft K\) .
Then, we also obtain the following theorem.
Theorem 4.7 (Quantitative Subject Reduction).
If \(P \rightarrow _1Q\) and \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K,\) then we have \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}Q \triangleleft K^{\prime }\) with \(\varphi ;\Phi \vDash K^{\prime } {+}1 \le K\) .
Proof.
By induction on \(P \rightarrow _1Q\) . All the cases are direct, since the rule for parallel composition is the sum of complexity and the rule for \(\nu\) does not change the complexity. Finally, the rule for tick gives directly this property.□
As a consequence, we almost immediately obtain that K is indeed a bound on the work of P if we have \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K\) . Formally, we have:
Theorem 4.8 (Work Complexity Bound).
If \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}P \triangleleft K,\) then, if we call n the work complexity of P, then we have \(\varphi ;\Phi \vDash K \ge n\) . In particular, for any \(\rho \mathbin {:}\varphi \rightarrow \mathbb {N}\) such that \(\rho \vDash \Phi\) , we have \([\![ K ]\!] _{\rho } \ge n\) .
This complexity bound only makes sense if the set of constraint \(\Phi\) is satisfiable.
Discussion. We emphasize on the fact that this soundness result is easily adaptable to similar processes and type systems for work. As stated before, we can enrich processes with other algebraic data-types and the proof can easily be adapted. An interesting consequence of this soundness theorem is that it immediately gives soundness for any subsystem. In particular, we detail in the next section a (slightly) weaker typing system where the shape of types are restricted to have an inference procedure close to the one in Reference [4].
Also note that additionally to complexity information, the type system also guarantees bounds on the size of values. For instance, if \(\Gamma\) contains \(a: \texttt {ch}(\mathsf {Nat}[I,J])\) , then any term transmitted through the channel a during an execution will be of integer type and of size between I and J. If one was not interested in the work but only by bounds on the sizes of values, then one could consider a type system whose rules are obtained by dropping K in all rules of Figures 6(a) and 6(b).
Moreover, there is an asymmetry between servers and simple channels in our type system: for servers, complexity comes from output and thus an index to keep track of the complexity is needed in the type, whereas for simple channels, complexity comes from input. However, this asymmetry is not necessary for the work type system. Indeed, servers need to have those typing rules, as explained before because of polymorphism, but for simple channels, we have a choice: We can either keep the current type system or modify simple channel types such that they are similar to servers types (with polymorphism over indexes and an index for complexity in the type). We chose to present the current type system first, because this way, we can show this alternative choice of typing for simple channels instead of mimicking servers, and because this asymmetry is essential for the span type system because of the way we use time information. This alternative choice of typing is presented in the next section, in Figure 9.
Fig. 9.
Fig. 9. Typing rules for processes for work inference.
Another interesting type system would be a non-syntax directed type-system, for which we have the choice between those two typing behaviours for simple channels. For the sake of simplicity, we avoid presenting this type system, but in fact the two choices have advantages and disadvantages and so allowing two different choices of typing can increase expressivity.

4.6 A Hint for Type Inference for Work

To infer a sized type for a process, we reduce the problem of finding a type derivation to that of satisfying a set of constraints on integers expressions. This idea has already been applied to sized type systems for functional languages [4, 29, 39] and has led to interesting results. Intuitively, this type inference procedure can be seen as a size reconstruction problem: We start from a type derivation without any size annotations, and we try to annotate it with sizes. We introduce for that variables for integer expressions, generate constraints on those variables and finally solve this set of constraints by finding an appropriate expression for each variable. Here is a very simple and informal example in \(\pi\) -calculus:
with \(\Gamma := a \mathbin {:}\texttt {ch}(\mathsf {Nat}), b \mathbin {:}\texttt {ch}(\mathsf {Nat})\) . We then reproduce this type derivation with additional variables for sizes, and some inferred constraints (for the sake of simplicity, we only consider upper bounds):
with \(\Delta := a \mathbin {:}\texttt {ch}(\mathsf {Nat}[0,I]), b \mathbin {:}\texttt {ch}(\mathsf {Nat}[0,J])\) . So, we only have one constraint in this typing, \(J = I {+}1\) . Thus, by substituting the variable J by the expression \(I {+}1\) , we obtain a valid typing for any expression I. Of course, in practice, constraints will be more complex, including, for example, recursive equations for an expression I when we consider servers.
In this section, we do not present the procedure for our type system, but we introduce a new system (that we call the intermediate type system) that is weaker that the previous one, but for which constraints inference will be simpler. Moreover, with this new system, we will obtain simpler constraints, essentially replacing constraints of the shape \(\varphi ;\Phi \vDash I \bowtie J\) by \(\varphi ^{\prime };\cdot \vDash I^{\prime } \bowtie J^{\prime }\) , by removing the need for a set of constraints \(\Phi\) in hypothesis.
To do this, we will mimic the work of Reference [4] for functional programs. In this work, usual types for functional programs are annotated with sizes, and in particular the arrow type \(T \rightarrow U\) is given a type \(\forall \widetilde{i}. T \rightarrow U\) , with a polymorphism similar to the one we have for server types. After defining a restriction of those arrow types (called canonical types), this article describes a sound and complete inference procedure for this type system. Intuitively, in Reference [4], the canonical form of a type forces the input of functions to have the shape \(\mathsf {Nat}[0,i]\) (or \(\mathsf {List}[0,i](\mathcal {B})\) ) for some new fresh variable i. Then more complex indices (such as, e.g., \(i^2 {+}j\) or other expressions) can occur in types at positions that correspond to outputs.
Our intermediate type system will use those canonical forms. Then, we show that this system is a restriction of a more general system for work so that we automatically deduce the soundness of the intermediate type system (with regard to work complexity). We can then use a similar inference procedure as Reference [4], which we will not detail here. To sum up, we first generate constraints from a process such that if this set of constraints is satisfiable, then the process is typable (soundness). To show expressivity, we also want that if a process is typable, then the generated set of constraints is indeed satisfiable (completeness). With this, we know that we do not lose expressivity with the reduction to a constraint satisfaction problem. Then the second step is to give those constraints to a SMT solver and hope that it can solve it (recall that this is undecidable in general).
We begin by designing an alternative type system for work, by changing the behaviour of channels, to have a quantification for channel variables even for channel types, then we merge server and channel together. This way, we obtain a type for channel very close to the arrow type in Reference [4].
Definition 4.9.
The set of types and base types for the intermediate type system are given by the following grammar:
\begin{equation*} \mathcal {B}:= \mathsf {Nat}[I,J] \; {|}\;\mathsf {List}[I,J](\mathcal {B}), \qquad T := \mathcal {B}\; {|}\;\forall \widetilde{i}. \texttt {ch}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {in}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {out}^{K}(\widetilde{T}). \end{equation*}
We consider as subtyping rules the ones from Figures 7(a) and 7(b), where \(\texttt {serv}\) is replaced by \(\texttt {ch}\) . The typing rules are given by Figures 5, 6(a), and 9. Thus, the only modification with regard to the system we presented before is that channel types and server types are not distinct anymore. We then obtain the following theorem, by a proof similar to the one from the previous section:
Theorem 4.10.
If \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K,\) then, if we call n the work complexity of P, we have \(\varphi ;\Phi \vDash K \ge n\) .

4.6.1 The Intermediate Type System.

A natural way to design a type inference procedure for our system is to start with a standard algorithm that, given a process P, produces a classical type for it, and then devise a procedure that decorates this classical type derivation with sizes and complexity information, to obtain a valid derivation.
For now, we only have a type system that gives a sound bound on the complexity, described in Figure 9. However, this type system relies on constraints of the shape \(\varphi ;\Phi \vDash I \bowtie J\) . As explained before, we would like to have simplified constraints, without hypotheses \(\Phi\) , so that we can use, for example, the solver of Reference [4]. Thus, we restrict the type system it to obtain a system very close to Reference [4] allowing us to mimic the type inference procedure of this article. We call this type system the intermediate type system.
Definition 4.11.
For this intermediate type system, we consider the following grammar:
\begin{equation*} \mathcal {B}_i:= \mathsf {Nat}[0,I] \; {|}\;\mathsf {List}[0,I] \; {|}\;\alpha ,\beta ,\dots ,\qquad T_i:= \mathcal {B}_i \; {|}\;\forall \widetilde{i}. \texttt {ch}^{K}(\widetilde{T_i}) \; {|}\;A,B,\dots , \end{equation*}
where \(\alpha ,\beta\) are base type variables and \(A,B\) are type variables, that we use in the type inference procedure when the type of a value is unknown. Then, we define types in canonical form, as in Reference [4].
Definition 4.12 (Canonical Intermediate Types).
A canonical intermediate type is a type of this shape:
\begin{equation*} \mathcal {B}_c := \mathsf {Nat}[0,i {+}n] \; {|}\;\mathsf {List}[0,i {+}n](\mathcal {B}_c) \; {|}\;\alpha ,\beta ,\dots ,\qquad T_c := \mathcal {B}_c \; {|}\;\forall i_1,\dots ,i_m. \texttt {ch}^{K}(\widetilde{T_c}) \; {|}\;A,B,\dots , \end{equation*}
where i is an index variable, n an integer, and in the channel type, the index variables of K belong to \(\lbrace i_1, \dots , i_m \rbrace\) and m is equal to the number of base type index occurrences in \(\widetilde{T_c}\) , denoted \(\mathtt {btocc}(\widetilde{T_c})\) , and defined by:
\(\mathtt {btocc}(T_c^1, \ldots , T_c^k) = \mathtt {btocc}(T_c^1) {+}\cdots {+}\mathtt {btocc}(T_c^k),\)
\(\mathtt {btocc}(\mathsf {Nat}[0,i]) = 1,\)
\(\mathtt {btocc}(\mathsf {List}[0,i](\mathcal {B}_c)) = 1 {+}\mathtt {btocc}(\mathcal {B}_c),\)
\(\mathtt {btocc}(\forall i_1,\dots ,i_m. \texttt {ch}^{K}(\widetilde{T_c})) = \mathtt {btocc}(A) = \mathtt {btocc}(\alpha) = 0.\)
Then, we also ask that for a canonical intermediate channel type, all the indices for base types corresponding to the base type index occurrences are an actual index variable (thus, \(n=0\) ), that they are all distinct, and in the left to right order (thus, we use all the different index variable names exactly once in base types and in a specific order). Moreover, as we are interested in an implementable procedure, a special focus is given to names of binding variables. We ask explicitly that in a canonical type, a binding name is never used twice in a type.
Example 4.13.
The following type is a canonical channel type:
\begin{equation*} \forall i_1^1, i_2^1, i_3^1. \texttt {ch}^{(i^1_1 {+}i^1_3)}(\mathsf {Nat}[0,i_1^1],\forall i^2_1. \texttt {ch}^{0}(\mathsf {Nat}[0,i^2_1],\texttt {ch}^{3}()),\mathsf {List}[0,i_2^1](\mathsf {List}[0,i_3^1](\alpha)),A). \end{equation*}
The first quantification is over three index variables, because there are exactly three positions in this type in which we can put an index variable without crossing another quantifier. Then, those three variables are indeed ordered from left to right. All the subtypes are also canonical, and notice that base type variables (A) and type variables ( \(\alpha\) ) are not taken into account in the counting of index variables.
The use of canonical types is mainly to simplify the inference procedure. First, by fixing the number of variables after a quantification, we avoid having to guess the number of variables. Then, we try to put those variables at strategic locations, such that all variables give some useful information (i.e., the size of one base type). Moreover, with a canonical type, all unknown sizes are just a unique variable i and not a possibly convoluted expression, so that we can change the pattern matching rule to get rid of the constraints \(\Phi\) of the previous type system, and we obtain in general simpler constraints.
Obviously, a canonical intermediate type is an intermediate type. In our intermediate type system, we will ask that all channel names have a canonical type. Moreover, in a context \(\Gamma\) , we will require all types to be canonical. Formally, a typing judgment has the shape \(\varphi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K,\) where \(\Gamma\) contains only canonical types, and there is no set of constraints \(\Phi\) . Subtyping is defined as a restriction of the previous subtyping relation to intermediate types, and the type system is given by Figures 10(a) and 10(b). One can see that the invariants described above on canonical types are respected. Also, there are no subtyping rules in this type system, as canonical types do not need subtyping, and the modification on the complexity bound are internalized in the useful rules. This way, all rules are syntax-directed, which simplifies the inference procedure. Moreover, in this typing, and for the following of this section, we only consider processes with well written pattern matching, meaning that pattern matching can only be done on base type variables (otherwise, the pattern matching is not useful...). Thanks to this restriction, we can consider that the base type element in a pattern matching is a canonical type, and this helps us to get rid of the previous rule for pattern matching where we needed to add constraints in the branches. The idea is that instead of adding the constraint \(i \ge 1\) to the typing judgement, we perform a substitution of i by an index of the shape \(i {+}1\) . Thus i now becomes the size of the predecessor (or the tail for a list). Without this set of constraints \(\Phi\) in a typing, we obtain a type system closer to the one of Reference [4]. To sum up, the rules are similar to the one for \({|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}\) , but subtyping is internalized in the rules, and pattern matching is modified to get rid of the constraints \(\Phi\) .
Fig. 10.
Fig. 10. Intermediate typing rules.
Now, let us show that if a process is typable with \({|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}\) , then it is typable with \({|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}\) .
Theorem 4.14.
If a process P is such that \(\varphi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K\) , then for any \(\Gamma _{sub}\) obtained from \(\Gamma\) by substituting all type variables by actual types, we have \(\varphi ;\cdot ;\Gamma _{sub} {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K\) .
From this, a direct corollary is that if \(\varphi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K\) , then K is a bound on the work of P.
Proof.
The proof is done by induction on \(\varphi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}P \triangleleft K\) . The type variables do not cause any problem, since in a intermediate typing, if we can use a type variable, then it means that this type is never really inspected. When typing an expression, this is rather straightforward, using subtyping for expressions. Again, for typing rules for processes, many cases are straightforward just by using the subtyping rule of Figure 6(a). Thus, we only detail the interesting case.
If the typing is
then we would like to give the following type:
From the typing \(\varphi ;\Gamma {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{P} \triangleleft {K_1}\) , obtaining \(\varphi ;(0 \le 0);\Gamma _{sub} {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{P} \triangleleft {K}\) is direct by induction hypothesis. Now, by induction hypothesis, we also obtain
\begin{equation*} \varphi ;\cdot ;\Gamma _{sub} \lbrace i {+}1 / i \rbrace , x \mathbin {:}\mathsf {Nat}[0,i] {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{Q} \triangleleft {K_2}, \qquad \varphi ;\cdot \vDash K_2 \le K \lbrace i {+}1 / i \rbrace . \end{equation*}
Then, by index substitution, we have
\begin{equation*} \varphi ;\cdot ;\Gamma _{sub} \lbrace i {+}1 / i \rbrace \lbrace i {-}1 / i \rbrace , x \mathbin {:}\mathsf {Nat}[0,i {-}1] {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{Q} \triangleleft {K_2 \lbrace i {-}1 / i \rbrace ,} \qquad \varphi ;\cdot \vDash K_2 \lbrace i {-}1 / i \rbrace \le K \lbrace i {+}1 / i \rbrace \lbrace i {-}1 / i \rbrace . \end{equation*}
Thus, by weakening, we obtain
\begin{equation*} \varphi ;(i \ge 1);\Gamma _{sub} \lbrace i {+}1 / i \rbrace \lbrace i {-}1 / i \rbrace , x \mathbin {:}\mathsf {Nat}[0,i {-}1] {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{Q} \triangleleft K_2 \lbrace i {-}1 / i \rbrace , \end{equation*}
\begin{equation*} \varphi ;(i \ge 1) \vDash K_2 \lbrace i {-}1 / i \rbrace \le K \lbrace i {+}1 / i \rbrace \lbrace i {-}1 / i \rbrace . \end{equation*}
Then, as we have \(i \ge 1\) , we obtain \((i {-}1) {+}1 = i\) . Moreover, \(0 {-}1 = 0\) by definition. So, by subtyping, we obtain
\begin{equation*} \varphi ;(i \ge 1);\Gamma _{sub}, x \mathbin {:}\mathsf {Nat}[0 {-}1,i {-}1] {|\!-_{\!\!\!\!{\text w}}}^{\!\!\!\!{\text {alt}}}{Q} \triangleleft {K.} \end{equation*}
We can conclude the proof as the typing above can be obtained.
The other case of pattern matching with \(n \gt 0\) is easier.□
Thus, if we have a correct and complete procedure for this intermediate type system, then we obtain indeed a bound on the complexity thanks to the soundness result of the previous type system. Moreover, this new type system does not seem too restrictive in practice. The main problem is that we cannot have too much information about the input. For example, to have a more understandable type, we might like to assume that an input list has a length \(2^i\) for some i. With this type system, this kind of assumption is not possible anymore, thus we would need to use the logarithm to obtain a similar reasoning. In general, we can lose some information about the input of a function that could have been useful. Subtyping also becomes very restrained, we no longer have input/output types and subtyping between canonical forms is not really useful, this is just equality everywhere. Note that in practice, because of canonical types, checking type equality is easy, since canonical forms drastically simplify the problems of \(\alpha\) -renaming and reordering of quantifiers.
Still, with this intermediate type system, we can mimic the work in Reference [4], and we obtain a procedure that is sound and complete for this intermediate type system, and such that the inferred constraints can be fed to the solver of Reference [4]. We have not explored yet a procedure that would work directly for our original type system and be complete with regard to this system. Moreover, we do not know if the inferred constraints would be solvable in practice.

5 Type System for Parallel Complexity

5.1 Definition of Span

We now define another notion of complexity taking into account parallelism. Before formally presenting the semantics, we show with some simple examples what kind of properties we would like for this parallel complexity.
First, we want a parallel complexity that works as if we had an infinite number of processors. For instance, on the process \(\mathtt {tick}. {\odot }\mathbin {\,|\,}\mathtt {tick}.{\odot }\mathbin {\,|\,}\mathtt {tick}.{\odot }\mathbin {\,|\,}\cdots \mathbin {\,|\,}\mathtt {tick}.{\odot }\) , we want the complexity to be 1, no matter the number of \(\mathtt {tick}\) in parallel.
Moreover, reductions with a zero-cost complexity (in our setting, this should mean all reductions except when we reduce a \(\mathtt {tick}\) ) should not harm this maximal parallelism. For example, \(a(). \mathtt {tick}. {\odot }\mathbin {\,|\,}\overline{a}\langle {}\rangle \mathbin {\,|\,}\mathtt {tick}. {\odot }\) should also have complexity one, because intuitively this synchronization between the input and the output can be done independently of the \(\mathtt {tick}\) on the right, and then the \(\mathtt {tick}\) on the left can be reduced in parallel with the \(\mathtt {tick}\) on the right.
Finally, as before for the work, adding a \(\mathtt {tick}\) should not change the behaviour of a process. For instance, consider the process \(\mathtt {tick}. a().P_0 \mathbin {\,|\,}a().\mathtt {tick}. P_1 \mathbin {\,|\,}\overline{a}\langle {}\rangle\) , where a is not used in \(P_0\) and \(P_1\) . This process should have the complexity \(max(1 {+}C_0,1 {+}C_1)\) , where \(C_i\) is the cost of \(P_i\) . Indeed, there are two possible reductions, either we reduce the tick, and then we synchronize the left input with the output, and continue with \(P_0\) , or we first do the synchronization with the right input and the output, we then reduce the ticks, and finally we continue as \(P_1\) .
A possible way to define such a parallel complexity would be to adapt causal complexity [14, 15, 16]; however, we believe there is a simpler presentation for our case. We will show in Section 7 the equivalence between our notion and a kind of causal complexity. The idea for defining span has been proposed by Naoki Kobayashi (private communication). It consists in introducing a new construction for processes, \(m: P\) , where m is an integer. A process using this constructor will be called an annotated process. Intuitively, this annotated process has the meaning P with m ticks before. We can then enrich the congruence relation \(\equiv\) with the following rules:
\begin{equation*} m : (P \mathbin {\,|\,}Q) \equiv (m : P) \mathbin {\,|\,}(m : Q), \qquad m : (\nu a) P \equiv (\nu a) (m : P), \qquad m : (n : P) \equiv (m + n) : P, \qquad 0 : P \equiv P. \end{equation*}
This intuitively means that the ticks can be distributed over parallel composition, name creation can be done before or after ticks without changing the semantics, ticks can be grouped together, and finally zero tick is equivalent to nothing.
With this congruence relation and this new constructor, we can give a new shape to the canonical form presented in Definition 3.1.
Definition 5.1 (Canonical Form for Annotated Processes).
An annotated process is in canonical form if it has the shape
\begin{equation*} (\nu \widetilde{a}) (n_1 : G_1 \mathbin {\,|\,}\cdots \mathbin {\,|\,}n_m : G_m), \end{equation*}
with \(G_1,\dots ,G_m\) guarded annotated processes.
Note that the congruence relation above allows one to obtain this canonical form from any annotated processes. With this intuition in mind, we can then define a reduction relation \(\Rightarrow\) for annotated processes. The rules are given in Figure 11. We do not detail the rules for integers as they are deducible from the ones for lists. Intuitively, this semantics works as the usual semantics for \(\pi\) -calculus, but when doing a synchronization, we keep the maximal annotation, and ticks are memorized in the annotations.
Fig. 11.
Fig. 11. Reduction rules.
We then define the parallel complexity of an annotated process.
Definition 5.2 (Span).
Let P be an annotated process. We define its local complexity \(\mathcal {C}_{\ell }(P)\) by:
\(\mathcal {C}_{\ell }(n : P) = n {+}\mathcal {C}_{\ell }(P),\)
\(\mathcal {C}_{\ell }(P \mathbin {\,|\,}Q) = \max (\mathcal {C}_{\ell }(P),\mathcal {C}_{\ell }(Q)),\)
\(\mathcal {C}_{\ell }((\nu a) P) = \mathcal {C}_{\ell }(P),\)
\(\mathcal {C}_{\ell }(G) = 0 \text{ if G is a guarded process.}\)
Equivalently, \(\mathcal {C}_{\ell }(P)\) is the maximal integer that appears in the canonical form of P. Then, for an annotated process P, its span is given by \(\mathsf {span}(P) := \max \lbrace n \mid P \Rightarrow ^* Q \wedge \mathcal {C}_{\ell }(Q) = n \rbrace\) where \(\Rightarrow ^*\) is the reflexive and transitive closure of \(\Rightarrow\) .
To show that this parallel complexity is well-behaved, we give the following lemmas.
Lemma 5.3 (Congruence and Local Complexity).
Let \(P,Q\) be annotated processes such that \(P \equiv Q\) . Then, we have \(\mathcal {C}_{\ell }(P) = \mathcal {C}_{\ell }(Q)\) .
Lemma 5.4 (Reduction and Local Complexity).
Let \(P,P^{\prime }\) be annotated processes such that \(P \Rightarrow P^{\prime }\) . Then, we have \(\mathcal {C}_{\ell }(P^{\prime }) \ge \mathcal {C}_{\ell }(P)\) .
Those lemmas are proved by induction. The main point for the second lemma is that guarded processes have a local complexity equal to zero, thus doing a reduction will always increase this local complexity. That is why, to bound the complexity of an annotated process, we need to reduce it with \(\Rightarrow\) , and then we have to take the maximum local complexity over all normal forms. Moreover, this semantics respects the conditions given in the beginning of this section.
Let us now present a type system for span. We want as previously a type system such that typing a process gives us a bound on its span.

5.2 Sized Types with Time

The type system is an extension of the previous one for work. To take into account parallelism, we need a way to synchronize the time between processes in parallel, thus we will add some time information in types, as in Reference [30] or Reference [12]. Formally, we start with the types for work, and we decorate channels with an index I indicating time. Recall that in our calculus, we consider that one unit of time corresponds to the time expressed by a \(\mathtt {tick}\) .
Definition 5.5.
The set of types and base types are given by the following grammar:
\begin{align*} \mathcal {B}&:= \mathsf {Nat}[I,J] \; {|}\;\mathsf {List}[I,J](\mathcal {B}),\\ T &:= \mathcal {B}\; {|}\;\mathsf {ch}_{I}(\widetilde{T}) \; {|}\;\mathsf {in}_{I}(\widetilde{T}) \; {|}\;\mathsf {out}_{I}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {serv}_{I}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {iserv}_{I}^{K}(\widetilde{T}) \; {|}\;\forall \widetilde{i}. \texttt {oserv}_{I}^{K}(\widetilde{T}). \end{align*}
As before, we have channel types, server types, and input/output capabilities in those types. For a channel type or a server type, the index I is called the time of this type. Giving a channel name the type \(\mathsf {ch}_{I}(\widetilde{T})\) ensures that communication on this channel should happen at a time t such that \(0 \le t \le I\) . For example, a channel name of type \(\mathsf {ch}_{0}(\widetilde{T})\) should be used to communicate before any tick occurs. With this information, we have a bound on when the continuation P of an input \(a(\widetilde{{v}}).P\) will be available. A server name of type \(\forall \widetilde{i}. \texttt {iserv}_{I}^{K}(\widetilde{T})\) has a slightly different meaning: it means that the inputs for this server should all be ready to receive for any time greater than I. For instance, a process \(\mathtt {tick}. ! a({v}).P\) enforces that the type of a is \(\forall \widetilde{i}. \texttt {serv}_{I}^{K}(\widetilde{T})\) with I greater than one, as the replicated input is not ready to receive at time zero. About the free variables in a server types, \(\forall \widetilde{i}. \texttt {serv}_{I}^{K}(\widetilde{T})\) , we emphasize the fact that \(\widetilde{i}\) can appear in K and \(\widetilde{T}\) but not in I. Indeed, the time that a server takes to become ready does not depend on the values sent to this server. However, to harmonize notations with channels, this time I is written after the quantification over \(\widetilde{i}\) even if it does not depend on it.
As before, we define a notion of subtyping on those types. The rules are essentially the same as the ones in Figures 7(a) and 7(b). The only difference is that we enforce the time of a type to be invariant in subtyping.
To write the typing rules, we need some other definitions to work with time in types. The first thing we need is a way to advance time. Indeed, consider the simple example \(\mathtt {tick}. a() \mathbin {\,|\,}\mathtt {tick}. \overline{a}\langle {}\rangle\) , when we consider the left branch, then after the \(\mathtt {tick}\) (i.e., after one time unit), both the input and the output should be ready (contrary to work where we would still have to wait one time unit). Thus, we have to express that the time advances in all the parallel branches simultaneously, and this is done by the operator we will introduce.
Definition 5.6 (Advancing Time in Types).
Given a set of index variables \(\varphi\) , a set of constraints \(\Phi\) , a type T and an index I, we define T after I time units, denoted \(\langle T \rangle _{{-}I}^{\varphi ;\Phi }\) by:
\(\langle \mathcal {B} \rangle _{{-}I}^{\varphi ;\Phi } = \mathcal {B}.\)
\(\langle \mathsf {ch}_{J}(\widetilde{T}) \rangle _{{-}I}^{\varphi ;\Phi } = \mathsf {ch}_{(J {-}I)}(\widetilde{T})\) if \(\varphi ;\Phi \vDash J \ge I\) . It is undefined otherwise.
Other channel types follow exactly the same pattern.
\(\langle \forall \widetilde{i}. \texttt {serv}_{J}^{K}(\widetilde{T}) \rangle _{{-}I}^{\varphi ;\Phi } = \forall \widetilde{i}. \texttt {serv}_{J {-}I}^{K}(\widetilde{T})\) if \(\varphi ;\Phi \vDash J \ge I\) .
Otherwise, \(\langle \forall \widetilde{i}. \texttt {serv}_{J}^{K}(\widetilde{T}) \rangle _{{-}I}^{\varphi ;\Phi } = \forall \widetilde{i}. \texttt {oserv}_{J {-}I}^{K}(\widetilde{T}).\)
\(\langle \forall \widetilde{i}. \texttt {iserv}_{J}^{K}(\widetilde{T}) \rangle _{{-}I}^{\varphi ;\Phi } = \forall \widetilde{i}. \texttt {iserv}_{J {-}I}^{K}(\widetilde{T})\) if \(\varphi ;\Phi \vDash J \ge I\) .
It is undefined otherwise.
\(\langle \forall \widetilde{i}. \texttt {oserv}_{J}^{K}(\widetilde{T}) \rangle _{{-}I}^{\varphi ;\Phi } = \forall \widetilde{i}. \texttt {oserv}_{J {-}I}^{K}(\widetilde{T})\) .
This definition can be extended to contexts, with \(\langle {v}\mathbin {:}T, \Gamma \rangle _{{-}I}^{\varphi ;\Phi } = {v}\mathbin {:}\langle T \rangle _{{-}I}^{\varphi ;\Phi }, \langle \Gamma \rangle _{{-}I}^{\varphi ;\Phi }\) if \(\langle T \rangle _{{-}I}^{\varphi ;\Phi }\) is defined. Otherwise, \(\langle {v}\mathbin {:}T, \Gamma \rangle _{{-}I}^{\varphi ;\Phi } = \langle \Gamma \rangle _{{-}I}^{\varphi ;\Phi }\) . We will often omit \(\varphi ;\Phi\) in the notation when it is clear from the context. Recall that as the order \(\le\) on indexes is not total, \(\varphi ;\Phi \nvDash J \ge I\) does not mean that \(\varphi ;\Phi \vDash J \lt I\) .
Let us explain a bit the definition here. For base types, there is no time indication, thus nothing happens. For simple channel types, there are two cases. Either the bound J on the time was greater than I, and we only have to subtract I from J to make time pass. Or the bound J was not greater than I, and this channel cannot be used any more after I units of time, thus we erase this channel from the context.
To understand server types, let us again look at a simple example \(\mathtt {tick}. !a().P \mathbin {\,|\,}\overline{a}\langle {}\rangle \mathbin {\,|\,}\mathtt {tick}.\mathtt {tick}. \overline{a}\langle {}\rangle\) . As explained before, the time of a server only corresponds to the time it takes for the input to be ready, thus the time I of this server should be one. The second branch \(\overline{a}\langle {}\rangle\) should have this information, because it means it has to wait one unit of time, and the third branch \(\mathtt {tick}.\mathtt {tick}. \overline{a}\langle {}\rangle\) should only know that the corresponding input is already ready after two time units. Moreover, by definition, after at least two time units, it should not be possible any more to redefine an input for this server, as it would break the invariant “all inputs are ready before I time units.”
If we formalize this intuition, then we obtain a dissymmetry between the input and output capabilities for servers. The input capability behaves like a simple channel, if the time J is too small, we erase this capability, since we cannot define any more an input. However, the output capability is never erased, even if the time J is too small, but we still need this information (when \(I \ge 0\) ) to estimate the time of waiting for the input to be available.
We remark that this definition of time advancing generates constraints in a type derivation. Indeed, if we want \(\langle a \mathbin {:}\mathsf {ch}_{J}(\widetilde{T}) \rangle _{{-}1}^{\varphi ;\Phi } = a \mathbin {:}\mathsf {ch}_{J {-}1}(\widetilde{T})\) , then we must have \(\varphi ;\Phi \vDash J \ge 1\) . This will be useful to see what constraints the complexity of a process should satisfy, as we will see in examples.
We also need another definition on time information.
Definition 5.7 (Time Invariant Context).
Given a set of index variables \(\varphi\) and a set of constraints \(\Phi\) , a context \(\Gamma\) is said to be time invariant when it only contains base type variables or output server types \(\forall \widetilde{i}. \texttt {oserv}_{I}^{K}(\widetilde{T})\) with \(\varphi ;\Phi \vDash I = 0\) .
Such a context is thus invariant by the operator \(\langle \cdot \rangle _{{-}I}^{}\) for any I. This is typically the kind of context that we need to define a server, as a server should not be dependent on the time it is called. We can now present the type system. Typing rules for expressions and some processes do not change; they can be found in Figures 5 and 6(a). In Figure 12, we present the remaining rules in this type system that differ from the ones in Figure 6(b). As before, a typing judgement \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) intuitively means that under the constraints \(\Phi\) , in a context \(\Gamma\) , a process P is typable and its span complexity is bounded by K.
Fig. 12.
Fig. 12. Span typing rules for processes.
The rule (Par) means that the parallel complexity is the maximum between the two processes instead of the sum (as explained in Section 4 for the (Intpm) rule, asking for the same complexity K is equivalent to taking the maximum because of the (Sub) rule). The (Tick) rule again says that complexity increases by 1, but it also decreases all time information in types by one.
Then, the (In) rule, the (Out) rule, and the (Oserv) rule are very similar to the ones for work. The only difference is this time information I. Indeed, in the span type system, as explained before, time should advance simultaneously in all parallel branches; however, when we consider a process of the shape \(a(\widetilde{{v}}).P\) , this process is not reduced immediately as it has to wait for a corresponding output to be ready. Thus, we have to estimate the time of waiting. This is estimated by this index I, and so we consider that I time units should pass before proceeding to type the continuation, as we can see with the \(\langle \Gamma \rangle _{{-}I}^{}\) operation.
Finally, the (Iserv) rules is far more complex that the previous one for work. Again, we have to wait those I units of time to synchronize time for all subprocesses. An important difference between input server and all the other processes is that, if an input server is ready to receive a message at time t, it should always be ready to receive a message at time \(t^{\prime } \ge t\) , so that we can always be able to make a recursive call. Because of this, we ask that the context \(\Gamma ^{\prime }\) in the continuation is time invariant, so that this continuation does not depend on current time. So, to have this time invariant context, we integrate some weakening on context (with \(\Delta\) ) and an explicit subtyping rule in the premises. This is because \(\langle \Gamma \rangle _{{-}I}^{\varphi ;\Phi }\) is not time invariant in general, since the type of a contains the input capability. However, if this server has both input and output capabilities, we can give a time invariant type for a (or other servers) just by removing the input capability, which can be done by subtyping.
Finally, notice that because of the advance of time in a context, some channels name could disappear (because their time is up), thus there is a kind of “time uniqueness” for channels, contrary to the previous section on work. This will be detailed later in Section 5.3.4.
Before moving to examples, let us show what results we expect from this type system.
Theorem 5.8 (Typing and Complexity).
Let P be a process such that \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) , then \(\varphi ;\Phi \vDash K \ge \mathsf {span}(P)\) .
Note that this theorem talks about open processes. However, our notion of span does not behave well with open processes. For example, the process \(\mathtt {match}~{v}~\lbrace \mathtt {0}\mapsto P ;;~ \mathtt {s}(x) \mapsto Q \rbrace\) is in normal form for a variable \({v}\) , thus this process has span zero. However, with the type system, we will not give it a zero complexity. This is because we will also obtain the following corollary:
Corollary 5.9 (Complexity and Open Processes).
We have:
If \(\varphi ;\Phi ; \Gamma , \widetilde{{v}} \mathbin {:}\widetilde{T} {|\!-_{\!\!\!\!{\text s}}}{P} \triangleleft {K}\) , then for any sequence of expressions \(\widetilde{e}\) such that \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}{\widetilde{e}} \mathbin {:}{\widetilde{T}}\) , then \(\varphi ;\Phi \vDash K \ge \mathsf {span}(P [\widetilde{{v}} := \widetilde{e}])\) .
If \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) , then for any other annotated process Q such that \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K^{\prime }\) , we have \(\varphi ;\Phi \vDash max(K,K^{\prime }) \ge \mathsf {span}(P \mathbin {\,|\,}Q)\) .
So, when we have a typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}{P} \triangleleft {K}\) for an open process, one should not see K as a bound on the actual complexity on P, but rather as a bound on the complexity of this particular process in an environment respecting the type of \(\Gamma\) . So, in \(\varphi ;\Phi ;v \mathbin {:}\mathsf {Nat}[2,10] {|\!-_{\!\!\!\!{\text s}}}{\mathtt {match}~{v}~\lbrace \mathtt {0}\mapsto P ;;~ \mathtt {s}(x) \mapsto Q \rbrace } \triangleleft {K}\) , this index K is a bound on the complexity of this pattern matching under the assumption that the environment gives to \({v}\) an integer value between 2 and 10.
We can then, for example, understand the rule for input by taking the judgement \(\varphi ;\Phi ;a \mathbin {:}\mathsf {ch}_{3}() {|\!-_{\!\!\!\!{\text s}}}{a().\mathtt {tick}.{\odot }} \triangleleft {4}\) . This expresses that with an environment providing a message on a within 3 time units, this process terminates in 4 time units.
Discussion. We observe that if we remove all size annotations and merge server types and channel types together, then we get back the classical input/output types, and all the rules described here are admissible in the classical input/output type system for the \(\pi\) -calculus.

5.3 Examples

5.3.1 Input, Time, and Complexity.

We first illustrate the time system on a simple generic example that will be very useful for other concrete examples. Let us consider the process \(P = c(). b(). \overline{a}\langle {}\rangle\) . We have the following typing for P:
\begin{equation*} \varphi ;\Phi ; a \mathbin {:}\mathsf {out}_{I_a}(), b \mathbin {:}\mathsf {in}_{I_b}(), c \mathbin {:}\mathsf {in}_{I_c}() {|\!-_{\!\!\!\!{\text s}}}P \triangleleft I_a, \end{equation*}
if and only if \(\varphi ;\Phi \vDash I_a \ge I_b \ge I_c\) . Indeed, the typing derivation has the shape
The constraints \(\varphi ;\Phi \vDash I_a \ge I_b \ge I_c\) are necessary in order for the various \(\langle \cdot \rangle _{{-}I}^{}\) to be defined. So, to sum up, the complexity of such a sequence of input/output is given by the time of the last channel, and the constraints that appear are that the order of time should correspond to the order of the process sequence.
Another interesting case of this is when a is a server type and not a simple channel type: let us take \(a \mathbin {:}\texttt {oserv}_{I_a}^{K_a}()\) in the example above. As an output capability for a server type is never erased by \(\langle \cdot \rangle _{{-}I}^{}\) , we have fewer restrictions. In particular, we only need \(\varphi ;\Phi \vDash I_b \ge I_c\) and the complexity becomes \(K_a {+}I_b {+}(I_a {-}I_b)\) . Recall that this is not always equal to \(K_a {+}I_a\) by definition of subtraction; for example, if \(I_a = 0\) , then we have the complexity \(K_a {+}I_b\) in the end.
Finally, one can remark that if we add a \(\mathtt {tick}\) constructor to this process, then the only thing it does is changing the shape of constraints. For example, if \(P = \mathtt {tick}. c(). \mathtt {tick}. b(). \overline{a}\langle {}\rangle\) and a is a simple channel, then the total complexity is still \(I_a\) but the constraints on \(I_a\) , \(I_b\) and \(I_c\) become
\begin{equation*} \varphi ;\Phi \vDash I_c \ge 1, \qquad \varphi ;\Phi \vDash I_b \ge I_c {+}1, \qquad \varphi ;\Phi \vDash I_a \ge I_b. \end{equation*}

5.3.2 Fibonacci.

Let us consider again the process P described in Figure 3. We set \(G(n) = \max (1,n)\) , corresponding to the function defined in Section 2, and we want to show that the server fib has a span \(G(n)\) . To do this, we give the typing described in Figure 13, which we detail here. This typing is similar to the one of Figure 8(b), so we detail especially the differences.
Fig. 13.
Fig. 13. A typing for Fibonacci (span).
The first rule of this typing is already quite different. Indeed, in the span type system, the (Iserv) rules has a condition of time invariance on the context of the continuation. Because of this, we have to transform (with subtyping) the initial context \(\Theta\) defining the servers add and fib into the time invariant context \(\Theta ^{\prime }\) , where those two servers only have output capabilities. Then, as before, we use the fact that \(i;\cdot \vDash G(i) \ge 1\) for all i to rewrite it \(G(i) {-}1 {+}1\) to do the (Tick) rule. Then, the (Tick) rule makes the time advance in the context \(\Gamma\) . We obtain
\begin{equation*} \langle \Gamma \rangle _{{-}1}^{} = \Theta ^{\prime }, n \mathbin {:}\mathsf {Nat}[i], a \mathbin {:}\mathsf {out}_{G(i) {-}1}(\mathsf {Nat}[Fib(i)]), \end{equation*}
again relying on the fact that \(i;\cdot \vDash G(i) \ge 1\) . Afterwards, we have the two pattern matchings, and we do not detail the zero cases, as they are simple. Intuitively, with the constraints ( \(i \le 0\) ) or \((i \ge 1, i {-}1 \le 0)\) , we have \(G(i) {-}1 = 0\) , so the type of a says that the channel has to send immediately, which it does. We can then focus on the main branch, where we have the constraints \(\Phi\) equivalent to \(i \ge 2\) .
Then, after some (Nu) rules and the (Par) rule, we have to type the three premises, and all with the same complexity \(G(i) {-}1\) . For the first premise, we use \(i;\Phi \vDash G(i {-}1) \le G(i) {-}1\) to change the complexity with a (Sub) rule. Then, we use polymorphism to show that this recursive call \(\overline{fib}\langle {m,b}\rangle\) is done on a size \(i {-}1\) to obtain the complexity \(G(i {-}1)\) . We have a similar behaviour for the second recursive call, with size \(i {-}2\) . Finally, the third premise corresponds to a usual pattern described in Section 5.3.1: the complexity of this subprocess is the time of b, which is \(G(i {-}1)\) . And the condition \(i;\Phi ;G(i {-}1) \ge G(i {-}2)\) is satisfied.

5.3.3 An Example to Justify the Use of Time.

To justify the use of time in types for span, and to show how we could find the time of a channel, we present here three examples of recursive calls with different behaviour. Usually, type inference for a size system reduces to satisfying a set of constraints on indices. We believe that even with time indexes on channels, type inference is still reducible to satisfying such a set of constraints. So, for the sake of simplicity, we will describe this example with constraints. We define three processes \(P_1, P_2\) , and \(P_3\) by
\begin{equation*} P_l \equiv !a(n,r). \mathtt {tick}. \mathtt {match}~n~\lbrace \mathtt {0}\mapsto {\overline{r}\langle {}\rangle } ;;~ \mathtt {s}(m) \mapsto (\nu r^{\prime }) (\nu r^{\prime \prime }) (Q_l) \rbrace , \end{equation*}
for the following definition of \(Q_l\) :
\begin{align*} Q_1 &\equiv \overline{a}\langle {m,r^{\prime }}\rangle \mathbin {\,|\,}\overline{a}\langle {m,r^{\prime \prime }}\rangle \mathbin {\,|\,}r^{\prime }(). r^{\prime \prime }(). \overline{r}\langle {}\rangle , \\ Q_2 &\equiv \overline{a}\langle {m,r^{\prime }}\rangle \mathbin {\,|\,}r^{\prime }(). \overline{a}\langle {m,r^{\prime \prime }}\rangle \mathbin {\,|\,}r^{\prime \prime }(). \overline{r}\langle {}\rangle , \\ Q_3 &\equiv \overline{a}\langle {m,r^{\prime }}\rangle \mathbin {\,|\,}r^{\prime }(). (\overline{a}\langle {m,r^{\prime \prime }}\rangle \mathbin {\,|\,}\overline{r}\langle {}\rangle) \mathbin {\,|\,}r^{\prime \prime }(). {\odot }. \end{align*}
Intuitively, for \(P_1\) the two recursive calls are done after one unit of time in parallel, and the return signal on r is done when both processes have done their return signal on \(r^{\prime }\) and \(r^{\prime \prime }\) . So, this is total parallelism for the two recursive calls (the span is linear in n). For \(P_2\) , a first recursive call is done, and then the process waits for the return signal on \(r^{\prime }\) , and when it receives it, the second recursive call begins. So, this is totally sequential (the span is exponential in n). Finally, for \(P_3\) , we have an intermediate situation between totally parallel and totally sequential. The process starts with a recursive call. Then, it waits for the return signal on \(r^{\prime }\) . When this signal arrives, it immediately starts the second recursive call and immediately does the return signal on r. So, intuitively, the second recursive call starts when all the “left” calls have been done. Note that those three servers have the same work, which is exponential in n.
So, let us type the three examples with the type system for span. For the sake of simplicity, we omit the typing of expressions, we only consider the difficult branch for the match constructors, and we focus on complexity and time. We consider the following context that is used for the three processes:
\begin{equation*} \Gamma \equiv a \mathbin {:}\forall i. \texttt {oserv}_{0}^{f(i)}(\mathsf {Nat}[0,i],\mathsf {ch}_{g(i)}()), n \mathbin {:}\mathsf {Nat}[0,i], r \mathbin {:}\mathsf {ch}_{g(i)}(). \end{equation*}
We have two unknown function symbols: f, which represents the complexity of the server, and g, the time for the return channel. We also use this second context:
\begin{equation*} \Delta \equiv \langle \Gamma \rangle _{{-}1}^{}, m \mathbin {:}\mathsf {Nat}[0,i {-}1], r^{\prime } \mathbin {:}\mathsf {ch}_{g^{\prime }(i)}(), r^{\prime \prime } \mathbin {:}\mathsf {ch}_{g^{\prime \prime }(i)}(). \end{equation*}
This gives two more unknown functions, \(g^{\prime }\) and \(g^{\prime \prime }\) corresponding, respectively, to the time of \(r^{\prime }\) and \(r^{\prime \prime }\) when defined. The three processes start with the same typing:
Because of the \(\mathtt {tick}\) , we know that the complexity on the line above the root should have the shape \(K {+}1\) for some K, so here we obtain immediately that \(f(i) \ge 1\) . In the same way, r should still be defined in \(\langle \Gamma \rangle _{{-}1}^{}\) , hence we obtain \(g(i) \ge 1\) .
We now describe the various constraints obtained on the three processes, under the assumption that \(i \ge 1\) . For \(Q_1\) , we obtain a typing similar to Figure 13 for Fibonacci, and we derive the following constraints:
\begin{equation*} f(i) {-}1 \ge f(i {-}1), \qquad g^{\prime }(i) = g(i {-}1), \qquad g^{\prime \prime }(i) = g(i {-}1), \qquad g(i) {-}1 \ge g^{\prime \prime }(i) \ge g^{\prime }(i), \qquad f(i) {-}1 \ge g(i) {-}1. \end{equation*}
The first constraint is because the total complexity \(f(i) {-}1\) must be greater than the complexity of the two recursive calls \(f(i {-}1)\) . Then, \(r^{\prime }\) and \(r^{\prime \prime }\) must have a time equal to \(g(i {-}1)\) to correspond to the type of a in the outputs \(\overline{a}\langle {m,r^{\prime }}\rangle\) and \(\overline{a}\langle {m,r^{\prime \prime }}\rangle\) . Finally, the last two constraints correspond to the constraints of Section 5.3.1 and the fact that the complexity bound \(f(i) {-}1\) should be greater than the complexity of this subprocess, which is \(g(i) {-}1,\) again, as in Section 5.3.1. So, we can satisfy the conditions with the following choice:
\begin{equation*} f(i) \equiv i {+}1, \qquad g(i) \equiv i {+}1, \qquad g^{\prime }(i) \equiv g^{\prime \prime }(i) \equiv i. \end{equation*}
So, as expected, the span, represented by the function f, is indeed linear.
Then, for \(Q_2\) , we describe the typing in Figure 14, where \(\varphi ;\Phi \equiv i;(i \ge 1)\) .
Fig. 14.
Fig. 14. A typing for \(Q_2\) .
Thus, we obtain the following constraints:
\begin{equation*} f(i) {-}1 \ge f(i {-}1), \qquad g^{\prime }(i) = g(i {-}1), \qquad f(i) {-}1 {-}g^{\prime }(i) \ge f(i {-}1), \end{equation*}
\begin{equation*} g^{\prime \prime }(i) {-}g^{\prime }(i) = g(i {-}1), \qquad g(i) {-}1 \ge g^{\prime \prime }(i), \qquad f(i) {-}1 \ge g(i) {-}1. \end{equation*}
The constraints on \(f(i)\) are obtained because of the subtyping rules, expressed by the double lines in the type derivation. The equality constraints are obtained, because we need both \(r^{\prime }\) and \(r^{\prime \prime }\) to have the type \(\mathsf {ch}_{g(i {-}1)}()\) , and finally the constraint \(g(i) {-}1 \ge g^{\prime \prime }(i)\) is as in Section 5.3.1. Thus, we can take
\begin{equation*} f(i) \equiv 2^{i {+}1} {-}1, \qquad g(i) \equiv 2^{i {+}1} {-}1. \end{equation*}
So, we indeed obtain the exponential complexity.
However, with those two examples, the time of the channel r is always equal to the complexity of the server a, and we cannot really see the usefulness of time. Still, with the next example, we obtain something more interesting. A type derivation for \(Q_3\) is given in Figure 15.
Fig. 15.
Fig. 15. A typing for \(Q_3\) .
We obtain the following constraints:
\begin{equation*} f(i) {-}1 \ge f(i {-}1), \qquad g^{\prime }(i) = g(i {-}1), \qquad f(i) {-}1 {-}g^{\prime }(i) \ge f(i {-}1), \end{equation*}
\begin{equation*} g^{\prime \prime }(i) {-}g^{\prime }(i) = g(i {-}1), \qquad g(i) {-}1 \ge g^{\prime }(i), \qquad f(i) {-}1 {-}g^{\prime }(i) \ge g(i) {-}1 {-}g^{\prime }(i), \qquad f(i) {-}1 \ge g^{\prime \prime }(i). \end{equation*}
The first four constraints are exactly the same as before, because there are the same typing derivations (represented by \(\cdots\) ). Then, the constraint on \(g(i) {-}1\) is because of \(\langle \cdot \rangle _{{-}g^{\prime }(i)}^{}\) , and the other constraints come from subtyping rules. So, using the equalities, and by removing redundant inequalities, we obtain for f and g,
\begin{equation*} f(i) \ge 1 {+}g(i {-}1) {+}f(i {-}1), \qquad g(i) \ge 1 {+}g(i {-}1), \qquad f(i) \ge 1 {+}2 \cdot g(i {-}1). \end{equation*}
Thus, we can take
\begin{equation*} g(i) \equiv i {+}1, \qquad f(i) \equiv \frac{(i {+}1)(i {+}2)}{2}. \end{equation*}
The complexity is quadratic in n. Note that for this example, the complexity f depends directly on g, and g is given by a recursive equation independent of f. In a sense, to find the complexity, we need to find first the delay of the second recursive call. Without time indications on channel, it would not be possible to track and obtain this recurrence relation on g, and thus we could not deduce the complexity.
Note that the two first examples used channels as a return signal for a parallel computation, whereas for the last example, channels are used as a synchronization point in the middle of a computation. We believe that this flexibility of channels justifies the use of \(\pi\) -calculus to reason about parallel computation. Moreover, this work is a step to a more expressive type system inspired by Reference [30], taking in account concurrent behaviour. Indeed, as we will show, the current type system fails to capture some simple concurrency.

5.3.4 Limitations of the Type System.

Our current type system enforces some kind of time uniqueness in channels. Indeed, take the process \(a().\mathtt {tick}.\overline{a} \langle \rangle\) . When trying to type this process, we obtain
As by definition \(\langle a \mathbin {:}\mathsf {ch}_{0}() \rangle _{{-}1}^{}\) is \(\emptyset\) , we cannot type the output on a. So, channels have strong constraints on the time they can be used. This is true especially when channels are not used linearly. Still, note that we can type a process of the shape \(a().{\odot }\mathbin {\,|\,}\overline{a} \langle \rangle \mathbin {\,|\,}\mathtt {tick}. \overline{a} \langle \rangle\) , thus it is better than plain linearity on channels. This restriction limits examples of concurrent behaviours. For example, take two processes \(P_1\) and \(P_2\) that should be executed but not simultaneously. To do that in a concurrent setting, we can use semaphores. In \(\pi\) -calculus, we could consider the process \((\nu a)(a().P_1^{\prime } \mathbin {\,|\,}a().P_2^{\prime } \mathbin {\,|\,}\overline{a} \langle \rangle)\) , where \(P_1^{\prime }\) is \(P_1\) with an output \(\overline{a} \langle \rangle\) at the end, likewise for \(P_2^{\prime }\) . This is a way to simulate a semaphore in \(\pi\) -calculus. Now, we can see that this example has the same problem as the example given above if, for instance, \(P_1\) contains a \(\mathtt {tick}\) , thus we cannot type this kind of process. Formally, this is because of our parallel composition rule:
If we take Q equal to P, then we then obtain, from a typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) a typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \mathbin {\,|\,}P \triangleleft K\) . So, the type system considers that P and \(P \mathbin {\,|\,}P\) are equivalent, and this is obviously not true in general, especially with the example described above. However, in a linear setting, this is not a problem.
Still, we believe that for parallel computation, our type system should be quite expressive in practice. Indeed, as stated above, the restriction appears especially when channels are not used linearly. However, it is known that linear \(\pi\) -calculus in itself is expressive for parallel computation [34]. For example, classical encodings of functional programs in a parallel setting rely on the use of linear return signals, as we will see in the example for bitonic sort in Section 6. Moreover, session types can also be encoded in linear \(\pi\) -calculus in the presence of variant types [11, 31]. Note that to encode a calculus as the one in Reference [12], we would also need recursive types. Our calculus and its proof of soundness could be extended to variant types, but not straightforwardly to recursive types. However, we believe the results on the linear \(\pi\) -calculus we cited suggest that the restriction given above should not be too harmful for parallel computation.

5.4 Complexity Results

In this section, we show how to prove that our type system indeed gives a bound on the number of time reduction steps of a process. As we work with the reduction relation \(\Rightarrow\) of Figure 11, we need to consider annotated processes instead of simple processes. So, we need to enrich our type system with a rule for the constructor \(n : P\) :
As the intuition suggested, this rule is equivalent to n times the typing rule for \(\mathtt {tick}\) . We can now work on the properties of our type system on annotated processes.
The procedure to prove the subject reduction for \(\Rightarrow\) in this type system is intrinsically more difficult than the one for Theorem 4.6. So, from the proof of subject reduction for span, one could deduce the proof of subject reduction for work, just by forgetting the considerations with time and the constructor \(n : P\) in the following proof.

5.4.1 Intermediate Lemmas.

We first show some intermediate lemmas on the typing system. To begin with, we give a lemma on the link between subtyping and time advance.
Lemma 5.10.
If \(\varphi ;\Phi \vdash T \sqsubseteq U,\) then for any I, either \(\langle U \rangle _{{-}I}^{}\) is undefined, or both \(\langle U \rangle _{{-}I}^{}\) and \(\langle T \rangle _{{-}I}^{}\) are defined, and \(\varphi ;\Phi \vdash \langle T \rangle _{{-}I}^{} \sqsubseteq \langle U \rangle _{{-}I}^{}\) .
Proof.
The proof is by induction on the subtyping derivation. First, transitivity is direct by induction hypothesis. For non-channel type, this is direct, because time advancing does not do anything. Then, for channels that are not servers, time is invariant by subtyping, thus time advancing is either undefined for both types, either defined for both types, with the same time. For a server type, again time is invariant by subtyping, so either both types lose their input capability, either they both keep the same capabilities. The case where \(\langle U \rangle _{{-}I}^{}\) is undefined and not \(\langle T \rangle _{{-}I}^{}\) is when T is an input/output server that loses its input capability, and U is an input server.□
Now, for the usual properties of typing systems, we have first weakening and strengthening.
Lemma 5.11 (Weakening).
Let \(\varphi ,\varphi ^{\prime }\) be disjoint sets of index variables, \(\Phi\) be a set of constraints on \(\varphi\) , \(\Phi ^{\prime }\) be a set of constraints on \((\varphi ,\varphi ^{\prime })\) , \(\Gamma\) and \(\Gamma ^{\prime }\) be contexts on disjoint set of variables.
(1)
If \(\varphi ;\Phi \vDash C,\) then \((\varphi ,\varphi ^{\prime });(\Phi ,\Phi ^{\prime }) \vDash C\) .
(2)
If \(\varphi ;\Phi \vdash T \sqsubseteq U,\) then \((\varphi ,\varphi ^{\prime });(\Phi ,\Phi ^{\prime }) \vdash T \sqsubseteq U\) .
(3)
If \(\varphi ;\Phi ;\Gamma \vdash e \mathbin {:}T,\) then \((\varphi ,\varphi ^{\prime });(\Phi ,\Phi ^{\prime });\Gamma ,\Gamma ^{\prime } \vdash e \mathbin {:}T\) .
(4)
\(\langle \Gamma \rangle _{{-}I}^{(\varphi ,\varphi ^{\prime });(\Phi ,\Phi ^{\prime })} = \Delta ,\Delta ^{\prime }\) for some \(\Delta , \Delta ^{\prime }\) with \((\varphi ;\varphi ^{\prime });(\Phi ;\Phi ^{\prime }) \vdash \Delta \sqsubseteq \langle \Gamma \rangle _{{-}I}^{\varphi ;\Phi }\) .
(5)
If \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K,\) then \((\varphi ,\varphi ^{\prime });(\Phi ,\Phi ^{\prime });\Gamma ,\Gamma ^{\prime } {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) .
Proof.
Point 1 is a direct consequence of the definition of \(\varphi ;\Phi \vDash C\) . Point 2 is proved by induction on the subtyping derivation, and it uses explicitly Point 1. Point 4 is a consequence of Point 1: Everything that is defined in \(\langle \Gamma \rangle _{{-}I}^{\phi ;\Phi }\) is also defined in \(\langle \Gamma \rangle _{{-}I}^{(\phi ,\phi ^{\prime });(\Phi ,\Phi ^{\prime })}\) , and the subtyping condition is here, since with more constraints, a server may not be changed into an output server by the advance of time. Points 3 and 5 are proved by induction on the typing derivation, and each point uses crucially the previous ones. Note that the weakening integrated in the rule for input servers is necessary to obtain Point 5. Note also that when the advance time operator is used, the weakened typing is obtained with the use of a subtyping rule.□
Formally, all lemmas should be presented in the same way, in the sense that a property such as weakening should hold first on constraints, then we can deduce it for subtyping, and finally we can deduce it for typing. However, for the sake of simplicity, we chose for the following lemmas to only present the interesting points.
Lemma 5.12 (Strengthening).
Let \(\varphi\) be a set of index variables, \(\Phi\) be a set of constraints on \(\varphi\) , and C a constraint on \(\varphi\) such that \(\varphi ;\Phi \vDash C\) .
(1)
\(\langle \Gamma \rangle _{{-}I}^{\varphi ;(\Phi ,C)} = \langle \Gamma \rangle _{{-}I}^{\varphi ;\Phi }\) .
(2)
If \(\varphi ;(\Phi ,C);\Gamma ,\Gamma ^{\prime } {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) and the variables in \(\Gamma ^{\prime }\) are not free in P, then \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) .
We also have a property specific to size type systems, expressing that an index variable can be substituted by any index.
Lemma 5.13 (Index Substitution).
Let \(\varphi\) be a set of index variables and \(i \notin \varphi\) . Let J be an index with free variables in \(\varphi\) . Then,
(1)
\([\![ I \lbrace J / i \rbrace ]\!] _{\rho } = [\![ I ]\!] _{\rho \lbrack i \mapsto [\![ J ]\!] _{\rho } \rbrack }\) .
(2)
If \((\varphi ,i);\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K,\) then \(\varphi ;\Phi \lbrace J / i \rbrace ;\Gamma \lbrace J / i \rbrace {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K \lbrace J / i \rbrace\) .
We also need a lemma specific to the notion of time.
Definition 5.14 (Delaying).
Given a type T and an index I, we define the delaying of T by I units of time, denoted \(\langle T \rangle _{{+}I}\) :
\begin{equation*} \langle \mathcal {B} \rangle _{{+}I} = \mathcal {B}, \qquad \langle \mathsf {ch}_{J}(\widetilde{T}) \rangle _{{+}I} = \mathsf {ch}_{J {+}I}(\widetilde{T}), \end{equation*}
and for other channel and server types, the definition is in correspondence with the one on the right above. This definition can be extended to contexts.
Lemma 5.15 (Delaying).
For any index I, we have:
(1)
\(\langle \langle \Gamma \rangle _{{+}I} \rangle _{{-}J}^{} = \Delta , \Delta ^{\prime }\) with \(\varphi ;\Phi \vdash \Delta \sqsubseteq \langle \langle \Gamma \rangle _{{-}J}^{} \rangle _{{+}I}\) .
(2)
\(\langle \langle \Gamma \rangle _{{+}I} \rangle _{{-}(J {+}I)}^{} = \langle \Gamma \rangle _{{-}J}^{}\) .
(3)
If \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K,\) then \(\varphi ;\Phi ;\langle \Gamma \rangle _{{+}I} {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K {+}I\) .
With this lemma, we can see that if we add a delay of I time units in the contexts for all channels, it increases the complexity by I time units, thus we see the link between time in types and the complexity. Then, we can show the usual substitution lemma.
Lemma 5.16 (Substitution).
We have:
(1)
If \(\varphi ;\Phi ;\Gamma , {v}\mathbin {:}T \vdash e^{\prime } \mathbin {:}U\) and \(\varphi ;\Phi ;\Gamma \vdash e \mathbin {:}T,\) then \(\varphi ;\Phi ;\Gamma \vdash e^{\prime } [{v} := e] \mathbin {:}U\) .
(2)
If \(\varphi ;\Phi ;\Gamma , {v}\mathbin {:}T {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) and \(\varphi ;\Phi ;\Gamma \vdash e \mathbin {:}T,\) then \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P [{v} := e] \triangleleft K\) .
The proof is standard.

5.4.2 Subject Reduction.

We now present the core theorem to have the complexity soundness: subject reduction. First, we need to show that typing is invariant by congruence.
Lemma 5.17 (Congruence and Typing).
Let P and Q be annotated processes such that \(P \equiv Q\) . Then, \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) if and only if \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) .
Proof.
We prove this by induction on \(P \equiv Q\) . Note that for a process P, the typing system is not syntax-directed because of the subtyping rule. However, by reflexivity and transitivity of subtyping, we can always assume that a proof has exactly one subtyping rule before any syntax-directed rule. Moreover, it is sufficient to prove this theorem for type derivations that do not start with a subtyping rule. Indeed, the first subtyping rule in a derivation for P can always be mimicked as it is in the derivation for Q. We show the essential base cases and the inductive steps follow directly from induction hypothesis.
Case \((\nu a) P \mathbin {\,|\,}Q \equiv (\nu a)(P \mathbin {\,|\,}Q)\) with a not free in Q.
Suppose \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}(\nu a)(P \mathbin {\,|\,}Q) \triangleleft K\) . Then the proof has the shape:
Since a is not free in Q, by Lemma 5.12, from \(\pi _Q\) , we obtain a proof \(\pi _Q^{\prime }\) of \(\varphi ;\Phi ;\Delta {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K^{\prime }\) . We can then derive the following typing:
For the converse, the proof is direct by induction hypothesis and weakening.
Case \(m : (P \mathbin {\,|\,}Q) \equiv m : P \mathbin {\,|\,}m : Q\) . Suppose \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}m : (P \mathbin {\,|\,}Q) \triangleleft K {+}m\) . Then we have
So, we can give the following derivation:
Now, suppose we have a typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}m : P \mathbin {\,|\,}m : Q \triangleleft K\) . The typing has the shape
By Lemma 5.10, from \(\Gamma \sqsubseteq \Delta _1\) , we obtain \(\Gamma = \Theta _0, \Theta _1\) with \(\langle \Theta _1 \rangle _{{-}m}^{} \sqsubseteq \langle \Delta _1 \rangle _{{-}m}^{}\) . In the same way, \(\Gamma = \Theta _0^{\prime }, \Theta _1^{\prime }\) with \(\langle \Theta _1^{\prime } \rangle _{{-}m}^{} \sqsubseteq \langle \Delta _2 \rangle _{{-}m}^{}\) . Moreover, we have easily \(\varphi ;\Phi \vDash K \ge m\) . Thus, by the Lemma 5.11 (weakening) for \(\pi _P\) and \(\pi _Q\) , we obtain
This concludes this case.
Case \(m : (\nu a) P \equiv (\nu a) (m : P)\) .
Suppose that \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}m : (\nu a) P \triangleleft K {+}m\) . Then, the proof has the shape
Recall that, by Lemma 5.15, \(\langle \langle T \rangle _{{+}m}{} \rangle _{{-}m}^{} = \langle T \rangle _{{-}0}^{} = T\) . So, we have
For the converse, suppose that \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}(\nu a) m : P \triangleleft K\) . Then the typing has the shape
By an abuse of notation, let us write \(\langle T^{\prime } \rangle _{{-}m}^{}\) to denote \(\langle T^{\prime } \rangle _{{-}m}^{}\) if it is defined, and any other type otherwise. Then, we have the derivation (with possibly a weakened version of \(\pi _P\) )
This concludes all the base cases. We can then prove the lemma by considering the remaining cases for \(P \equiv Q\) . Symmetry, transitivity and contextual congruence are direct by induction hypothesis.□
Now that we have Lemma 5.17, we can work up to the congruence relation. So, we proceed to show subject reduction.
Theorem 5.18 (Subject Reduction).
If \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) and \(P \Rightarrow Q,\) then \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) .
Let us show this Theorem. We do this by induction on \(P \Rightarrow Q\) . Let us first remark that when considering the typing of P, again the first subtyping rule has no importance, since we can always start the typing of Q with the exact same subtyping rule. We now proceed by doing the case analysis on the rules of Figure 11. Again, we only present the interesting cases.
Case \((n : !a(\widetilde{{v}}).P) \mathbin {\,|\,}(m : \overline{a}\langle {\widetilde{e}}\rangle) \Rightarrow (n : !a(\widetilde{{v}}).P) \mathbin {\,|\,}(\max (n,m) : P [\widetilde{{v}} := \widetilde{e}])\) . Consider the typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}(n : !a(\widetilde{{v}}).P) \mathbin {\,|\,}(m :\overline{a}\langle {\widetilde{e}}\rangle) \triangleleft K\) . The first rule is the rule for parallel composition, then the proof is split into the two following subtrees:
The first subtree can be used exactly as it is to type the server in the right part of the reduction relation. Furthermore, as the name a is used as an input and as an output, the original type in \(\Gamma\) for this name must be a server type \(\forall \widetilde{i}. \texttt {serv}_{I}^{K_a}(\widetilde{T})\) . As this server does not lose its input capacity after the time decrease, we also know that \(\varphi ;\Phi \vDash I \ge n\) . So, by subtyping, we have
\begin{equation*} \varphi ;\Phi \vDash I_0 = I {-}n, \qquad (\varphi ,\widetilde{i});\Phi \vdash \widetilde{T} \sqsubseteq \widetilde{T_0}, \qquad (\varphi ,\widetilde{i});\Phi \vDash K_0^{\prime } \le K_a, \end{equation*}
\begin{equation*} \varphi ;\Phi \vDash I_1 = I {-}m, \qquad (\varphi ,\widetilde{i});\Phi \vdash \widetilde{T_1} \sqsubseteq \widetilde{T}, \qquad (\varphi ,\widetilde{i});\Phi \vDash K_a \le K_1^{\prime }. \end{equation*}
There are now two cases to consider: Either \(\varphi ;\Phi \vDash I \ge m\) or \(\varphi ;\Phi \nvDash I \ge m\) . The most difficult case between the two is \(\varphi ;\Phi \nvDash I \ge m\) , hence we only detail this case.
Suppose that \(\varphi ;\Phi \nvDash I \ge m\) . Note that as we know \(\varphi ;\Phi \vDash I \ge n\) , it means that \(m \gt n\) . Moreover, as \(\varphi ;\Phi \vDash I_1 = I -m\) , then \(\varphi ;\Phi \vDash I_1 {+}m = \max (I,m)\) . We still have
\begin{equation*} (\varphi ,\widetilde{i});\Phi \vdash \widetilde{T_1} \sqsubseteq \widetilde{T_0}, \qquad (\varphi ,\widetilde{i});\Phi \vDash K_0^{\prime } \le K_1^{\prime }. \end{equation*}
Thus, by subtyping, from \(\pi _P\) , we can obtain a proof of \((\varphi ,\widetilde{i});\Phi ;\Theta _0, \widetilde{{v}} \mathbin {:}\widetilde{T_1} {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K_1^{\prime }\) . By Lemma 5.13, we have a proof of \(\varphi ;\Phi \lbrace \widetilde{J} / \widetilde{i} \rbrace ;\Theta _0 \lbrace \widetilde{J} / \widetilde{i} \rbrace , \widetilde{{v}} \mathbin {:}\widetilde{T_1} \lbrace \widetilde{J} / \widetilde{i} \rbrace {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K_1^{\prime } \lbrace \widetilde{J} / \widetilde{i} \rbrace\) . As \(\widetilde{i}\) only appears in \(\widetilde{T_1}\) and \(K_1^{\prime }\) , we obtain a proof of \(\varphi ;\Phi ;\Theta _0, \widetilde{{v}} \mathbin {:}\widetilde{T_1} \lbrace \widetilde{J} / \widetilde{i} \rbrace {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K_1^{\prime } \lbrace \widetilde{J} / \widetilde{i} \rbrace\) .
Now, by using several times Lemma 5.10, we have
\begin{equation*} \varphi ;\Phi \vdash \langle \Gamma \rangle _{{-}(n {+}I_0)}^{} \sqsubseteq \epsilon _0, \langle \Delta _0 \rangle _{{-}I_0}^{} \sqsubseteq \epsilon _0, \Theta _0, \qquad \varphi ;\Phi \vdash \langle \Gamma \rangle _{{-}(m {+}I_1)}^{} \sqsubseteq \epsilon _1, \langle \Delta _1 \rangle _{{-}I_1}^{}, \end{equation*}
for some \(\epsilon _0,\epsilon _1\) . Moreover, we know that \(\Theta _0\) is time invariant. let us call \(J = max(I_0 {+}n, I_1 {+}m)\) , we have by again decreasing in the first subtyping relation:
\begin{equation*} \varphi ;\Phi \vdash \langle \Gamma \rangle _{{-}J}^{} \sqsubseteq \epsilon _2, \Theta _0, \end{equation*}
for some \(\epsilon _2\) . Note that we have \(\varphi ;\Phi \vDash J = max(I, m) = I_1 {+}m,\) since \(\varphi ;\Phi \vDash I_0 {+}n = I\) and \(\varphi ;\Phi \vDash I_1 {+}m = max(I,m)\) .
By Lemma 5.11, we can obtain two proofs, with the subtyping rule:
\begin{equation*} \varphi ;\Phi ;\langle \Gamma \rangle _{{-}J}^{}, \widetilde{{v}} \mathbin {:}\widetilde{T_1} \lbrace \widetilde{J} / \widetilde{i} \rbrace {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K_1 \lbrace \widetilde{J} / \widetilde{i} \rbrace , \qquad \varphi ;\Phi ;\langle \Gamma \rangle _{{-}J}^{} \vdash \widetilde{e} \mathbin {:}\widetilde{T_1} \lbrace \widetilde{J} / \widetilde{i} \rbrace . \end{equation*}
Thus, by the substitution lemma (Lemma 5.16), we have \(\varphi ;\Phi ;\langle \Gamma \rangle _{{-}J}^{} {|\!-_{\!\!\!\!{\text s}}}P [\widetilde{{v}} := \widetilde{e}] \triangleleft K_1 \lbrace \widetilde{J} / \widetilde{i} \rbrace\) . Recall that in this case, \(\max (n,m) = m\) . We can obtain the following typing using the associated typing rule:
\begin{equation*} \varphi ;\Phi ;\langle \Gamma \rangle _{{-}(J {-}m)}^{} {|\!-_{\!\!\!\!{\text s}}}m : P [\widetilde{{v}} := \widetilde{e}] \triangleleft m {+}K_1 \lbrace \widetilde{J} / \widetilde{i} \rbrace . \end{equation*}
Then, by delaying (Lemma 5.15), we have \(\varphi ;\Phi ;\langle \langle \Gamma \rangle _{{-}(J {-}m)}^{} \rangle _{{+}(J {-}m)} {|\!-_{\!\!\!\!{\text s}}}m : P [\widetilde{{v}} := \widetilde{e}] \triangleleft J {+}K_1 \lbrace \widetilde{J} / \widetilde{i} \rbrace\) , and \(\Gamma = \epsilon _0^{\prime }, \epsilon _1^{\prime }\) with \(\varphi ;\Phi \vdash \epsilon _1^{\prime } \sqsubseteq \langle \langle \Gamma \rangle _{{-}(J {-}m)}^{} \rangle _{{+}(J {-}m)}\) . Recall that \(\varphi ;\Phi \vDash J = I_1 {+}m\) and \(\varphi ;\Phi \vDash I_1 {+}m {+}K_1 \lbrace \widetilde{J} / \widetilde{i} \rbrace \le K\) . Thus, again by subtyping and weakening, we obtain
\begin{equation*} \varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}\max (n,m) : P [\widetilde{{v}} := \widetilde{e}] \triangleleft K. \end{equation*}
This concludes this case. Note that many notations in this case are somewhat complicated, because we only know that \(\varphi ;\Phi \vDash I \ge m\) is false, but it does not immediately mean that \(\varphi ;\Phi \vDash m \gt I\) , because the relation on indexes is not complete. So, we have to take that into account when writing substraction.
The case of simple channel synchronization works in the same way.
Case \(\mathtt {match}~e::e^{\prime }~\lbrace \lbrack \rbrack \mapsto P ;;~ x::y \mapsto Q \rbrace \Rightarrow Q [x,y := e,e^{\prime }]\) . This case is more difficult than its counterpart for integers, thus we only detail this case and the one for integers can easily be deduced from this one. Moreover, this case is also more difficult than the case for \(\ni\) . Assume given a derivation \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}\mathtt {match}~e::e^{\prime }~\lbrace \lbrack \rbrack \mapsto P ;;~ x::y \mapsto Q \rbrace \triangleleft K\) . Then the proof has the shape
Where we ignore the branch for P and \(\pi _Q\) proves \(\varphi ; (\Phi ,J \ge 1) ; \Gamma , x \mathbin {:}\mathcal {B}, y \mathbin {:}\mathsf {List}[I {-}1, J {-}1](\mathcal {B}) {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) . Subtyping gives us the following information:
\begin{equation*} \varphi ;\Phi \vDash I \le I^{\prime } {+}1, \qquad \varphi ;\Phi \vDash J^{\prime } {+}1 \le J, \qquad \varphi ;\Phi \vdash \mathcal {B}^{\prime } \sqsubseteq \mathcal {B}. \end{equation*}
From this, we can deduce the following constraints:
\begin{equation*} \varphi ;\Phi \vDash J \ge 1, \qquad \varphi ;\Phi \vDash I {-}1 \le I^{\prime }, \qquad \varphi ;\Phi \vDash J^{\prime } \le J-1. \end{equation*}
Thus, with the subtyping rule and the proofs \(\pi _e\) and \(\pi _{e^{\prime }}\) , we obtain
\begin{equation*} \varphi ;\Phi ;\Gamma \vdash e \mathbin {:}\mathcal {B}, \qquad \varphi ;\Phi ;\Gamma \vdash e^{\prime } \mathbin {:}\mathsf {List}[I {-}1, J {-}1](\mathcal {B}). \end{equation*}
Then, by Lemma 5.12, from \(\pi _Q\) , we obtain a proof of \(\varphi ;\Phi ;\Gamma , x \mathbin {:}\mathcal {B}, y \mathbin {:}\mathsf {List}[I {-}1, J {-}1](\mathcal {B}) {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) . By the substitution lemma (Lemma 5.16), we obtain \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}Q [x,y := e,e^{\prime }] \triangleleft K\) . This concludes this case.
Case \(P \Rightarrow Q\) with \(P \equiv P^{\prime }\) , \(P^{\prime } \Rightarrow Q^{\prime },\) and \(Q \equiv Q^{\prime }\) . Suppose that \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) . By Lemma 5.17, we have \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}P^{\prime } \triangleleft K\) . By induction hypothesis, we obtain \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}Q^{\prime } \triangleleft K\) . Then, again by Lemma 5.17, we have \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) . This concludes this case.
This concludes the proof of Theorem 5.18.
Now that we have the subject reduction for \(\Rightarrow\) , we can easily deduce a more generic form of Theorem 5.8.
Theorem 5.19.
Let P be an annotated process such that \(\varphi ;\Phi ; \Gamma {|\!-_{\!\!\!\!{\text s}}}P \triangleleft K\) . Then, \(\varphi ;\Phi \vDash K \ge \mathsf {span}(P)\) .
Proof.
By Theorem 5.18, all reductions from P using \(\Rightarrow\) preserve the typing. Moreover, for any process Q, if we have a typing \(\varphi ;\Phi ;\Gamma {|\!-_{\!\!\!\!{\text s}}}Q \triangleleft K\) , then \(\varphi ;\Phi \vDash K \ge \mathcal {C}_{\ell }(Q)\) . Indeed, a constructor \(n : P\) incurs an increment of the complexity of n both in typing and in the definition of \(\mathcal {C}_{\ell }(Q)\) , and for parallel composition the typing imposes a complexity greater than the maximum as in the definition for \(\mathcal {C}_{\ell }(Q)\) . Thus, for any process Q reachable from P, we have \(\varphi ;\Phi \vDash K \ge \mathcal {C}_{\ell }(Q)\) , and K is indeed a bound on the span.□
Corollary 5.9, which has been stated before, is then obtained with the substitution lemma and the rule for parallel composition.

6 An Example: Bitonic Sort

As an example for this type system, we show how to obtain the bound on a common parallel algorithm: bitonic sort [1]. The particularity of this sorting algorithm is that it admits a parallel complexity in \(\mathcal {O}(log(n)^2)\) . We will show here that our type system allows one to derive this bound for the algorithm, just as the paper-and-pen analysis. Actually, we consider here a version for lists, which is not optimal for the number of operations, but we obtain the usual number of comparisons. For the sake of simplicity, we consider the case of lists of size a power of 2. Let us briefly sketch the ideas of this algorithm. For a formal description, see Reference [1].
A bitonic sequence is either a sequence composed of an increasing sequence followed by a decreasing sequence (e.g., References [2, 5, 7, 8, 19, 23]), or a cyclic rotation of such a sequence (e.g., References [2, 5, 7, 8, 19, 23]).
The algorithm uses two main functions, bmerge and bsort.
bmerge takes a bitonic sequence and recursively sorts it as follows:
Assume \(s=[a_0,\dots , a_{n {-}1}]\) is a bitonic sequence such that \([a_0,\dots , a_{n/2 {-}1}]\) is increasing and \([a_{n/2}\dots , a_{n {-}1}]\) is decreasing, then we consider
\(s_1=[ \min (a_0,a_{n/2}), \min (a_1,a_{n/2 {+}1})\dots , \min (a_{n/2 {-}1} , a_{n {-}1})]\) the list of minima and
\(s_2=[ \max (a_0,a_{n/2}), \max (a_1,a_{n/2 {+}1})\dots , \max (a_{n/2 {-}1} , a_{n {-}1})]\) the list of maxima.
Then, we have \(s_1\) and \(s_2\) are bitonic and satisfy \(\forall x \in s_1, \forall y \in s_2, x\le y\) .
bmerge then applies recursively to \(s_1\) and \(s_2\) to produce a sorted sequence.
bsort takes a sequence and recursively sorts it. It starts by separating the sequence in two. Then, it recursively sorts the first sequence in increasing order, and the second sequence in decreasing order. With this, we obtain a bitonic sequence that can be sorted with bmerge.
We will encode this algorithm in \(\pi\) -calculus with a Boolean type. As said before, our results can easily be extended to support Boolean with a conditional constructor.
First, we suppose that a server for comparison lessthan is already implemented. We start with \(\texttt {bcompare}\) such that given two lists of same length, it creates the list of minimum and the list of maximum ( \(s_2\) and \(s_1\) described above). The process is given in Figure 16 and intuitively, it compares the two top elements of the lists, puts the minimum in the left list and the maximum in the right list, and then proceeds recursively.
Fig. 16.
Fig. 16. Bitonic sort.
Then, to present the processes for bitonic sort, let us use the macro \(\mathtt {let}~\widetilde{{v}} = f(\widetilde{e})~ \mathtt {in}~ P\) to represent \((\nu a)(\overline{f}\langle {\widetilde{e},a}\rangle \mathbin {\,|\,}a(\widetilde{{v}}).P)\) , with the meaning that if \(\overline{f}\) is a server representing a function f, then this process indeed corresponds to computing f on \(\widetilde{e}\) , and putting the output in the variables \(\widetilde{v}\) in the continuation P. We will only use it with f that has complexity 0, then the associated typing rule corresponds to adding \(\widetilde{{v}}\) in the context with types corresponding to the outputs of the function f. We also use a generalized pattern matching, allowing us to match on a list with one element, which could formally be done by two successive pattern matching. We also assume that we have a function for concatenation of lists and a function partition taking a list of size 2n, and giving two lists corresponding to the first n elements and the last n elements. Then, the process for bitonic sort is given in Figure 16. The server bmerge takes a list, splits it into two lists \(l_1\) and \(l_2\) , computes the list of minima \(p_1\) and the list of maxima \(p_2\) , applies recursively to those lists, and then concatenates them in increasing order if up is true, and in decreasing order otherwise. And finally, bsort takes a list, separates it into two lists, sorts the first one in increasing order and the second one in decreasing order, and then merges them using the previous function.
We present here intuitively the typing. To begin with, we suppose that lessthan is given the server type \(\texttt {oserv}_{0}^{0}(\mathcal {B},\mathcal {B},\mathsf {ch}_{0}(\mathsf {Bool}))\) , saying that this is a server ready to be called, and it takes in input a channel that is used to return the Boolean value. With this, we can give to bcompare the following server type:
\begin{equation*} \forall i. \texttt {serv}_{0}^{1}(\mathsf {List}[0,i](\mathcal {B}), \mathsf {List}[0,i](\mathcal {B}), \mathsf {out}_{1}(\mathsf {List}[0,i](\mathcal {B}), \mathsf {List}[0,i](\mathcal {B}))). \end{equation*}
The important things to notice are that this server has complexity 1, and the channel taken in input has a time 1. A sketch of this typing is given in Figure 17(a), where we use abbreviations for the name of server (lt for lessthan, bc for bcompare...). The cases of empty lists are not detailed, but they are easy. In the non-empty case, for the \(\nu\) constructor, we must give a type to the channels b and c. We use
\begin{equation*} b \mathbin {:}\mathsf {ch}_{1}(\mathsf {List}[0,i {-}1](\mathcal {B}), \mathsf {List}[0,i {-}1](\mathcal {B})), \qquad c \mathbin {:}\mathsf {ch}_{1}(\mathsf {Bool}). \end{equation*}
And we can then type the various processes in parallel.
Fig. 17.
Fig. 17. Bitonic sort.
For the call to bcompare, the arguments have the expected type, and this call has complexity 1, because of the type of bcompare.
For the process \(\mathtt {tick}.\overline{\texttt {lessthan}}\langle {x,y,c}\rangle\) , the tick enforces a decreasing of time 1 in the context. This modifies in particular the time of c, that becomes 0. Thus, we can do the call to lessthan as everything is well-typed.
Finally, for the last process, we have in the two branches a shape \(b(\cdots). c(\cdots). \overline{a}\langle {\cdots }\rangle\) . So, by Section 5.3.1, as all those three channels \(b,c\) and a have a time equal to 1, we have a complexity 1 for this typing.
So, we can indeed give this server type to bcompare, and thus we can call this server and it generates a complexity of 1.
Then, the main point in the typing of the two remaining servers is to find a solution to a recurrence relation for the complexity of server types. In the typing of \(\texttt {bmerge}\) , we suppose given a list of size smaller than \(2^i\) , and we choose both the complexity of this type and the time of the channel a equal to an index \(f(i)\) as in Section 5.3.3. So, it means we choose for bmerge the type:
\begin{equation*} \forall i. \texttt {serv}_{0}^{f(i)}(\mathsf {Bool}, \mathsf {List}[0,2^i](\mathcal {B}), \mathsf {out}_{f(i)}(\mathsf {List}[0,2^i](\mathcal {B}))). \end{equation*}
Then, the typing given in Figure 17(b) gives us the following conditions, for the three branches, when \(2^i \ge 2\) (or equivalently, \(i \ge 1\) ):
\begin{equation*} f(i) \ge 1, \qquad f(i) \ge 1 {+}f(i {-}1), \qquad f(i) \ge f(i {-}1) \ge f(i {-}1). \end{equation*}
The first inequality comes from the (Sub) rule for the first branch, the second inequality comes from the (Sub) rule for the second branch, and the third inequality comes from the condition that the time of a should be greater than the time of d, which should be greater than the time of c in the third branch, as explained in Section 5.3.1. So, we can take \(f(i) = i\) , and thus bmerge has logarithmic complexity.
In the same way, for bsort, we chose the type
\begin{equation*} \forall i. \texttt {serv}_{0}^{g(i)}(\mathsf {Bool}, \mathsf {List}[0,2^i](\mathcal {B}), \mathsf {out}_{g(i)}(\mathsf {List}[0,2^i](\mathcal {B}))). \end{equation*}
The typing is given in Figure 17(c), which gives us the following conditions, again for the three parallel branches, when \(2^i \ge 2\) (equivalently, \(i \ge 1\) ):
\begin{equation*} g(i) \ge g(i {-}1), \qquad g(i) \ge g(i {-}1) {+}f(i), \qquad g(i) \ge g(i {-}1) {+}f(i). \end{equation*}
The first inequality comes from the (Sub) rule for the first branch, the second inequality comes from the (Sub) rule for the second branch, where \(g(i {-}1) {+}f(i)\) is the complexity of \(b(q_1). \cdots\) (time of b and c summed with the call to bmerge), and the last inequality comes from the third branch, as the time of a should be greater than the time of d. So, if we take \(f(i) = i\) as previously, then we have
\begin{equation*} i \ge 1 \text{ implies } g(i) \ge g(i {-}1) {+}i. \end{equation*}
Thus, we can take \(g(i)\) in \(\mathcal {O}(i^2)\) , and we obtain in the end that bitonic sort is indeed in \(\mathcal {O}(log(n)^2)\) on a list of size n.
Note that in this example, the type system gives recurrence relations corresponding to the usual recurrence relations we would obtain with a complexity analysis by hand. Here, the recurrence relation is only on f or g, because channel names are only used as return channels, hence their time is always equal to the complexity of the server that uses them. In general, this is not the case; as we saw before in Section 5.3.3, we can obtain mutually recurrent relations when defining a server.

7 Span and Causal Complexity

In this section, we present how our notion of span can be linked with the causal complexity of the literature, as we believe it can be of interest to show that both annotated processes and causal complexity are well-behaved notions of parallel complexity in the \(\pi\) -calculus.

7.1 Presentation of Causal Complexity

We present here a notion of causal complexity inspired by other works [14, 15, 16]. We explained before with the canonical form in Definition 3.1 that a process can be described by a set of names and a multiset of guarded processes, when working up to congruence. For causal complexity, we consider more structure for processes. The idea is to see a process as a set of names and a binary tree where leaves are guarded processes and a node means parallel composition. Formally, instead of using the previous congruence relation, we use the tree congruence. This is defined as the least congruence relation \(\equiv _t\) closed under
\begin{equation*} (\nu a) (\nu b) P \equiv _t (\nu b) (\nu a)P, \end{equation*}
\begin{equation*} (\nu a)(P \mathbin {\,|\,}Q) \equiv _t (\nu a) P \mathbin {\,|\,}Q~(\text{when } a \text{ is not free in } Q), \qquad (\nu a)(P \mathbin {\,|\,}Q) \equiv _t P \mathbin {\,|\,}(\nu a) Q~(\text{when } a \text{ is not free in } P). \end{equation*}
This tree congruence can indeed move names as before, but it preserves the tree-shape of a process. With this intuition, we can redefine the semantics to preserve this tree structure. For this, we annotate the reduction relation by a location.
Definition 7.1 (Locations and Positions).
The sets of positions and locations are given by the following grammars:
\(p := \epsilon \mid 0 \cdot p \mid 1 \cdot p, \qquad \ell := p;\mathtt {tick}\mid p;\mathsf {pm}\mid \tau \langle p,p^{\prime } \rangle .\)
The intuition is that a reduction \(P \overset{p;\mathtt {tick}}{\longrightarrow } P^{\prime }\) removed the top \(\mathtt {tick}\) of the guarded process of P at position p in the tree. A reduction \(P \overset{\tau \langle p,p^{\prime } \rangle }{\longrightarrow } P^{\prime }\) is a communication between the input process at position p and the output process at position \(p^{\prime }\) . Finally, the action \(p;\mathsf {pm}\) is for the position of a pattern-matching reduction.
The rules are described in Figure 18. For example, from a process P seen as a tree with at position p a replicated input \(!a(\widetilde{{v}}).Q\) and at position \(p^{\prime }\) an output \(\overline{a}\langle {\widetilde{e}}\rangle\) , we obtain the process \(P^{\prime }\) , the same tree as P, with at position p the same replicated input but at position \(p^{\prime }\) , we have the tree corresponding to the process \(Q [\widetilde{{v}} := \widetilde{e}]\) . The location \(\tau \langle p,p^{\prime } \rangle\) indicates at which positions the modification happened, and what was the action performed. In the same way, we can define a reduction annotated by a \(\mathtt {tick}\) , or a match. An alternative presentation of this semantics, closer to the one in Reference [16], with a labelled transition system, is also possible. As for the standard reduction in \(\pi\) -calculus, both semantics (the one with the congruence and the one with the labelled transition system) are equivalent. We chose to present this one, because it is easier to use in proofs.
Fig. 18.
Fig. 18. Semantics for causal complexity.
The goal of this semantics is first to preserve the tree structure in a reduction step, and second to remember when doing a reduction step where the modification occurs exactly in the tree. Then, we can define a causality relation between locations. The idea is that a location \(\ell\) causes a location \(\ell ^{\prime }\) (denoted \(\ell \prec _c\ell ^{\prime }\) ) when the reduction step at location \(\ell ^{\prime }\) could not have happened without the reduction step at location \(\ell\) .
Definition 7.2.
The causality relation \(\ell \prec _c\ell ^{\prime }\) between locations is defined by:
\(p;\mathtt {tick}\prec _cp^{\prime };\mathtt {tick}\) when p is a prefix of \(p^{\prime }\) ,
\(p;\mathtt {tick}\prec _c\tau \langle p_0,p_1 \rangle\) when p is a prefix of \(p_0\) or \(p_1\) ,
\(\tau \langle p_0,p_1 \rangle \prec _cp;\mathtt {tick}\) when \(p_1\) is a prefix of p,
\(\tau \langle p_0,p_1 \rangle \prec _c\tau \langle p_0^{\prime },p_1^{\prime } \rangle\) when \(p_1\) is a prefix of \(p_0^{\prime }\) or \(p_1^{\prime }\) .
As for \(\mathsf {pm}\) locations, they behave as a \(\mathtt {tick}\) location. By extension, we will sometime say that a location \(\ell \prec _cp\) when \(\ell \prec _cp ; \mathtt {tick}\) . Intuitively, this definition comes from where the continuation of a reduction is. For example, for the subprocess \(\mathtt {tick}.Q\) at position p, the continuation Q after a reduction is a subtree with its root at position p. Thus, any position in this tree for Q has p as a prefix, and so any reduction happening in Q has p as a prefix in its location.
The main interest of causal complexity is that this notion of causality can be adapted to account for different behaviours. For example, in Reference [16], the causality relation is different. For instance, they consider that linear communications (on non replicated input) do not propagate causality in their work. Here, we chose this causality relation to show the equivalence with annotated processes, and in this sense, our notion of span is a particular case of causal complexity with this choice of causality relation.
The important point in this causality relation we define is that a \(\tau\) location causes another location \(\ell\) when the output position is a prefix of the positions in \(\ell\) . Indeed, for a communication with a non-replicated input, the input position becomes a \({\odot }\) thus it cannot cause anything, and for a communication with a replicated input, we consider that two calls to the same replicated input are independent one from the other. Then, the important point is that two reductions with independent locations could be done in any order, it would not change the final tree.
With this definition of causality, intuitively we can define causal complexity of a computation as the maximal number of tick in all the chains of causality in this computation.
Definition 7.3 (Computation).
A computation from a process P is a sequence \((P_i,\ell _i)_{i \le N}\) such that \(P_0 = P\) and \(P_i \overset{\ell _i}{\longrightarrow } P_{i+1}\) for \(i \lt N\) .
Definition 7.4 (Chain of Causality).
In a computation \((P_i, \ell _i)_{i \le N}\) , we say that \(\ell _i\) depends on \(\ell _j\) , noted \(\ell _i \prec \ell _j\) when \(i \lt j\) and \(\ell _i \prec _c\ell _j\) . Then a chain of causality in this computation is a chain \(\ell _{i_1} \lt \ell _{i_2} \lt \cdots \lt \ell _{i_m}\) .
Definition 7.5 (Causal Complexity).
The causal complexity of a computation \((P_i, \ell _i)_{i \le N}\) is given by the maximal number of tick locations in all the chains of causality. Finally, the causal complexity of a process P, denoted \(\mathsf {CausC}(P)\) is defined as the maximal causal complexity over all computations from P.
We can now prove the equivalence between the notions of parallel with annotated processes complexity and causal complexity for this particular causality relation.

7.2 Span(P) ≥ CausC(P)

In this section, we show that span is an upper bound on causal complexity. Formally, we prove the following lemma.
Lemma 7.6.
Let P be a process. Let \((P_i,\ell _i)_{i \le N}\) be a computation from P with causal complexity K. Then, \(\mathsf {span}(P) \ge K\) .
To do that, we show that we can do the same computation with our semantics with annotated processes. Let us take a process P seen as a tree. By definition, each leaf of P is a guarded process G. For each leaf, we replace the guarded process G by \(0 : G\) , and we call \(P^{\prime }\) this annotated process. By the definition of congruence for annotated processes, we have \(P \equiv P^{\prime }\) . Then, we will work with this tree representation for annotated processes.
Definition 7.7 (Tree Representation of Annotated Processes).
We consider annotated trees such that a set of names is given at the beginning, nodes represent parallel composition and leaves are processes of the shape \(n : G\) with G guarded. Such a tree indeed represents an annotated process.
Then, we say that an annotated process \(P^{\prime }\) seen as a tree is an annotation of a process P seen as a tree if \(P^{\prime }\) and P have exactly the same shape, and each leaf G of P is a leaf \(n : G\) for \(P^{\prime }\) .
So, by definition \(P^{\prime }\) is an annotation of P. We can then prove the following lemma:
Lemma 7.8 (Causal Reduction and Annotation).
Suppose that \(P \overset{\ell }{\longrightarrow } Q\) . Then, for any \(P^{\prime }\) annotation of P, we have \(P^{\prime } \Rightarrow Q^{\prime }\) where \(Q^{\prime }\) is an annotation of Q.
Moreover, we have:
If \(\ell = p ; \mathtt {tick},\) then \(Q^{\prime }\) has the same annotation as \(P^{\prime }\) for all leaves at a position \(p^{\prime }\) such that p is not a prefix of \(p^{\prime }\) . For all the other leaves, \(Q^{\prime }\) has the annotation \(n+1\) where n is the annotation for the leaf at position p in \(P^{\prime }.\)
If \(\ell = p ; \mathsf {pm},\) then \(Q^{\prime }\) has the same annotation as \(P^{\prime }\) for all leaves at a position \(p^{\prime }\) such that p is not a prefix of \(p^{\prime }\) . For all the other leaves, \(Q^{\prime }\) has the annotation n where n is the annotation for the leaf at position p in \(P^{\prime }.\)
If \(\ell = \tau \langle p,p^{\prime } \rangle ,\) then \(Q^{\prime }\) has the same annotation as \(P^{\prime }\) for all leaves at position q such that \(p^{\prime }\) is not a prefix of q. For all the other leaves, \(Q^{\prime }\) has the annotation \(\max (n,m)\) where n is the annotation for the leaf at position p in \(P^{\prime }\) and m is the annotation for the leaf at position \(p^{\prime }\) in \(P^{\prime }\) .
Proof.
The proof is done by case analysis on the rules of Figure 18. All cases are rather direct. The idea is to always keep the same tree shape in the reduction \(\Rightarrow\) , and then to make the names go up and the annotations go down after doing this reduction using the congruence rules. Formally, the names can go up with \(((\nu a) P) \mathbin {\,|\,}Q \equiv (\nu a) (P \mathbin {\,|\,}Q)\) (always possible by \(\alpha\) -renaming) and \(n : ((\nu a) P) \equiv (\nu a) (n : P)\) , and then the annotations can go down with \(n : (P \mathbin {\,|\,}Q) \equiv n : P \mathbin {\,|\,}n : Q\) . Then, with the shape of the reduction relation \(\Rightarrow\) , we can indeed see that the annotations indeed correspond to the one given in this lemma.□
With this lemma, we can start from the annotation \(P^{\prime }\) of P, and simulate the computation. Now, we only need to show that the annotations correspond to the number of ticks in a chain of causality. Formally, we prove the following lemma.
Lemma 7.9.
Let \((P_i^{\prime },\ell _i)_{i \le N}\) be the computation given by the previous lemma from an original computation \((P_i,\ell _i)_{i \le N}\) . Then, for all \(i \le N\) , the annotation of a guarded process G at position p in \(P_i^{\prime }\) is an upper bound of the maximal number of \(\mathtt {tick}\) locations in all chains of causality for the locations \(\ell _0,\dots ,\ell _{i-1}\) such that the last location \(\ell\) of this chain satisfies \(\ell \prec _cp\)
We prove this by induction on i.
This is true for \(i=0,\) since \(P^{\prime }\) is P annotated with zeros everywhere.
Let \(i \lt N\) . Suppose that this is true for \(P_i^{\prime }\) , the annotation of \(P_i\) . Let us look at the reduction \(P_i \overset{\ell _i}{\longrightarrow } P_{i+1}\) .
If \(\ell _i = p ; \mathtt {tick}\) , then by induction hypothesis, the annotation n for the tick corresponds to the maximal number of \(\mathtt {tick}\) locations in all chains of causality for the locations \(\ell _0,\dots ,\ell _{i-1}\) that are also in causality \(\prec _c\) with p. Let us look at \(P_{i+1}^{\prime }\) given by lemma 7.8. For all the positions in \(P_{i+1}^{\prime }\) with p not a prefix, dependency did not change, since \(\ell _i = p; \mathsf {pm}\) does not cause those positions. As annotations did not change either, the hypothesis is still correct. For the new positions in the tree with p as a prefix, all the annotations are n. All chains of causality with the locations \(\ell _0,\dots ,\ell _i\) are either chains that do not contain \(\ell _i\) and that caused p and so \(n+1\) is a bound, because n is a bound by induction hypothesis, either they contain \(\ell _i\) and in this case it was a chain in causal relation with p, thus \(n + 1\) is a bound as n is a bound on the causality between \(\ell _0\) and \(\ell _{i-1}\) and the last location \(\ell _i\) adds one to the complexity. The case for pattern matching is a simpler version of this case.
If \(\ell _i = \tau \langle p,p^{\prime } \rangle\) , then by induction hypothesis, the annotation n for the input and m for the output are bounds on some chains of causality on \(\ell _0, \dots , \ell _{i-1}\) . Let us look at \(P_{i+1}^{\prime }\) given by Lemma 7.8. The only interesting positions are the one with \(p^{\prime }\) as a prefix. All the annotations for those positions are \(\max (n,m)\) . The only new chain of causality on \(\ell _0,\dots ,\ell _i\) that end with a location that causes those positions are the ones that finish with \(\ell _i\) . In this case, either they cause \(\ell _i\) , because they cause p or because they cause \(p^{\prime }\) . In both cases, n or m was a bound on the number of ticks by induction hypothesis. So, \(\max (n,m)\) is indeed a bound on the number of ticks for all those chains.
This concludes the proof. In the end, the annotation in position p in \(P_N\) is a bound on chains of causality that also cause p. Moreover, for any chain of causality, this chain causes its last position (or output position by definition of causality). Thus, all chains of causality are bounded by at least one of the annotations, so the maximum over all annotations is a bound on the causal complexity. This directly gives us that span is an upper bound on causal complexity.

7.3 CausC(P) ≥ Span(P)

Let us work on the converse. To do that, we will restrict a bit the congruence \(\equiv\) for annotated processes and expand the semantics \(\Rightarrow\) to work with trees. As before, we can define a tree congruence \(\equiv _t\) for annotated processes, with the base rules
\begin{equation*} (\nu a) (\nu b) P \equiv _t (\nu b) (\nu a)P, \end{equation*}
\begin{equation*} (\nu a)(P \mathbin {\,|\,}Q) \equiv _t (\nu a) P \mathbin {\,|\,}Q~(\text{when } a \text{ is not free in } Q), \qquad (\nu a)(P \mathbin {\,|\,}Q) \equiv _t P \mathbin {\,|\,}(\nu a) Q~(\text{when } a \text{ is not free in } P), \end{equation*}
\begin{equation*} n : (P \mathbin {\,|\,}Q) \equiv n : P \mathbin {\,|\,}n : Q, \qquad n : (m : P) \equiv (n+m) : P, \qquad (\nu a) (n : P) \equiv n : ((\nu a) P), \qquad 0 : P \equiv P. \end{equation*}
Then, we define the semantics \(\Rightarrow _t\) exactly as before but with trees instead of simple processes in parallel. An example is given in Figure 19.
Fig. 19.
Fig. 19. Tree semantics for span.
As before, any annotated process can be written in a tree representation as in Definition 7.7 using the tree congruence rule \(\equiv _t\) for annotated processes. So, from this, it is rather direct that this semantics defined with tree \(\Rightarrow _t\) is equivalent to the previously defined \(\Rightarrow\) , in the sense that they give the same complexity. (It relies in particular on the fact that congruence does not change the span). Now, we can work on this span with tree representation. Formally, we want to prove:
Lemma 7.10.
If P is a process without annotation, with \(P (\Rightarrow _t)^* Q\) and \(\mathcal {C}_{\ell }(Q) = K\) , then there is a computation \((P_i,\ell _i)_{i \le N}\) from P with causal complexity greater than K.
So, by definition of causal complexity and span, this will indeed show that \(\mathsf {CausC}(P) \ge \mathsf {span}(P).\)
As we only need to prove this lemma for processes without annotation, we can take an additional hypothesis on annotated processes: We consider in the following that annotations appear exclusively at the “top-level” of a process, so there is no annotation in the subprocess P in \(a(\widetilde{{v}}).P\) , in \(\mathtt {tick}.P\) , in \(!a(\widetilde{{v}}).P\) or in the subprocesses of a pattern matching. We can take this hypothesis, because if a process P satisfies this hypothesis and \(P \Rightarrow _t Q,\) then Q also satisfies this hypothesis. Of course, processes without annotation satisfy this hypothesis. Still, in this definition, we do not consider \(0 : P\) as a real annotation, since it can be removed by congruence. We start by the following definition.
Definition 7.11 (Removing Annotations).
Let P be a tree representation of an annotated process. We define \(\mathsf {forget}(P)\) as the tree P where leaves \(n : G\) are replaced by G.
Note that this definition only makes sense because of the previous hypothesis; otherwise, we would need to apply recursively the forgetful function to G. We then easily show the following lemma.
Lemma 7.12 (Forget Reductions).
Suppose that \(P \Rightarrow _t Q\) . Then, we have \(\mathsf {forget}(P) \overset{\ell }{\longrightarrow } \mathsf {forget}(Q)\) for some location \(\ell\) .
Proof.
This is a direct consequence of our definition of \(\Rightarrow _t\) . Note that the reduction \(\mathtt {tick}. P \Rightarrow _t 1 : P\) , or more generally \(n : \mathtt {tick}. P \Rightarrow _t (n+1) : P\) here corresponds indeed to removing a tick with the forgetful function.□
With this lemma, we can start from \(\mathsf {forget}(P)\) and simulate the reduction \((\Rightarrow _t)^*\) . Now, we only need to show that the annotations are bounded by the number of ticks in a chain of dependency. We show the following lemma:
Lemma 7.13.
If P is a process without annotation, and if \(P (\Rightarrow _t)^* Q\) , then there is a computation \((P_i,\ell _i)_{i \le N}\) from \(P = \mathsf {forget}(P)\) to \(\mathsf {forget}(Q)\) . Moreover, for each leaf \(n : G\) at position p in Q, there is a chain of causality with at least n ticks that ends with a location \(\ell\) such that \(\ell \prec _cp\) .
Note that from this lemma, we can immediately deduce Lemma 7.10. We prove this by induction on \(P (\Rightarrow _t)^* Q\) :
If this relation is the reflexive one, and \(P = Q\) , then this is direct, because all annotations are equal to 0.
Now, suppose we have \(P (\Rightarrow _t)^* R \Rightarrow _t Q\) . By induction hypothesis, there is a computation \((P_i,\ell _i)_{i \le N}\) from \(\mathsf {forget}(P)\) to \(\mathsf {forget}(R)\) , with the expected chains of causality. We now proceed by case analysis on \(R \Rightarrow Q\) .
If this reduction is a tick reduction at position p, then we have \(\mathsf {forget}(R) \overset{p;\mathtt {tick}}{\longrightarrow } \mathsf {forget}(Q)\) . Let us take a leaf \(n : G\) at position \(p^{\prime }\) of Q. If p is not a prefix of \(p^{\prime }\) , then this leaf was also in R. So, by induction hypothesis, we obtain the desired chain of causality. If p is a prefix of \(p^{\prime }\) , then \(n {-}1\) was the annotation for the position p in R. So, by induction hypothesis for R, there is a chain of causality with at least \(n {-}1\) ticks that ends with a location \(\ell\) such that \(\ell \prec _cp\) . By definition, it means that this last location \(\ell \prec _cp;\mathtt {tick}\) . So, this gives us a chain of causality with at least n ticks that ends with a location that causes \(p^{\prime }\) in Q. This concludes this case. The case of pattern matching is a simpler version of this case.
If this reduction is a synchronization with input at position p and output at position \(p^{\prime }\) , then we have \(\mathsf {forget}(R) \overset{\tau \langle p,p^{\prime } \rangle }{\longrightarrow } \mathsf {forget}(Q)\) . Let us take a leaf \(n : G\) at position q of Q. We only consider the interesting case: \(p^{\prime }\) is a prefix of q. Then, we have \(n = \max (n_0,n_1)\) with \(n_0\) the annotation for the input position p in R and \(n_1\) the annotation for the output position \(p^{\prime }\) in R. Let us say, by symmetry, that \(n_0\) is the maximum between those two. So, by induction hypothesis for R, there is a chain of causality with at least \(n_0\) ticks that ends with a location \(\ell\) such that \(\ell \prec _cp\) . By definition, it means that this last location \(\ell \prec _c\tau \langle p,p^{\prime } \rangle\) . So, this gives us a chain of causality with at least \(n_0\) ticks that ends with a location that causes q in Q. This concludes this case.
This concludes the proof.
We have indeed obtained that causal complexity is an upper bound of span. From this, we have the equivalence between causal complexity and our definition of span.

8 Related Work

An analysis of the complexity of parallel functional programs based on types has been carried out in Reference [26]. Their system can analyse the work and the span (called depth in this article), and makes use of amortized complexity analysis, which allows one to obtain sharp bounds. However, the kind of parallelism they analyse is limited to parallel composition. So, on the one hand, we are considering a more general model of parallelism, and on the other hand, we are not taking advantage of amortized analysis as they do. Reference [20] proposes a complexity analysis of parallel functional programs written in interaction nets, a graph-based language derived from linear logic. Their analysis is based on sized types. However, their model is also quite different from ours as interaction nets do not provide name-passing.
Other works, like Reference [2], tackle the problem of analysing the parallel complexity of a distributed system by building a distributed flow graph and searching for a path of maximal cost in this graph. Another approach to analyse loops with concurrency in an actor-based language is done by rely-guarantee reasoning [3]. Those approaches give interesting results on some classes of systems, but they cannot be directly applied to the \(\pi\) -calculus language we are considering, with dynamic creation of processes and channels. Moreover, they do not offer the same compositionality as analysis based on type systems. Reference [19] studies distributed systems that are comparable to those of Reference [2], and analyses their complexity by means of a behaviour type system. In a second step the types are used to run an analysis that returns complexity bounds. Thus, this approach is more compositional than that of Reference [2], but still does not apply to our \(\pi\) -calculus language.
Let us now turn to related works in the setting of \(\pi\) -calculus or process calculi. To our knowledge, the first work to study parallel complexity in \(\pi\) -calculus by types was given by Kobayashi [30], as another application of his type system for deadlock freedom, further developed in other papers [33]. In his setting, channels are typed with usages, which are simple CCS-like processes to describe the behaviour of a channel. To carry out complexity analysis, those usages are annotated by two time informations, obligation and capability. The obligation level is the time at which a channel is ready to perform an action, and the capability level is the time at which it successfully finds a communication partner. We believe that when they are not infinite, the sum of those levels is related to our own time annotation of channels. The definition of parallel complexity in this work differs from ours, as it loses some non-deterministic paths and the extension with dependent types is suggested but not detailed. It is not clear to us if everything can be adapted to reason only about our parallel complexity, but we plan to study it in future work. More recently, Das et al. in References [12, 13] proposed a type system with temporal session types to capture several parallel cost models with the use of a tick constructor. Our usage of time was inspired by their types with the usual next modality of temporal logic, but in this paper they also use the always and eventually modalities to gain expressivity. We believe that because our usage of time is more permissive, those modalities would not be useful in our calculus. Because of session-types, they have linearity for the use of data-types such as lists, but they obtain deadlock-freedom contrary to our calculus. Moreover, they provide decidable operations to simplify the use of their types, such as subtyping, but they do not define dependent types nor sized types that are useful to treat data-types. Still, they provide a significant number of examples to show the expressivity of their type system. In a recent paper [8], a framework was introduced for the cost analysis in multiparty session types. It shares with our approach the use of sized types but it is targeted at communication protocols, which is slightly different from our problematic. It would be interesting however to carry out a closer comparison with our setting.
The methodology of our work is inspired by implicit computational complexity, which aims at characterizing complexity classes by means of dedicated programming languages, mainly in the sequential setting, for instance, by providing languages for FPTIME functions. Some results have been adapted to the concurrent case, but mainly for the work complexity or for other languages than the \(\pi\) -calculus, e.g., References [10, 17, 35] (the first reference is for a higher-order \(\pi\) -calculus). Reference [16] is closer to our setting as it defines a notion of causal complexity in \(\pi\) -calculus and gives a type system characterizing processes with polynomial complexity. However, contrary to those works, we do not restrict to a particular complexity class (like FPTIME) and we handle the case of the span.
Technically, the types we use are inspired from linear dependent types [9]. Those are one of the many variants of sized types, which were introduced in Reference [29].

9 Conclusion and Perspectives

We believe that the salient contributions of this article are the following:
a definition of the span in \(\pi\) -calculus by means of a simple reduction semantics (reduction of annotated processes),
a sized type system for \(\pi\) -calculus, which is here employed for analysing the complexity, but which we think could be used for other applications,
a natural proof method for establishing the complexity soundness of a type system for span, consisting in proving a subject reduction property for the annotated processes.
We see several possible future directions to this work:
Type inference: We plan to investigate how type inference could be automatized or partially automatized for the span type system. We will study typing by constraint generation and explore whether existing off-the-shelf solvers or new procedures could allow one to solve these constraints. We have shown here (Section 4.6) that the case of work generates a set of constraints close to those in Reference [4]. However, the case of span could require more sophisticated reasoning because of the strong distinction between servers and channels with the advancing of time.
We have mentioned that our type system for span is not adapted to analyse some concurrent systems such as the simple example of the semaphore (Section 5.3). However, we believe that a type system based on an adaptation of usages [30, 32, 33] could be promising for this purpose.
It would be challenging to examine whether similar type systems could be developed to account for some other complexity properties, for instance, to extract the number of parallel processes needed to achieve the span.

Acknowledgment

We are grateful to Naoki Kobayashi for suggesting the definition of annotated processes and their reduction that we use in this article.

References

[1]
Selim G. Akl. 2011. Encyclopedia of Parallel Computing. Springer, Boston, MA, 139–146.
[2]
Elvira Albert, Jesús Correas, Einar Broch Johnsen, and Guillermo Román-Díez. 2015. Parallel cost analysis of distributed systems. In Proceedings of the 22nd International Symposium on Static Analysis (SAS’15)(Lecture Notes in Computer Science, Vol. 9291). Springer, 275–292.
[3]
Elvira Albert, Antonio Flores-Montoya, Samir Genaim, and Enrique Martin-Martin. 2017. Rely-guarantee termination and cost analyses of loops with concurrent interleavings. J. Autom. Reason. 59, 1 (2017), 47–85.
[4]
Martin Avanzini and Ugo Dal Lago. 2017. Automating sized-type inference for complexity analysis. Proc. ACM Program. Lang. 1 (2017), 43.
[5]
Patrick Baillot and Alexis Ghyselen. 2021. Types for complexity of parallel computation in pi-calculus. In Proceedings of the 30th European Symposium on Programming Languages and Systems (ESOP’21)(LNCS, Vol. 12648). Springer, 59–86.
[6]
Patrick Baillot and Virgile Mogbil. 2004. Soft lambda-Calculus: A language for polynomial time computation. In Proceedings of the 7th International Conference on Foundations of Software Science and Computation Structures (FOSSACS’04)(LNCS, Vol. 2987). Springer, 27–41.
[7]
Patrick Baillot and Kazushige Terui. 2004. Light types for polynomial time computation in lambda-calculus. In Proceedings of the 19th IEEE Symposium on Logic in Computer Science (LICS’04). IEEE Computer Society, 266–275.
[8]
David Castro-Perez and Nobuko Yoshida. 2020. CAMP: Cost-aware multiparty session protocols. Proc. ACM Program. Lang. 4, OOPSLA (2020), 155:1–155:30.
[9]
Ugo Dal Lago and Marco Gaboardi. 2011. Linear dependent types and relative completeness. In Proceedings of the 26th Annual IEEE Symposium on Logic in Computer Science (LICS’11), Proceedings. IEEE, 133–142.
[10]
Ugo Dal Lago, Simone Martini, and Davide Sangiorgi. 2016. Light logics and higher-order processes. Math. Struct. Comput. Sci. 26, 6 (2016), 969–992.
[11]
Ornela Dardha, Elena Giachino, and Davide Sangiorgi. 2017. Session types revisited. Info. Comput. 256 (2017), 253–286.
[12]
Ankush Das, Jan Hoffmann, and Frank Pfenning. 2018. Parallel complexity analysis with temporal session types. Proc. ACM Program. Lang. 2, ICFP (2018), 91:1–91:30.
[13]
Ankush Das, Jan Hoffmann, and Frank Pfenning. 2018. Work analysis with resource-aware session types. In Proceedings of the 33rd Annual ACM/IEEE Symposium on Logic in Computer Science (LICS’18). ACM, 305–314.
[14]
Pierpaolo Degano, Fabio Gadducci, and Corrado Priami. 2003. Causality and replication in concurrent processes. In Perspectives of System Informatics. Springer, Berlin, 307–318.
[15]
Pierpaolo Degano and Corrado Priami. 1995. Causality for mobile processes. In Automata, Languages, and Programming. Springer, Berlin, 660–671.
[16]
Romain Demangeon and Nobuko Yoshida. 2018. Causal computational complexity of distributed processes. In Proceedings of the 33rd Annual ACM/IEEE Symposium on Logic in Computer Science (LICS’18). ACM, 344–353.
[17]
Paolo Di Giamberardino and Ugo Dal Lago. 2015. On session types and polynomial time. Math. Struct. Comput. Sci. 1 (2015).
[18]
Marco Gaboardi, Jean-Yves Marion, and Simona Ronchi Della Rocca. 2008. A logical account of pspace. In Proceedings of the 35th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL’08). ACM, 121–131.
[19]
Elena Giachino, Einar Broch Johnsen, Cosimo Laneve, and Ka I. Pun. 2016. Time complexity of concurrent programs—A technique based on behavioural types. In Proceedings of the 12th International Conference on Formal Aspects of Component Software (FACS’15)(Lecture Notes in Computer Science, Vol. 9539). Springer, 199–216.
[20]
Stéphane Gimenez and Georg Moser. 2016. The complexity of interaction. In Proceedings of the 43rd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL’16). 243–255.
[21]
Emmanuel Hainry, Jean-Yves Marion, and Romain Péchoux. 2013. Type-based complexity analysis for fork processes. In Proceedings of the 16th International Conference on Foundations of Software Science and Computation Structures (FOSSACS’13)(Lecture Notes in Computer Science, Vol. 7794). Springer, 305–320.
[22]
Robert Harper. 2012. Practical Foundations for Programming Languages. Cambridge University Press.
[23]
Jan Hoffmann, Klaus Aehlig, and Martin Hofmann. 2012. Multivariate amortized resource analysis. ACM Trans. Program. Lang. Syst. 34, 3 (2012), 14:1–14:62.
[24]
Jan Hoffmann, Klaus Aehlig, and Martin Hofmann. 2012. Resource aware ML. In Proceedings of the 24th International Conference on Computer Aided Verification (CAV’12)(Lecture Notes in Computer Science, Vol. 7358). Springer, 781–786.
[25]
Jan Hoffmann and Martin Hofmann. 2010. Amortized resource analysis with polynomial potential. In Proceedings of the 19th European Symposium on Programming on Programming Languages and Systems (ESOP’10)(Lecture Notes in Computer Science, Vol. 6012). Springer, 287–306.
[26]
Jan Hoffmann and Zhong Shao. 2015. Automatic static cost analysis for parallel programs. In Programming Languages and Systems. Springer, Berlin, 132–157.
[27]
Martin Hofmann. 2003. Linear types and non-size-increasing polynomial time computation. Info. Comput. 183, 1 (2003), 57–85.
[28]
Martin Hofmann and Steffen Jost. 2003. Static prediction of heap space usage for first-order functional programs. In Proceedings of the 30th SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL’03). ACM, 185–197.
[29]
John Hughes, Lars Pareto, and Amr Sabry. 1996. Proving the correctness of reactive systems using sized types. In Proceedings of the 23rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. ACM, 410–423.
[30]
Naoki Kobayashi. 2002. A type system for lock-free processes. Info. Comput. 177, 2 (2002), 122–159.
[31]
Naoki Kobayashi. 2003. Type systems for concurrent programs. In Formal Methods at the Crossroads: From Panacea to Foundational Support. Springer, 439–453.
[32]
Naoki Kobayashi. 2005. Type-based information flow analysis for the \(\pi\) -calculus. Acta Informatica 42, 4–5 (2005), 291–347.
[33]
Naoki Kobayashi. 2006. A new type system for deadlock-free processes. In Proceedings of the International Conference on Concurrency Theory. Springer, 233–247.
[34]
Naoki Kobayashi, Benjamin C. Pierce, and David N. Turner. 1999. Linearity and the pi-calculus. ACM Trans. Program. Lang. Syst. 21, 5 (Sep. 1999), 914–947.
[35]
Antoine Madet and Roberto M. Amadio. 2011. An elementary affine \(\lambda\) -calculus with multithreading and side effects. In Proceedings of the 10th International Conference on Typed Lambda Calculi and Applications (TLCA’11)(Lecture Notes in Computer Science, Vol. 6690). Springer, 138–152.
[36]
Jean-Yves Marion. 2011. A type system for complexity flow analysis. In Proceedings of the 26th Annual IEEE Symposium on Logic in Computer Science, (LICS’11). IEEE Computer Society, 123–132.
[37]
Robin Milner, Joachim Parrow, and David Walker. 1992. A calculus of Mobile processes, I. Info. Comput. 100, 1 (1992), 1–40.
[38]
Davide Sangiorgi and David Walker. 2003. The Pi-calculus: A Theory of Mobile Processes. Cambridge University Press.
[39]
Pedro B. Vasconcelos. 2008. Space cost analysis using sized types. Ph.D. Dissertation. University of St. Andrews.

Cited By

View all

Recommendations

Comments

Information & Contributors

Information

Published In

cover image ACM Transactions on Programming Languages and Systems
ACM Transactions on Programming Languages and Systems  Volume 44, Issue 3
September 2022
302 pages
ISSN:0164-0925
EISSN:1558-4593
DOI:10.1145/3544000
Issue’s Table of Contents

Publisher

Association for Computing Machinery

New York, NY, United States

Publication History

Published: 15 July 2022
Online AM: 23 February 2022
Accepted: 01 November 2021
Revised: 01 September 2021
Received: 01 March 2021
Published in TOPLAS Volume 44, Issue 3

Permissions

Request permissions for this article.

Check for updates

Author Tags

  1. Type systems
  2. pi-calculus
  3. process calculi
  4. complexity analysis
  5. implicit computational complexity
  6. sized types

Qualifiers

  • Research-article
  • Refereed

Funding Sources

  • LABEX MILYON

Contributors

Other Metrics

Bibliometrics & Citations

Bibliometrics

Article Metrics

  • Downloads (Last 12 months)300
  • Downloads (Last 6 weeks)48
Reflects downloads up to 21 Sep 2024

Other Metrics

Citations

Cited By

View all

View Options

View options

PDF

View or Download as a PDF file.

PDF

eReader

View online with eReader.

eReader

HTML Format

View this article in HTML Format.

HTML Format

Get Access

Login options

Full Access

Media

Figures

Other

Tables

Share

Share

Share this Publication link

Share on social media