Roberto M Amadio

Frederic Dabrowski

Frédéric Dabrowski

Feasible reactivity in a synchronous π-calculus *

come

Feasible reactivity in a synchronous pi-calculus

Introduction

Mastering the computational complexity of programs is an important aspect of computer security with applications ranging from embedded systems to mobile code and smartcards. One approach to this problem is to monitor at run time the resource consumption and to rise an exception when some bound is reached. A variant of this approach is to instrument the code so that bounds are checked at appropriate time. An alternative approach is to analyse statically the program to guarantee that during the execution it will respect certain resource bounds. In other words, the first approach performs a dynamic verification while the second relies on a static analysis. As usual, the main advantage of the first approach is its flexibility while the advantage of the second approach is the fact that it does not introduce an overhead at run time and, perhaps more importantly, that it allows an early detection of 'buggy' programs. In this work, we will focus on the static analyses which offer the more challenging problems while keeping in mind that the two approaches are complementary. For instance, static analyses may be helpful in reducing the frequency of dynamic verifications.

When addressing the issue of resource control, there is a variety of properties of a program that one may check. Termination is probably the first one that comes to mind. However, in the context of interactive programs, this property should be refined into reactivity. In general, the set of reactive programs can be defined (co-inductively) as the largest set R of programs that terminate and such that each interaction with the environment leads to a program which is again in the set R.

If a program manipulates data values of variable size such as lists, trees, graphs, . . . then the analysis can go beyond reactivity and, for instance, it can establish that the program reacts while using a feasible amount of resources where feasible can be understood, for instance, as computable in polynomial time. In this case, the analysis produces a function that bounds the time (or space) needed for the reaction depending on the size of certain parameters.

There is a large collection of static analysis techniques (see, e.g., [START_REF] Cobham | The intrinsic computational difficulty of functions[END_REF][START_REF] Bellantoni | A new recursion-theoretic characterization of the poly-time functions[END_REF][START_REF] Hofmann | The strength of non size-increasing computation[END_REF][START_REF] Jones | Computability and complexity, from a programming perspective[END_REF][START_REF] Leivant | Predicative recurrence and computational complexity i: word recurrence and poly-time[END_REF][START_REF] Bonfante | On termination methods with space bound certifications[END_REF]] that allow to establish feasible reactivity of functional programs. A common feature of these methods is the combination of traditional termination methods with what could be called a data-size flow analysis. By this we mean a method to describe how the size of the values computed by a program depends on the size of the values taken in input.

In [START_REF] Amadio | Resource control for synchronous cooperative threads[END_REF][START_REF] Amadio | Feasible reactivity for synchronous cooperative threads[END_REF], we have started a research programme that aims at extending this approach to a synchronous, concurrent programming language. In the present work, we focus in particular on the Sπ-calculus [START_REF] Amadio | A synchronous π-calculus[END_REF]. This is a synchronous version of the π-calculus [START_REF] Milner | A calculus of mobile processes, parts 1-2[END_REF] which is based on the SL (synchronous language) model [START_REF] Boussinot | The SL Synchronous Language[END_REF]. The latter can be regarded as a relaxation of the Esterel model [START_REF] Berry | The Esterel synchronous programming language[END_REF] where the reaction to the absence of a signal within an instant can only happen at the next instant. Various full fledged concurrent and synchronous programming languages have been developed on top of the SL model (see, e.g., [START_REF] Serrano | Scheme fair threads[END_REF][START_REF] Mandel | ReactiveML, a reactive extension to ML[END_REF]) and the Sπ-calculus can be regarded as a more refined model capturing some essential aspects of those languages.

Our contribution includes (i) a methodology to annotate programs and (ii) related static analysis methods that guarantee feasible reactivity for finite control programs expressed in the Sπ-calculus.

Programs come with two kinds of annotations that concern thread identifiers and signals. A characteristic of synchronous programs is that each thread performs some set of actions in a cyclic way. A cycle is different from an instant in that it can span several instants (possibly an unbounded number of them). We require that a subset of the thread identifiers mark the end of a cycle and the beginning of a new one. This annotation has no effect on the operational semantics but it is used to produce certain static conditions. The first condition is what we call the read once condition. Informally, this condition requires that each thread within each cycle can only read a finite number of signals. The technical consequence of this restriction is that the behaviour of a thread within an instant can be described as a function of its parameters and the (finitely many) values read within the same cycle.

Thread identifiers carry two additional annotations. A basic goal is to show that each instant terminates. We are then naturally lead to compare thread identifiers and their parameters according to some suitable well-founded order. For this reason we assume that each thread identifier is annotated with a status that describes how its parameters should be compared (typically, according to a lexicographic or multi-set order). Another important goal towards feasible reactivity, is to show that the parameters of a thread are in a sense non-size increasing. It turns out that it is not always appropriate to consider all parameters and therefore we require that we explicitly associate with each thread identifier the (possibly proper) subset of parameters that should be considered in the analysis of its size. To summarise, a thread identifier has three kinds of annotations: one saying whether it marks the end of a cycle, another, that we call status, describing how its parameters have to compared for termination analysis, and a final one specifying the subset of the parameters that are relevant to the computation of its size.

On one hand, a program should be allowed to emit values on a signal that depend on values read on other signals. On the other hand, we want to avoid situations where, for example, a program repeatedly reads a value on a signal and emits a larger value on the same signal. To address this issue, we assume that signal names are partitioned into a finite number of regions which are ordered. More precisely, we refine the type system so that signal types come with a region ρ as in the type Sig ρ (t). In other terms, the type of a signal name explicitly carries the information on the region to which the signal name belongs. Again, this annotation does not affect the operational semantics but it is used in the generation of static conditions that guarantee feasible reactivity. Informally, the condition states that the size of a value emitted on a signal at region ρ is bound by a function of the size of the values read from signals of smaller regions.

Next, we move on to an informal description of the static conditions. First of all, we have to find an abstract way to describe the data-size flow of a program. To this end, we import and adapt the concept of quasi-interpretation that has been proposed in the context of the analysis of the computational complexity of first-order functional programs [START_REF] Bonfante | On termination methods with space bound certifications[END_REF][START_REF] Amadio | Synthesis of max-plus quasi-interpretations[END_REF]. As a second step, we describe a method to associate with a program a finite set of inequalities on first-order terms and prove that whenever these inequalities are satisfied by a (polynomially bounded) quasi-interpretation the program is feasibly reactive. The inequalities can be classified in three categories according to their purpose which is to ensure: (1) the termination of each instant, (2) that the size of the parameters of a thread at the beginning of each cycle is non-size increasing, (3) that the size of the values computed by a thread within a cycle is bounded by a polynomial in the size of the parameters of the thread and the size of the values read on the signals within the cycle. Obviously, these inequalities depend on the signal and thread annotations we described above.

The rest of the paper is organised as follows. In section 2 we introduce the syntax of the Sπ-calculus along with some programming examples and an informal comparison with the π-calculus. In section 3, we provide the formal reduction semantics of the Sπ-calculus and we introduce the notion of feasible reactivity. In section 4, we define the different kinds of thread and signal annotations mentioned above, we show how to associate a set of inequalities with an annotated program, and we introduce the notion of assignment which provides an interpretation of the inequalities in terms of numerical functions. A quasiinterpretation is a polynomially bounded assignment which satisfies the inequalities. Our main result states that a program that admits a quasi-interpretation is feasibly reactive.

We devote section 5 to an outline of the proof techniques leaving the details in an appendix.

The Sπ-calculus

We introduce the syntax of the Sπ-calculus along with some programming examples and an informal comparison with the π-calculus.

Programs

Programs P, Q, . . . in the Sπ-calculus are defined as follows:

P ::= 0 | | A(e) | | se | | s(x).P, K | | [s 1 = s 2 ] P 1 , P 2 | | [u ¤ p] P 1 , P 2 | | νs P | | P 1 | P 2 K ::= A(r)
We use the notation m for a vector m 1 , . . . , m n , n ≥ 0. The informal behaviour of programs follows. 0 is the terminated thread. A(e) is a (tail) recursive call of a thread identifier A with a vector e of expressions as argument; as usual the thread identifier A is defined by a unique equation A(x) = P such that the free variables of P occur in x. se evaluates the expression e and emits its value on the signal s. s(x).P, K is the present statement which is the fundamental operator of the SL model. If the values v 1 , . . . , v n have been emitted on the signal s then s(x).P, K evolves non-deterministically into [v i /x]P for some v i ([ / ] is our notation for substitution). On the other hand, if no value is emitted then the continuation K is evaluated at the end of the instant. [s 1 = s 2 ] P 1 , P 2 is the usual matching function of the π-calculus that runs P 1 if s 1 = s 2 and P 2 , otherwise. Here both s 1 and s 2 are free. [u ¤ p] P 1 , P 2 , matches u against the pattern p. We assume u is either a variable x or a value v and p has the shape c(p), where c is a constructor and p is a vector of patterns. We also assume that if u is a variable x then x does not occur free in P 1 . At run time, u is always a value and we run σP 1 if σ is the substitution matching u against p if it exists, and P 2 otherwise. Note that as usual the variables occurring in the pattern p (including signal names) are bound. νs P creates a new signal name s and runs P . (P 1 | P 2 ) runs in parallel P 1 and P 2 . The continuation K is simply a recursive call whose arguments are either expressions or values associated with signals at the end of the instant in a sense that we explain below. We will also write pause.K for νs s(x).0, K with s not free in K. This is the program that waits till the end of the instant and then evaluates K.

Expressions

The definition of programs relies on the following syntactic categories:

Sig ::= s | | t | | • • • (signal names) Var ::= Sig | | x | | y | | z | | • • • (variables) Cnst ::= * | | nil | | cons | | c | | d | | • • • (constructors) Val ::= Sig | | Cnst(
)| = 1 + Σ i=1,...,n |v i | if n ≥ 1.
Patterns Pat are terms built out of constructors and variables (including signal names). We assume first-order function symbols f, g, . . . whose behaviour will be defined axiomatically. Expressions Exp are terms built out of variables, constructors, and function symbols. Finally, Rexp are expressions that may include the value associated with a signal s at the end of the instant (which is written !s, following the ML notation for dereferenciation). Intuitively, this value is a list of values representing the set of values emitted on the signal during the instant. If P, p are a program and a pattern then we denote with fn(P ), fn(p) the set of free signal names occurring in them, respectively. We also use FV (P ), FV (p) to denote the set of free variables (including signal names). More inductive types (booleans, numbers, trees,. . .) can be added along with more constructors. We assume that variables (including signals), constructor symbols, and thread identifiers come with their (first-order) types. For instance, a constructor c may have a type (t 1 , t 2 ) → t meaning that it waits two arguments of type t 1 and t 2 respectively and returns a value of type t. It is then straightforward to define when a program is well-typed and verify that this property is preserved by the following reduction semantics. We just notice that if a signal name s has type Sig(t) then its dereferenced value !s should have type list(t). In the following, we will tacitly assume that we are handling well typed programs, expressions, substitutions,. . .

Typing

Comparison with the π-calculus

The syntax of the Sπ-calculus is similar to the one of the π-calculus, however there are some important semantic differences to keep in mind. Deadlock vs. End of instant. What happens when all threads are either terminated or waiting for an event that cannot occur? In the π-calculus, the computation stops. In the Sπ-calculus (and more generally, in the SL model), this situation is detected and marks the end of the current instant. Then suspended threads are reinitialised, signals are reset, and the computation moves to the following instant. Channels vs. Signals. In the π-calculus, a message is consumed by its recipient. In the Sπ-calculus, a value emitted along a signal persists within an instant and it is reset at the end of it. We note that in the semantics the only relevant information is whether a given value was emitted or not, e.g., we do not distinguish the situation where the same value is emitted once or twice within an instant. Data types. The (polyadic) π-calculus has tuples as basic data type, while the Sπ-calculus has lists. The reason for including lists rather than tuples in the basic calculus is that at the end of the instant we transform a set of values into a suitable data structure (in our case a list) that represents the set and that can be processed as a whole in the following instant. Note in particular, that the list associated with a signal is nil if and only if no value was emitted on the signal during the instant. This allows to detect the absence of a signal at the end of the instant. We consider a simple example that illustrates our discussion. Assume v 1 = v 2 are two distinct values and consider the following program in Sπ:

P = ν s 1 , s 2 ( s 1 v 1 | s 1 v 2 | s 1 (x). (s 1 (y). (s 2 (z). A(x, y) , B(!s 1 )) , 0) , 0 )
If we forget about the underlined parts and we regard s 1 , s 2 as channel names then P could also be viewed as a π-calculus process. In this case, P would reduce to

P 1 = νs 1 , s 2 (s 2 (z).A(σ(x), σ(y))
where σ is a substitution such that σ(x), σ(y) ∈ {v 1 , v 2 } and σ(x) = σ(y). In Sπ, signals persist within the instant and P reduces to

P 2 = νs 1 , s 2 (s 1 v 1 | s 1 v 2 | (s 2 (z).A(σ(x), σ(y)), B(!s 1 )))
where σ(x), σ(y) ∈ {v 1 , v 2 }. What happens next? In the π-calculus, P 1 is deadlocked and no further computation is possible. In the Sπ-calculus, the fact that no further computation is possible in P 2 is detected and marks the end of the current instant. Then an additional computation represented by the relation → moves P 2 to the following instant:

P 2 → P ′ 2 = νs 1 , s 2 B(v) where v ∈ {[v 1 ; v 2 ], [v 2 ; v 1 ]}.
Thus at the end of the instant, a dereferenced signal such as !s 1 becomes a list of (distinct) values emitted on s 1 during the instant and then all signals are reset.

Programming examples

We introduce a few programming examples on which we will rely in the following to illustrate our static analysis techniques.

Example 1. The synchronous model is particularly adapted to the simulation of various kinds of systems (we refer to [START_REF]Reactive Programming[END_REF] for a number of examples). Here, we describe the behaviour of a cell of a generic cellular automaton. Each cell relies on three parameters: its own activation signal s, its state q, and the list ℓ of activation signals of its neighbours. The cell performs the following operations in a cyclic fashion: (i) it emits its current state on the activation signals of its neighbours, (ii) it suspends for the current instant, and (iii) it collects the values emitted by its neighbours and computes its new state. This behaviour can be programmed as follows:

Cell (s, q, ℓ) = Send (s, q, ℓ, ℓ) Send(s, q, ℓ, ℓ ′ ) = [ℓ ′ ¤ cons(s ′ , ℓ ′′ )] (s ′ q | Send (s, q, ℓ, ℓ ′′ )), pause.Cell(s, next(q, !s), ℓ)
where next is a function that computes the following state of the cell according to its current state and the state of its neighbours. We assume some finite enumerated type 'state' that contains a constant for each state. The type of the signals s, s ′ is Sig(state), the type of the lists ℓ, ℓ ′ is list(Sig(state)), and the type of the function next is state, list(state) → state.

Example 2. This example describes a 'server' handling a list of requests emitted in the previous instant on the signal s. For each request of the shape req(s ′ , x), it provides an answer which is a function of x along the signal s ′ .

Server (s) = pause.Handle(s, !s) Handle(s, ℓ) = [l ¤ cons(req(s ′ , x), ℓ ′ )] (s ′ f (x) | Handle(s, ℓ ′ )), Server(s)
Assume the function f has type t → t ′ and assume an inductive type treq with a constructor req : Sig(t ′ ), t → treq. Then the parameters s have type Sig(treq) and the lists ℓ, ℓ ′ have type list(treq). Example 3. This example describes two threads: the thread A(s) re-emits on s the values that were emitted on s in the previous instant while the thread C(s) emits a (fresh) value on s.

A(s) = pause.B(s, !s) B(s, ℓ) = [ℓ ¤ cons(n, ℓ ′ )] (sn | B(s, ℓ ′ )), A(s) C(s) = νn sn | pause.C(s)
Assuming n has type Sig(1), s has type Sig(Sig(1)), and the list ℓ has type list(Sig(1)).

Reduction semantics and feasible reactivity

We provide the formal reduction semantics of the Sπ-calculus and we introduce the notion of feasible reactivity.

Expression evaluation

We assume an evaluation relation ⇓ such that for every function symbol f and values v 1 , . . . , v n of suitable type there is a unique value v such that f (v 1 , . . . , v n ) ⇓ v, fn(v) ⊆ i=1,...,n fn(v i ), and moreover we suppose that the value v can be computed in time polynomial in the size of the values v 1 , . . . , v n . As already mentioned, the techniques for defining first-order functional programs that enjoy these properties are well-studied.

The evaluation relation ⇓ is extended to expressions as usual:

s ⇓ s e i ⇓ v i i = 1, . . . , n c(e 1 , . . . , e n ) ⇓ c(v 1 , . . . , v n ) e i ⇓ v i i = 1, . . . , n f (v 1 , . . . , v n ) ⇓ v f (e 1 , . . . , e n ) ⇓ v
We will abbreviate e 1 ⇓ v 1 , . . . , e n ⇓ v n with e ⇓ v.

Reduction semantics

The (internal) behaviour of a program is specified by (i) a reduction system → describing the possible reductions of the program during an instant and (ii) an evaluation relation → determining how a program evolves at the end of each instant. These definitions rely on a structural equivalence relation ≡ that we introduce first.

Structural equivalence

The structural equivalence ≡ is the least equivalence relation on programs that identifies programs up to α-renaming and that satisfies the following standard equations:

P | 0 ≡ P, P 1 | P 2 ≡ P 2 | P 1 , (P 1 | P 2 ) | P 3 ≡ P 1 | (P 2 | P 3 ), νs P ≡ P if s / ∈ fn(P ), νs P 1 | P 2 ≡ νs (P 1 | P 2 ) if s / ∈ fn(P 2 ) .

Reduction relation

We introduce the following reduction rules:

e ⇓ v se | s(x).P, K -⊲ se | [v/x]P A(x) = P e ⇓ v A(e) -⊲ [v/x]P [s = s]P 1 , P 2 -⊲ P 1 s = s ′ [s = s ′ ]P 1 , P 2 -⊲ P 2 match(v, p) = σ [v ¤ p] P 1 , P 2 -⊲ σP 1 match(v, p) undefined [v ¤ p] P 1 , P 2 -⊲ P 2 A static context C is defined by C ::= [ ] | | νs C | | (C | P ).
The reduction relation → is then defined by the rule:

P ≡ C[P ′ ] P ′ -⊲ Q ′ C[Q ′ ] ≡ Q P → Q 3.2.

Suspension and evaluation at the end of the instant

We write P ↓ if ¬∃Q (P → Q) and say that the program P is suspended. When P is suspended the instant ends and an additional computation is carried on to move to the next instant. This goes in three steps that amount to: (1) collect in lists the set of values emitted on every signal, (2) extrude the signal names contained in values visible at the end of the instant, and (3) initialise the continuations K of the present statements.

To this end, we introduce first some notation. A suspended program P is structurally equivalent to:

νs(S | In) (1)
where the signal names s are all distinct, S ≡ s

1 e 1 | • • • | s n e n , In ≡ t 1 (x 1 ).P 1 , A 1 (r 1 ) | • • • | t m (x m ).P m , A m (r m ),
and n, m ≥ 0 (by convention an empty parallel composition equals the program 0). We write se ∈ S to mean that se occurs in the parallel composition S.

We can now formalise the steps (1-3).

1. Let V be a function from signal names to lists of values. We say that V represents S and write V -S if for all signal names s,

if {v 1 , . . . , v n } = {v | se ∈ S, e ⇓ v} then V (s) = [v π(1) ; • • • ; v π(n) ]
for some permutation π.

2. We define Free(νs S) as the least set of signal names such that Free(νs S) ⊇ fn(νs S) and if s ∈ Free(νs S), se ∈ S, e ⇓ v, and s ′ ∈ fn(v) then s ′ ∈ Free(νs S). For instance, Free(νs

1 , s 2 ss 1 | s 1 s 2 ) = {s, s 1 , s 2 }.
3. If r is an expression with dereferenciation then V (r) is the expression resulting from the replacement of all dereferenced signals !s with V (s). If A(r) is a continuation K of a present statement, where r are closed expressions, then Eval (A(r),

V ) = A(v) if V (r) ⇓ v. Finally, if In is defined as in (1) then Eval (In, V ) = Eval (A 1 (r 1 ), V ) | • • • | Eval (A m (r m ), V ).
With these conventions, we can now state the evaluation rule at the end of the instant:

P ↓ P ≡ νs (S | In) V -S {s ′ } = {s}\Free(νs S) P ′ ≡ νs ′ Eval (In, V ) P → P ′
In this rule, (i) we decompose the suspended program in emissions and inputs, (ii) we compute a representation of the emission, (iii) we compute the signal names extruded, and finally (iv) we remove the emitted names and initialise the continuations of the present statements.

Feasible reactivity

At the beginning of each instant, a program receives an input that we may represent as a (fresh) thread identifier Env defined by the equation Env By the properties of the model, we may assume without loss of generality that in the input all values emitted on a signal s are distinct.

() = s 1 v 1 | • • • | s n v n .
Definition 1 (computation). A computation of a program P is an infinite and countable sequence of programs P 1 , P 2 , . . . such that

P ≡ P 1 * → P i 1 Env 1 → P i 1 +1 * → P i 2 Env 2 → P i 2 +1 • • •
In general, the reduction of P 1 , P i 1 +1 , P i 2 +1 , . . . may fail to reach the end of the instant. We call reactive the programs that are guaranteed to suspend.

Definition 2 (reactivity).

A program P is reactive if in all computations that start with P , the evaluation at the end of the instant occurs infinitely often.

A(s) | C(s) * → pause.B(s, !s) | νn 0 sn 0 | pause.C(s) Env 1 → B(s, [n 0 ]) | C(s) * → sn 0 | pause.B(s, !s) | νn 1 sn 1 | pause.C(s) Env 2 → B(s, [n 0 ; n 1 ]) | C(s) • • •
In this case, we assume that the input at the beginning of each instant is empty, Env i () = 0 for i = 1, 2, . . .. Note that the order of the signal names in the list ℓ, which is a parameter of the identifier B, is chosen non-deterministically at the beginning of each instant.

We assume that initially a program has the shape

νs(A 1 (v 1 ) | • • • | A n (v n )) (2)
Then, by the definition of the present instruction and the input, a program will have this shape at the beginning of each instant, up to structural equivalence. The definition of feasible reactivity is relative to the size of the initial program and the size of the (largest) input. By convention, the size of a program with the shape (2) is n plus the sum of the sizes of the values v 1 , . . . , v n . The size of an input Env defined by an equation Env =

s 1 v 1 | • • • | s n v n is the size of the list [v 1 ; . . . ; v n ].
Definition 3 (feasible reactivity). A program P of the shape ( 2) is feasibly reactive if there exists a polynomial Q such that for every computation For instance, the program in example 3 fails to be feasibly reactive because the size of the parameter ℓ of the identifier B grows by one every instant.

P ≡ P i 0 +1 * → P i 1 Env 1 → P i 1 +1 * → P i 2 Env 2 → P i 2 +1 • • • if d

Annotations and Constraints Generation

Programs come with a finite system of recursive equations. Our static analysis actually concerns this system and it is independent of the particular program that is used to initialise the computation. The reader should keep in mind that the analysis of a program is actually the analysis of the associated system. We restrict our attention to finite control programs. To this end, we inspect the system of equations and we check that in each equation A(x) = P , P cannot spawn two recursive calls that run in parallel. Also, the static analysis makes abstraction of the actual signal names while keeping track of the region they belong to. It will be convenient to suppose that the program does not contain trivial matchings such as a value matching a pattern ([v ¤ p] P 1 , P 2 ) and the comparison of two identical names ([s = s] P 1 , P 2 ). Such matchings can be removed by a trivial symbolic execution.

Reset annotations and read once condition

We denote with Reset a subset of the thread identifiers containing those thread identifiers that correspond to the beginning of a new 'cycle'. To be in Reset a thread identifier A has to satisfy one of the following conditions: either it is defined by an equation of the shape A(. . .) = pause.K or all its occurrences in the program are in the else branch of a present statement. By these syntactic conditions, we guarantee that the end of a cycle for a given thread always entails the end of its computation for the current instant. For instance, in the example 2, it is natural to assume that Server ∈ Reset and Handle / ∈ Reset. As we have seen, a program may read a signal during an instant with the present statement or at the end of the instant through dereferencing. The read once condition is the hypothesis that for every thread, in every cycle, there is a bound on the number of times the reading of a signal can be performed. Specifically, we require and statically check on the call graph of the program (see below) that the computation performed starting from any thread identifier can execute any given read instruction at most once within a cycle.

1. We assign to every present statement and to every dereferencing in a program a distinct fresh label (a variable), y, and we collect all these labels in an ordered sequence, y 1 , . . . , y m . In the following, we will use the notation s y (x).P, K and ! y s to make the labels explicit. If r is a vector of expressions with dereferenciation, we denote with Lab(r) the finite set of labels that occur in r.

2. With every thread identifier A defined by an equation A(x) = P , we associate a node of the graph. We also introduce a fresh thread identifier O and a related node that plays the role of a sink in the call graph.

3. We define a function Call that takes in input a program and a finite set of labels and produces in output a finite set of pairs composed of a thread identifier and a set of labels. The function Call is defined as follows:

Call (0, L) = {(O, L)} Call (se, L) = {(O, L)} Call (s y (x).P, A(r), L) = Call(P, L ∪ {y}) ∪ {(A, L ∪ Lab(r))} if A / ∈ Reset Call(P, L ∪ {y}) ∪ {(O, L ∪ Lab(r))} otherwise Call (A(e), L) = {(A, L)} if A / ∈ Reset {(O, L)} otherwise Call ([s 1 = s 2 ] P 1 , P 2 , L) = Call (P 1 , L) ∪ Call (P 2 , L) Call ([x ¤ p] P 1 , P 2 , L) = Call (P 1 , L) ∪ Call (P 2 , L) Call (P 1 | P 2 , L) = Call (P 1 , L) ∪ Call (P 2 , L) Call (νs P, L) = Call (P, L)
4. Suppose the identifier A is defined by an equation A(x) = P and that C = Call (P, ∅).

We introduce an edge from A to an identifier B (possibly O) if (B, L) ∈ C. In this case, we label the edge with the set {L | (B, L) ∈ C}.

5. We denote with R(A) the union of the sets of labels of the edges accessible from A and with y A the ordered sequence of labels in R(A).

The definition of Call is such that for every sequence of calls in the execution of a thread within the cycle we can find a corresponding path in the call graph.

Definition 4 (read once condition).

A program satisfies the read once condition if in the call graph there are no loops that go through an edge whose label is a non-empty set.

Note that while the number of reads is bounded by a constant, the amount of information that can be read is not. Thus, for instance, a 'server' thread can just read one signal in which is stored the list of requests produced so far and then it can go on scanning the list and replying to all the requests within the same instant. In the following, we will focus on programs that satisfy the read once condition. For such programs, we introduce for each thread identifier A with parameters x, a fresh thread identifier A + whose parameters are those of A plus the parameters y A that can be read within a cycle. The idea is that the behaviour generated by the thread identifier A within a cycle can be described as a function of its parameters x which are determined at the beginning of the cycle and the values y A of the signals read within the cycle. We will also refer to x as proper parameters and to y A as auxiliary parameters of the identifier A + . Example 5. Consider example 1 and suppose that Cell ∈ Reset marks the end of a cycle and that the label associated with the dereferenciation is y. The graph resulting from the analysis has three nodes {Cell, Send, O} and the following labelled edges: (Cell, ∅, Send), (Send , ∅, Send) and (Send , {y}, O). The program satisfies the read once condition since the only possible loop, namely the one form Send to Send, is composed of edges (just one in this case) whose label is the empty set. Both Send + and Cell + have an auxiliary parameter y.

Next consider example 2 and suppose that Server ∈ Reset and the label associated with the dereferenciation is y. The call graph has three nodes Server, Handle, O and the following labelled edges: (Server , {y}, Handle), (Handle, ∅, Handle), and (Handle, ∅, O). Again the read once condition is satisfied. Server + has an additional parameter y while Handle + has no additional parameter.

Finally, consider example 3 and suppose that A, C ∈ Reset and the label associated with the dereferenciation is y. The graph has four nodes: C, A, B, O and the following labelled edges: (A, {y}, B), (B, ∅, B), (B, ∅, O), and (C, ∅, C). In this case too, the read once condition is satisfied. A + has an additional parameter y while B + and C + have no additional parameter.

Status annotations

We associate a status, either lexicographic (lex) or multi-set (mset), with every thread identifier. We assume that thread identifiers which are equivalent with respect to a preorder ≥ F that we define below have the same arity and the same status. We note that this implies that A + , B + have the same arity too.

To define the pre-order ≥ F , we introduce first a call graph within an instant by modifying the definition given in section 4.1 so that Call(A(e), L) = {(A, L)} and Call (s(x).P, K, L) = Call(P, L). Thus there is an edge from the identifier A to the identifier B if in the definition of A, say A(x) = P , it is possible to call B within the same instant A is called. Second, we build the least pre-order (reflexive and transitive) ≥ F over thread identifiers such that A ≥ F B if there is an edge from A to B in the call graph within an instant. We write A = F B if A ≥ F B and B ≥ F A, and A > F B if A ≥ F B and A = F B. The rank of the thread identifier A, noted rank(A), is the length of the longest chain A > F B > F . . .

Parameter annotations

One of our goals is to control the size of the proper parameters of a thread. However, it is sometimes appropriate to neglect some parameters. For instance, consider the example 2. One of the parameters of the thread identifier Handle is a list ℓ that is read on a signal s whose size is unrelated to the size of the parameter s of the thread identifier Server. We observe that the parameter ℓ is needed by Handle to perform some computation and that this parameter is then neglected at the end of the cycle. We then introduce a mechanism to mask parameters such as ℓ. Let 0 be a fresh constant that stands for a parameter of size 0. If h is a function of arity n and I ⊆ {1, . . . , n} is a subset of its parameters then h(e 1 , . . . , e n ) I is defined as h(e ′ 1 , . . . , e ′ n ) where e ′ i = e i if i ∈ I and e ′ i = 0 otherwise. Intuitively, in h(e 1 , . . . , e n ) I 'we set to 0' all arguments that are not in I. For each thread identifier A defining a behaviour of arity n, we assume a set I A ⊆ {1, . . . , n} with the condition that I A = {1, . . . , n} if A marks the end of a cycle in the program (thus in the latter case, no parameter can be set to 0). Note that the mask acts only on the proper parameters of the identifier A and not on the auxiliary parameters y A corresponding to the values read within a cycle.

Signal annotations

One purpose of the signal annotations is to reject programs such as the one in example 3. Let us consider in particular the thread A. At each instant, this thread re-emits on a signal s the values emitted on the same signal s at the previous instant. We want to reject this kind of behaviour while allowing -under suitable conditions-a slightly different behaviour where a thread emits on a signal s a series of values (possibly the same) that depend on the values emitted on a different signal s ′ at the previous instant. For instance, we want to be able to program a 'server' (cf. example 2) that receives a series of requests at the end of the instant and produces a series of related answers in the following instant. The idea is to partition the signal names into a finite collection of regions. Then regions are ordered and the behaviour of the server described above is allowed if the signal s belongs to a region that is strictly below the region to which s ′ belongs. For instance, in the example 2, we emit on signal s ′ a value which depends on a value read on a signal s. If we admit that this value has arbitrary size then we should require that the signal s is associated with a region smaller than the region associated with s ′ .

Formally, we assume a set of regions R = {ρ 1 , ρ 2 , . . .} with a strict order > R and we denote with rank (ρ) the length of the longest sequence

ρ > R ρ 1 > R • • • > R ρ n .
We assume that every signal type comes with a region annotation Sig ρ (t) so that the type of a signal name also provides the region to which the signal name belongs. In section 4.6, we will rely on these annotations to derive inequalities that guarantee that the size of the values emitted on a signal of region ρ can be bound as a function of the size of the values received on signals belonging to regions of smaller rank.

Inequalities

We rely on the annotations to produce a set of inequalities. We use the notation r for r where each ! y s is replaced with y. Given a system of equations, for each thread identifier A defined by an equation A(x) = P , we compute C i (P, A + (x, y A )), with index i = 0, 1, 2 according to the rules described in table 1. The definition of the functions C i amounts to perform a 'symbolic execution' of the body P of the equation while keeping track of the shape of the parameters x and the values read y A . More precisely, the functions C i explore the finitely many control points of a computation starting with a recursive call to the thread identifier A. At some critical points, namely (i) when a value is emitted, (ii) when a value is received, and (iii) when a recursive call is executed, the functions C i produce certain inequalities whose purpose is discussed next.

Inequalities for termination of the instants

In our model, the only way a computation may fail to be reactive is that a thread goes through a recursive call infinitely often within an instant. To avoid this situation, we have to make sure that whenever the identifiers A 1 , . . . , A n may call each other, a certain wellfounded measure decreases. This is the purpose of the inequalities of index 0. Moreover,

C i (P, A + (p)) = case P of 0 : ∅ [x ¤ p] P 1 , P 2 : C i (P 1 , A + ([p/x]p)) ∪ C i (P 2 , A + (p)) [s 1 = s 2 ]P 1 , P 2 : C i (P 1 , A + (p)) ∪ C i (P 2 , A + (p)) (P 1 | P 2 ) : C i (P 1 , A + (p)) ∪ C i (P 2 , A + (p)) νs P ′ : C i (P ′ , A + (p)) se, i = 0, 1 : ∅ , i = 2 {A + (p) ↓ρ ≥ 2 e} s : Sig ρ (t) B(e), i = 0 : ∅ if A > F B {A + (p) > 0 B + (e, y B )} otherwise , i = 1 : {A + (p) I A ≥ 1 B + (e, y B ) I B } , i = 2 : {A + (p) ↓ρ ≥ 2 B + (e, y B ) ↓ρ | ρ ∈ W(B)} B ∈ Reset ∅ otherwise s y (x).P ′ , B(r), i = 0 : C 0 ([y/x]P ′ , A + (p)) , i = 1 : C 1 ([y/x]P ′ , A + (p)) ∪ {A + (p) I A ≥ 1 B + (r, y B ) I B } , i = 2 : C 2 ([y/x]P ′ , A + (p)) ∪ {A + (p) ↓ρ ≥ 2 B + (r, y B ) ↓ρ | ρ ∈ W(B)} B ∈ Reset ∅ otherwise
Table 1: Inequalities of index 0, 1, 2 the inequalities will be interpreted so as to make sure that a decrement step can only be taken polynomially many times in the size of the values.

Example 6. We rely on the call graphs computed in example 5. For the example 1, we obtain: Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), y) > 0 Send + (s, q, ℓ, ℓ ′′ , y), for the example 2, we obtain: Handle + (s, cons(req(s ′ , x), ℓ ′ )) > 0 Handle + (s, ℓ ′ ), and for the example 3, we obtain:

B + (s, cons(n, ℓ ′ )) > 0 B + (s, ℓ ′ ).

Inequalities for size control at the beginning of a cycle

The purpose of the inequalities of index 1 is to ensure that the size of the parameters of a thread at the beginning of a new cycle is bounded by a function (a polynomial) of the size of the initial parameters of the computation. Of course, a cycle starting with A may span several instants and may go through several recursive calls before a new cycle is started again. For this reason, the invariant we have to maintain concerns all recursive calls both within and at the end of the instant.

Example 7. We rely again on the computation of the call graphs in example 5. For example 1, assuming I Cell = {1, 2, 3} and I Send = {1, 2, 3, 4} we obtain:

Cell + (s, q, ℓ, 0) ≥ 1 Send + (s, q, ℓ, ℓ, 0), Send + (s, q, ℓ, ℓ ′ , 0) ≥ 1 Cell + (s, next(q, y), ℓ, 0), Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), 0) ≥ 1 Send + (s, q, ℓ, ℓ ′′ , 0) .
For example 2, assuming I Server = I Handle = {1} we obtain: Server + (s, 0) ≥ 1 Handle + (s, 0), Handle + (s, 0) ≥ 1 Handle + (s, 0), Handle + (s, 0) ≥ 1 Server + (s, 0) . For example 3, assuming I A = I B = I C = {1}, we obtain:

A + (s, 0) ≥ 1 B + (s, 0), B + (s, 0) ≥ 1 B + (s, 0), B + (s, 0) ≥ 1 A + (s, 0), C + (s) ≥ 1 C + (s) .

Inequalities for size control within a cycle

Finally, the purpose of the inequalities of index 2 is to ensure that the size of any value emitted during a cycle in a given region as well as the number of these emissions within an instant is polynomial in the size of the parameters at the beginning of the cycle, the inputs provided by the environment, and the size of the values read in regions of smaller rank.

1. Given a thread identifier A, we compute an over approximation of the set of regions associated with an output within a cycle starting from A. To this end, we use the call graph defined in section 4.1 and we compute all thread identifiers that are reachable from A within a cycle. Then we inspect the definition of each thread identifier (different from O) and determine the regions associated with the emissions that may arise in the definition. We denote with W ′ (A) this set. Moreover, let ρ ⊤ be a region whose rank is higher than the rank of all the regions used in the program and let W(A) equal {ρ ⊤ } if W ′ (A) = ∅, and W ′ (A) otherwise.

2. Let A be a thread identifier of arity n with auxiliary parameters y A = y 1 , . . . , y m . We can associate with each position 1, . . . , m in the list of auxiliary parameters a unique region γ(i) which is the region associated with the corresponding read instruction. Given a region ρ, we denote with ↓ ρ the set of regions of rank smaller than ρ. In particular, if rank (ρ) = 0 then we ↓ ρ = ∅. Given a set M of regions we introduce the notation A + (p) M for A + (p) I where I = {1, . . . , n} ∪ {n + i | γ(i) ∈ M}. Thus, this amounts to set to 0 all auxiliary parameters whose region is not in M. Note that this masking only affects the auxiliary parameters of the thread identifiers. Cell + (s, q, ℓ, 0) ≥ 2 Send + (s, q, ℓ, ℓ, 0), Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), 0) ≥ 2 Send + (s, q, ℓ, ℓ ′′ , 0), Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), 0) ≥ 2 q .

Next consider example 2, assuming the region ρ of the signal on which the Server receives the requests is below the region ρ ′ of the signals on which it provides an answer. In this case, W(Server ) = W(Handle) = {ρ ′ } and the resulting inequalities are:

Server + (s, y) ≥ 2 Handle + (s, y), Handle + (s, cons(req(s ′ , x), ℓ ′ )) ≥ 2 Handle + (s, ℓ ′ ), Handle + (s, cons(req(s ′ , x), ℓ ′ )) ≥ 2 f (x) .
Finally, consider example 3. Here we have just one signal belonging, say, to a region ρ. In this case, W(A) = W(B) = W(C) = {ρ} and the resulting inequalities are:

A + (s, 0) ≥ 2 B + (s, y), B + (s, cons(n, ℓ ′ )) ≥ 2 B + (s, ℓ ′ ), B + (s, cons(n, ℓ ′ )) ≥ 2 n, C + (s) ≥ 2 C + (s), C + (s) ≥ 2 n .
We anticipate that the inequality A + (s, 0) ≥ 2 B + (s, y) is not going to be satisfiable since A does not depend on y which is a list of arbitrary size.

Assignments and quasi-interpretations

We introduce first the notion of assignment which interprets the inequalities in terms of certain numerical functions. A quasi-interpretation is then an assignment that satisfies the inequalities associated with the program.

Assignments

Let h denote either a constructor c or a function symbol f or a thread identifier A + . An assignment associates with each symbol h of arity n of the program a function q h : N n → N subject to a series of conditions that we specify below.

First we have to introduce some notation. Let E denote a formula which is either an expression e or the application of a thread identifier to expressions A + (e 1 , . . . , e n ). Suppose E contains the variables x 1 , . . . , x n . Once an assignment is fixed, we can associate with E a function over the natural numbers of arity n by defining q x i = x i and q h(e 1 ,...,en) = q h (q e 1 , . . . , q en ). In particular, we note that if v is a value then q v is a numerical constant.

A ground substitution is a substitution that associates values with variables (while respecting the types). Given two formulae E 1 , E 2 , we write q |= E 1 > E 2 (q |= E 1 ≥ E 2 ) if for all ground substitutions σ, q σE 1 > q σE 2 (q σE 1 ≥ q σE 2 ). 1We will also compare vectors of formal expressions. For lexicographic comparison, we write q

|= (E 1 , . . . , E n ) > lex (E ′ 1 , . . . , E ′ n ) if there is an i ≤ n such that q |= E j ≥ E ′ j for j = 1, . . . , i-1 and q |= E i > E ′ i . For multi-set comparison, we write q |= (E 1 , . . . , E n ) > mul (E ′ 1 , . . . , E ′ n )
if for all ground substitutions σ, {|q σE 1 , . . . , q σEn |} > N mset {|q σE ′ 1 , . . . , q σE ′ n |}, where {| . . . |} is our notation for multi-sets and > N mset is the well-founded multi-set order over the finite multi-sets of natural numbers. We notice the following simple combinatorial fact about lexicographic and multi-set orders which is instrumental to establish polynomial time termination.

Lemma 1. Suppose a 1 , . . . , a n , c are natural numbers and a 1 , . . . , a n < c. Then the length of any strictly decreasing sequence of the shape (a 1 , . . . ,

a n ) > lex (b 1 , . . . , b n ) > lex • • • or of the shape {|a 1 , . . . , a n |} > N mset {|b 1 , . . . , b n |} > N mset • • • is bounded by c n .
Definition 5. An assignment should satisfy the following conditions.

(1) If s is a signal name or c is a constructor with arity 0 then q s = q c = 0. Otherwise, if c is a constructor with positive arity n then q c = d c + Σ i=1,...,n x i for some natural number d c ≥ 1.

(2) For all symbols h of arity n it holds that: (i) q |= h(x 1 , . . . , x n ) ≥ x i for i = 1, . . . , n and (ii) q h is monotonic, i.e., a j ≥ b j for j = 1, . . . , n implies q h (a 1 , . . . , a n ) ≥ q h (b 1 , . . . , b n ).

(3) Let f be a function symbol of arity n.

Then f (v 1 , . . . , v n ) ⇓ v implies that q f (v 1 ,...,vn) ≥ q v .
It follows from condition (1) that there is a constant k ≥ 1 (that can be taken as the largest additive constant d c ) such that for any value v, |v| ≤ q v ≤ k • |v|. Also note that condition (1) implies condition (2) for constructors.

The definition of an assignment q ensures that σe ⇓ v implies q σe ≥ q v . We say that a function U : N → N bounds the assignment q if for all symbols h and all natural numbers n it holds that q h (n, . . . , n) ≤ U(n). We say that an assignment is polynomially bounded if it can be bound by a function U which is a polynomial. In the following, we will restrict our attention to polynomially bounded assignments.

Quasi-interpretations

A quasi-interpretation is a polynomially bounded assignment which satisfies the constraints of index 0, 1, 2.

Definition 6 (quasi-interpretation). An assignment q is a quasi-interpretations if:

(1) For all constraints of the shape A + (p 1 , . . . , p n ) > 0 B + (e 1 , . . . , e n ) where A = F B, with status st, we have:

q |= (p 1 , . . . , p n ) > st (e 1 , . . . , e n ) .
(2) For all constraints of the shape A + (p 1 , . . . , p n ) ≥ i B + (e 1 , . . . , e m ) (i = 1, 2) and A + (p 1 , . . . , p n ) ≥ 2 e we have:

q |= A + (p 1 , . . . , p n ) ≥ B + (e 1 , .
. . , e m ) and q |= A + (p 1 , . . . , p n ) ≥ e .

Example 9.

Consider example 1 and assume that we attribute the lexicographic status to Cell and Send. We note that Cell > F Send . The inequality of index 0 is satisfied because the quasi-interpretation of cons(s ′ , ℓ ′′ ) is always strictly larger than the quasi-interpretation of ℓ ′′ . To satisfy the remaining inequalities of index 1, 2 it suffices to interpret Cell + and Send + as the maximum function, noticing that next(q, y) is always a state which is represented by a constant of size 0.

Next, consider example 2 and assume lexicographic status for the thread identifiers. We note that Handle > F Server. Again the inequality of index 0 is satisfied because the quasiinterpretation of cons(req(s ′ , x), ℓ ′ ) is always larger than the quasi-interpretation of ℓ ′ . To satisfy the inequalities of index 1, 2, 3 it suffices to suppose that the quasi-interpretation of Handle + and Server + is a function g : N 2 → N such that g(0, x) is pointwise larger than the quasi-interpretation of the function f . Finally, consider example 3. We note that A > F B. We can satisfy the inequalities of index 0, 1 but as anticipated there is no way the inequality A + (s, 0) ≥ 2 B + (s, y) can be satisfied since y ranges over lists of arbitrary size.

We can now state our main result whose proof will be discussed in the following section 5.

Theorem 1. A program that admits a polynomial quasi-interpretation is feasibly reactive.

Proofs outline

We are given a finite system of recursive equations. The initial configuration of a program relatively to such a system has the shape: R = νs

(A 1 (v 1 ) | • • • | A n (v n ))
. Since we have assumed that the system is finite control during the computation we will have at most n main parallel threads plus a variable number of auxiliary threads that may just branch and emit signals and that disappear at the end of each instant. Of course one of our goals is to show that this variable number of threads can be polynomially bounded.

Lemma 2. Let R be a program admitting a polynomial quasi-interpretation. There is a polynomial Q(x) such that if c bounds the size of R, the size of the inputs, and the sizes of the parameters of all calls within a given instant then the program in that instant will suspend in time less than Q(c).

The computation performed by the program is simply the interleaving of the computations performed by the n main threads. It is clear that the computation a thread may perform within an instant before running a recursive call is polynomially bounded in c. Thus it is enough to show that each thread may perform at most polynomially many recursive calls before suspending and to this end we rely on the inequalities of index 0 and the lemma 1. Note that the size and the number of the values emitted during the instant is polynomial in c and that therefore their concatenation in a list has size polynomial in c too. We anticipate that the proof we have sketched of the lemma 2 actually shows that each thread whose parameters and inputs are bound by c will suspend in time polynomial in c. Lemma 3. Let R be a program admitting a polynomial quasi-interpretation. There is a polynomial Q(x) such that if c bounds the size of R and A ∈ Reset then, in all computations of R, the sizes of the parameters in every call to A are bounded by Q(c).

The inequalities of index 1 guarantee that a computation that starts with B(v) will have the property that B(v) will 'dominate' (up to quasi-interpretation and modulo the parameter annotations) all the following calls A(u) including those that correspond to a reset point and in this case all parameters of the call are taken into account by the definition of I A . Lemma 4. Let R be a program admitting a polynomial quasi-interpretation. There exists a polynomial Q(x) such that in every computation

R ≡ R i 0 +1 * → R i 1 Env 1 → R i 1 +1 * → R i 2 Env 2 → R i 2 +1 . . .
if c bounds the size of R and of the inputs Env 1 , . . . , Env k for k ≥ 0 then the size of every value computed within the instant k is bounded by Q(c).

First of all we show by induction on the rank of a region that the size of every value computed in that region is polynomial in c.

If the region ρ has rank 0 the inequalities of index 2 (in the case where all auxiliary parameters are set to 0) guarantee that (i) the size of an emitted value and (ii) the size of a parameter in a recursive call to a thread identifier that may emit on the region ρ is polynomial in the parameters at the beginning of a cycle. Now, by lemma 3, the size of the parameters at the beginning of a cycle is polynomial in c. Thus from (the proof of) lemma 2, we can derive that the number of values emitted is polynomial in c. We can then conclude that all the values emitted or computed at the end of the instant by list concatenation have a size that is polynomial in c.

Next suppose the region ρ has rank greater than 0. This time the inequalities of index 2 (in the case where we restrict the auxiliary parameters to those that depend on regions of rank strictly smaller than ρ) guarantee that (i) the size of an emitted value and (ii) the size of a parameter in a recursive call to a thread identifier that may emit on the region ρ, is polynomial in the size of the parameters at the beginning of a cycle and the values read from regions strictly smaller than ρ. Using the fact that the composition of polynomials is again a polynomial we can appeal again to lemmas 2 and 3 to conclude that all values emitted or computed at the end of the instant by list concatenation in the region ρ have a size that is polynomial in c.

There is one situation that remains to be considered. The computation may reach a thread identifier that that does not emit any value within its current cycle. By lemma 2, it is enough to make sure that the size of its parameters is polynomial in c. This is guaranteed again by the inequalities of index 2 since by convention a region with the largest rank is in W(B).

Thus we have shown that the size of the values is polynomial in the size of the initial configuration and the size of the largest input. By applying again lemma 2 we can conclude that the program is feasibly reactive.

Conclusion

We have introduced the property of feasible reactivity in the context of a synchronous π-calculus and we have provided static conditions that enforce it. The read-once condition builds on the cyclic behaviour of typical synchronous applications and allows to regard each thread as a function of its parameters and of the finitely many inputs it receives within a cycle. Reactivity is obtained as usual through a well-founded measure. In our case, this measure is tuned so as to ensure termination in time polynomial in the size of the values. Feasible reactivity requires that we control both the number and the size of the threads. This is achieved in particular by requiring that each thread at the beginning of a cyle is non-size increasing. To escape certain circular situations, a final condition requires a stratification of the signals in regions so that, intuitively, a value emitted on a certain region can be polynomially bounded in the size of the values read in lower regions.

Various directions for further research can be mentioned. First, it is clear that an automatisation of our approach relies on the possibility of synthesizing quasi-interpretations. Preliminaries experiences suggest that quasi-interpretations are not too hard to find in practice (see, e.g., [START_REF] Amadio | Synthesis of max-plus quasi-interpretations[END_REF]), but it remains to be seen whether this approach scales up to large programs. Second, one might wonder whether the read-once condition can be dropped. Currently, it plays an essential role in the proofs and its eventual removal seems to require new ideas on the abstraction of threads' execution. Third, our analysis is tailored towards the synchronous model and a signal based interaction mechanism. It remains to be seen whether similar analyses could be performed on different models of concurrent threads. For instance a model based on shared references and possibly asynchronous execution. a signal name of the same type with s. Following this operation, we remove all name generation instructions νs. As for the operation [s 1 = s 2 ]P 1 , P 2 that compares signal names, we will simply disregard it and systematically explore the situations where one of the programs P 1 or P 2 is executed. This is like replacing a conditional [s 1 = s 2 ]P 1 , P 2 with an internal choice P 1 ⊕ P 2 .

B.2 Abstracting pattern matching

Consider a pattern matching instruction [x ¤ p] P 1 , P 2 . As in the name comparison operation, we will systematically consider the situations where P 1 or P 2 are executed. However, in the case where the first branch P 1 is selected, we will remember that x must match the pattern p.

B.3 Abstracting the input

In section 4, we have associated a distinct label (a variable) y with every input. We rely on this variable to compute 'abstractly' beyond an input. Namely, in the input operations, say, s y (x).P, A(f (! y ′ s ′ )) we will consider both the possibility where a signal is received on s and the computation continues within the instant with [y/x]P and the possibility that the computation suspends and resumes in the following instant with A(f (y ′ )).

B.4 Rewriting rules

We will rely on rewriting rules of the shape

A + (p) → se (3)
to express the situation where the thread identifier A with parameters and inputs that match the patterns p emits within the same instant the value resulting from the evaluation of the expression e on the signal s.

We will also rely on rewriting rules of the shape:

A + (p) Y T (4)
to describe the situation where the thread identifier A with parameters and inputs that match the patterns p evolves into a continuation T . Here, the reduction symbol Y can be either → or → with the convention that we use → to describe a situation where the continuation T runs in the same instant and → to describe a situation where the continuation T runs in the following instant. Moreover, the continuation T can have two shapes:

• Either B / ∈ Reset, T = B + (e, y B ), and p = p ′ , y B ,

• or B ∈ Reset and T = λy B .B + (e, y B ).

For example 2, we derive:

Server + (s, y) → Handle + (s, y) Handle + (s, cons(req(s ′ , x), ℓ ′ )) → Handle + (s, ℓ ′ ) Handle + (s, cons(req(s ′ , x), ℓ ′ )) → s ′ f (x)
Handle + (s, ℓ) → λy.Server + (s, y)

Finally, for example 3, we derive:

A + (s, y) → B + (s, y) B + (s, cons(n, ℓ ′ )) → sn B + (s, cons(n, ℓ ′ )) → B + (s, ℓ ′ ) B + (s, ℓ) → λy.A + (s, y) C + (s) → sn C + (s) → λ().C + (s)
Remark 1. The reader might have noticed that the rewriting rules and the inequalities we have produced do not keep track of events that can happen in parallel like "emitting two signals and calling another thread". This information can be neglected because we have assumed we are handling finite control programs. In such programs a call to an identifier A may generate at most one call to another thread identifier (either in the current instant or in the following one) plus a number of emissions that is bounded by a constant that depends on the size of the program only. Alternatively, we could have considered rewriting rules such as:

A + (p) → s 1 e 1 s 2 e 2 B + (e, y B )
where the right hand side carries a composition operator to express the parallelism of the events. We note that this approach may produce exponentially more rules than the previous one because one needs to distribute the parallel composition through the non-determinism.

C Analysis

We proceed to an analysis of the abstracted system, i.e., of the term rewriting system. Table 2 summarizes the inequalities that are associated with each kind of term rewriting rule.

A term rewriting rule describes a family of ground rewriting rules which is obtained by replacing the variables with ground substitutions σ and by evaluating the ground expressions according to the evaluation axioms. We write

A + (v) R1 → sv
if there is a term rewriting rule A + (p) → se and a ground substitution σ such that σp = v and σe ⇓ v. In a similar way, we write

A + (v, u) R2 → B + (v ′ , u) (or A + (v, u) R4 → B + (v ′ , u) )
if there is a term rewriting rule Consider a ground rewriting rule representing a computation step. As we have seen this rule is an instance of a term rewriting rule. In turn, we have associated a set of inequalities with every term rewriting rule. Let us now assume we have an assignment q that satisfies all generated inequalities. Table 3 spells out what this means in terms of the ground rewriting rule. To this end, we need some notation to distinguish the parameters e of a thread identifier A + (remember that a list of variables y B or a list of patterns p is also a list of expressions and that r is a list of expressions too since, by definition, the dereferenced signals are replaced by variables). We distinguish between proper parameters and auxiliary parameters (those corresponding to an input). Among the former, we distinguish those in the set I A (e I A ) and the others (e I A ). Among the latter, for a given region ρ, we distinguish those whose rank is smaller than ρ (e ↓ρ ) and the others (e ↓ρ ). To summarise, given a list of parameters e and a region ρ, we can always partition it into four parts: e = e I A , e I A , e ↓ρ , e ↓ρ .

We also notice that A + (e, y A ) I A = A + (e, 0) I A since by definition all auxiliary parameters are set to 0. Moreover, if A is a reset point then A + (e, 0) I A = A + (e, 0) since for the reset points, I A coincides with the proper parameters. Finally, we recall that the restriction ↓ ρ acts only on the auxiliary parameters.

C.1 Proof of lemma 2

We analyse ground reductions of the shape:

A + 1 (v 1 ) R2 → • • • R2 → A + k (v k )
These reductions correspond to a sequence of recursive calls that happen within the same instant (and the same cycle). Suppose the maximum arity of a thread identifier A + in a given program is n. Moreover, suppose c is a bound on the size of the values v j for j = 1, . . . , k. Then the length k of the reduction sequence is O(c n ). To see this, notice that A i ≥ F A i+1 for i = 1, . . . k -1. The inequality ≥ F can be strict at most a constant number of times that depends on the program. Thus, it suffices to prove the assertion when A i = F A i+1 , for i = 1, . . . , k -1 knowing that the thread identifiers have the same status st and the same arity n. By the existence of a quasi interpretation q (case (R2) in table 3), we have:

q |= v 1 > st v 2 > st • • • > st v k
By the properties of assignments, we know that the interpretation of a value is proportional to its size. Thus we can conclude by applying lemma 1.

C.2 Proof of lemma 3

We analyse ground reductions of the shape:

A + 1 (v 1 ) Y • • • Y A + n (v n ) Y λy A n+1 .A + n+1 (v, y A n+1 )
where A 1 ∈ Reset, Y∈ {→, →}, and the last reduction is optional. These reductions correspond to a sequence of recursive calls that start with a reset point and continue within a cycle (but may span several instants). Optionally, these reductions may reach another reset point. Let us denote with (v j ) I A j the parameters whose indexes correspond to I A j . Recall that if B is a reset point then I B coincides with the proper parameters. By the cases (R2) and (R4) in table 3 we have:

q |= A + 1 ((v 1 ) I A 1 , 0) ≥ • • • ≥ A + n ((v n ) I An , 0) .
Moreover, at the last optional step, by inspection of the cases (R2) and (R4) in table 3, we deduce: q |= A + n ((v n ) I An , 0) ≥ A + n+1 (v, 0) . In other terms, we know that if starting from a call A(v) we arrive at a call B(u) then q |= A + (v, 0) ≥ B + ((u) I B , 0). In particular, we see that, up to the quasi-interpretation, the initial configuration A(v) dominates all the following configurations at the beginning of a cycle.

C.3 Proof of lemma 4

We analyse ground reductions of the shape:

A + 1 (v 1 ) Y • • • Y A + n (v n ) R1 → sv
where A 1 ∈ Reset, Y∈ {→, →}, ρ ∈ W(A n ), and the last reduction R1 is optional with s also belonging to region ρ.

Example 4 .

 4 With reference to the example 3, a possible computation of the program A(s) | C(s) is as follows:

Example 8 .

 8 Consider example 1, assuming all the signals on which the automata interact belong to the same region ρ. In this case, W(Cell ) = W(Send ) = {ρ} and the resulting inequalities are:

  A + (p, y B ) → B + (e, y B ) (or A + (p, y B ) → B + (r, y B )) and a ground substitution σ such that σp = v, σy B = u, and σe ⇓ v ′ (or σr ⇓ v ′ ). Finally, we writeA + (v) R3 → λy B .B + (v ′ , y B ) (or A + (v) R5 → λy B .B + (v ′ , y B ) ) A + (p) → se, s : Sig ρ (t) A + (p) ↓ρ ≥ 2 e (R2) A + (p, y B ) → B + (e, y B )    A + (p, y B ) > 0 B + (e, y B ) if A = F B A + (p, 0) I A ≥ 1 B + (e, 0) I B A + (p, y B ) ↓ρ ≥ 2 B + (e, y B ) ↓ρ if ρ ∈ W(B) (R3) A + (p) → λy B .B + (e, y B ) A + (p) I A ≥ 1 B + (e, 0) (R4) A + (p, y B ) → B + (r, y B ) A + (p, 0) I A ≥ 1 B + (r, 0) I B A + (p, y B ) ↓ρ ≥ 2 B + (r, y B ) ↓ρ if ρ ∈ W(B) (R5) A + (p) → λy B .B + (r, y B ) A + (p) I A ≥ 1 B + (r, 0)Table 2: Inequalities associated with the term rewriting rules if there is a term rewriting rule A + (p) → λy B .B + (e, y B ) (or A + (p) → λy B .B + (r, y B )) and a ground substitution σ such that σp = v, and σe ⇓ v ′ (or σr ⇓ v ′ ).

  As in the π-calculus, signal names stand both for signal constants as generated by the ν operator and signal variables as in the formal parameter of the present operator. Variables Var include signal names as well as variables of other types. Constructors Cnst include * , nil, and cons. Values Val are terms built out of constructors and signal names. The size of a value |v| is defined as |s| = |c| = 0 if c is a constant, and |c(v 1 , . . . , v n

	Val , . . . , Val)	(values v, v ′ , . . .)
	Pat ::= Var | | Cnst(Pat, . . . , Pat)	(patterns p, p ′ , . . .)
	Fun ::= f | | g | | • • •	(first-order function symbols)
	Exp ::= Var | | Cnst(Exp, . . . , Exp) | | Fun(Exp, . . . , Exp) (expressions e, e ′ , . . .)
	Rexp ::= !Sig | | Var | | Cnst(Rexp, . . . , Rexp) | |
	Fun(Rexp, . . . , Rexp)	(exp. with deref. r, r ′ , . . .)

  Types include the basic type 1 inhabited by the constant * and, assuming t is a type, the type Sig(t) of signals carrying values of type t, and the type list(t) of lists of values of type t with constructors nil and cons. In the examples, it will be convenient to abbreviate cons(v 1 , . . . , cons(v n , nil) . . .) with [v 1 ; . . . ; v n ]. 1 and list(t) are examples of inductive types.

  bounds the size of P and the sizes of Env 1 , . . . , Env k for k ≥ 1 then (i) P i k +1 (the program at the beginning of the instant k) has size bounded by Q(d) and (ii) it is guaranteed to suspend in time less than Q(d),

Sometimes, a stronger definition of satisfaction is considered that requires e.g., q E1 ≥ q E2 where q E1 , q E2 are regarded as functions over the natural numbers. We prefer the definition based on ground substitutions because it allows to exploit some information on the data size. For instance, we may satisfy a constraint f (x) ≥ c(x, y) if we know that all the values that may replace y have bounded size. On the other hand, with the stronger definition such constraint cannot be satisfied.

* Work partially supported by ACI CRISS and ANR-06-SETI-010-02.

A Proof of lemma 1

Suppose a n-1 , . . . , a 0 are natural numbers strictly smaller than a constant c. We define B lex (a n-1 , . . . , a 0 )(c) = Σ i=0,...,n-1 a i c i which is simply the value in base c of the sequence (a n-1 , . . . , a 0 ). We also define B mset (a n-1 , . . . , a 0 )(c) = Σ i=0,...,n-1 a π(i) c i where π is a permutation over {0, . . . , n -1} such that a π(0) ≤ • • • ≤ a π(n-1) . The permutation π is not uniquely determined but the definition of B mset does not depend on its choice. Now suppose a n-1 , . . . , a 0 , b n-1 , . . . , b 0 are natural numbers strictly smaller than a constant c and note that B st (a n-1 , . . . , a 0 )(c) < c n for st ∈ {lex , mset}. If (a n-1 , . . . , a 0 ) > lex (b n-1 , . . . , b 0 ) then clearly B lex (a n-1 , . . . , a 0 )(c) > B lex (b n-1 , . . . , b 0 )(c). Therefore, the length of a decreasing sequence with respect to the lexicographic order is bounded by c n .

On the other hand, suppose

. By definition of the multi-set order, we know that there is a non-empty multisubset of M whose largest element is, say, a which is replaced in N by another multi-set (with the same cardinality) whose largest element is strictly smaller than a. For instance, {|1, 2, 5, 5, 5, 7|} > mset {|4, 4, 4, 4, 5, 7|} and {|1, 2, 5, 5|} is replaced by {|4, 4, 4, 4|}. Then for some k ∈ {0, . . . , n-1} we have:

If follows that B mset (a n-1 , . . . , a 0 )(c) > B mset (b n-1 , . . . , b 0 )(c) and again the length of a decreasing sequence with respect to the multi-set order is bounded by c n .

B Abstraction

We are given a finite system of recursive equations. Our goal is to analyse the possible computations of a program whose initial shape is

. We will assume that initially all thread identifiers are reset points, i.e., A 1 , . . . , A n ∈ Reset. We will proceed in two steps. First, we will abstract the program (the system of equations, actually) as a term-rewriting system. Second, we will show that the inequalities we have produced in table 1 guarantee feasible reactivity for the abstracted system and therefore for the concrete one.

B.1 Abstracting signal names

The only information we will keep of a signal name is its type Sig ρ (t). Thus we know its region ρ and the type of the values it may carry. Formally, we select a distinct canonical constant, say s, for every type Sig ρ (t) and replace in the program every occurrence of Thus the rule ( 4) is declined into four cases: the continuation T can run in the same instant or not and it can be a reset point or not.

Here the notation e, y B (or p ′ , y B ) should be understood with a grain of salt. We just mean that the parameters can be partitioned into two groups one of which corresponds to the auxiliary variables of the thread identifier B; the parameters y B do not necessarily follow the others. In case y B is empty, we will take the convention that λy B is a dummy abstraction. As usual in term-rewriting, it is assumed that the variables free in the emitted expression e or the continuation T are contained in the variables in the patterns p (recalling that the abstraction of a signal name is treated as a constant).

B.5 Generating the rewriting rules

Given a finite system of recursive equations, the computation of the term rewriting rules follows quite closely the generation of the inequalities described in table 1. Namely for each equation A(x) = P we compute the function R(P, A + (x, y A )) which is defined on the structure of P as follows:

νs P ′ : R(P ′ , A + (p))

Here the abstracted variables λy B are supposed to be fresh. Also note that by the shape of the rules we can never rewrite an emission se or an abstraction such as λy B .B + (e, y B ) since these terms never match the left-hand side of a rule.

Example 10. We compute the term rewriting rules associated with our running examples. For example 1, we derive: Cell + (s, q, ℓ, y) → Send + (s, q, ℓ, ℓ, y) Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), y) → Send + (s, q, ℓ, ℓ ′′ , y) Send + (s, q, ℓ, cons(s ′ , ℓ ′′ ), y) → s ′ q Send + (s, q, ℓ, ℓ ′ , y) → λy ′ .Cell + (s, next(q, y), ℓ, y ′ ) (R1)

Table 3: What the quasi-interpretation guarantees of a ground rewriting step These reductions correspond to a sequence of recursive calls that start with a reset point and continue within a cycle (but may span several instants). Optionally, these reductions may reach a point where a value is emitted.

Let c be a bound on the size of the parameters at the beginning of the computation and the size of the values emitted by the environment at the beginning of an instant. Each vector v j can be decomposed in v ′ j , v ′′ j where v ′′ j correspond to the auxiliary parameters on regions whose rank is not smaller than ρ's. Applying cases (R 1 ), (R2) and (R4) in table 3, we deduce:

Property A The size of the emitted value v is polynomial in c and the size of the values read in regions whose rank is smaller than ρ's.

How many times can a value be emitted on a region ρ within an instant? Between two calls, a thread can only emit a number of messages which is bounded by a constant. Therefore, as in lemma 2, it is enough to focus on the length of computations that happen within an instant. We focus on ground reductions of the shape:

and ρ ∈ W(A j ), for j = k, . . . , n.

These reductions are a particular case of those considered above, where we suppose that after an initial sequence of recursive calls the computation reaches a series of calls among thread identifiers that can mutually call each other. Let u be the arguments that correspond to the auxiliary parameters of A + j for j = k, . . . , n. Each vector v j can be decomposed in v ′ j , u for j = 1, . . . , n. Applying cases (R2) and (R4) in table 3, we deduce:

Property B The parameters v ′ j for j = k, . . . , n are polynomial in c and the size of values read in regions whose rank is smaller than ρ's.

Remember that by construction there is always a region ρ in W(A k ). Therefore, property B guarantees that the size of the proper parameters of a call to a thread identifier is under control. Now, applying case (R2) in table 3, we deduce:

Because the values u are constant, we are forced to decrease the parameters v ′ j with respect to the status st. By Property B, these parameters are polynomial in c and the size of the values read in regions whose rank is smaller than ρ's. By lemma 2, we know that the length of the sequence is polynomial in the size of the largest parameter. Thus we compose the polynomials to obtain the following.

Property C The number of times a value can be emitted within an instant in a region ρ is polynomial in c and the size of values read in regions whose rank is smaller than ρ's.

It remains to analyse how in our model the size of the values read from a region depends on the size of the values emitted in that region. We have the following property.

Property D The values read from a region ρ are the concatenation of some of the values emitted in the region ρ within the same instant.

We can now proceed by induction on the rank of region ρ to show that the size of the concatenation of some of the values emitted in the region ρ is polynomial in c. At rank 0, we use directly properties A and C noticing that the concatenation of polynomially many values whose size is polynomial in c produces a value which is again polynomial in c. At rank n + 1, we use again properties A and C and the inductive hypothesis. Obviously the degree of the polynomial will depend on the highest rank of a region which depends on the program only.

C.4 Proof of theorem 1

We can now conclude our proof. Since the size of the computed values is polynomial in c, we can apply lemma 2 and derive that each instant terminates in time polynomial in c. Thus the existence of a quasi-interpretation entails feasible reactivity.