Page 1

Calculating Polynomial Runtime Properties

Hugh Anderson, Siau-Cheng Khoo, Stefan Andrei and Beatrice Luca

Department of Computer Science

School of Computing

National University of Singapore

{hugh,khoosc,andrei,lucabeat}@comp.nus.edu.sg

Abstract. Affine size-change analysis has been used for termination

analysis of eager functional programming languages. The same style of

analysis is also capable of compactly recording and calculating other

properties of programs, including their runtime, maximum stack depth,

and (relative) path time costs. In this paper we show how precise poly-

nomial bounds on such costs may be calculated on programs, by a char-

acterization as a problem in quantifier elimination. The technique is de-

cidable, and complete for a class of size-change terminating programs

with limited-degree polynomial costs. An extension to the technique al-

lows the calculation of some classes of exponential-cost programs. We

demonstrate the new technique by recording the calculation in numbers-

of-function (or procedure) calls for a simple definition language, but it

can also be applied to functional and imperative languages. The tech-

nique is automated within the reduce computer algebra system.

1Introduction

Polynomial runtime properties are considered essential in many applications.

The ability to calculate such properties statically and precisely will contribute

significantly to the analysis of complex systems. In real-time systems, the time-

cost of a function or procedure may be critical for the correct operation of a

system, and may need to be calculated for validation of the correct operation of

the system. For example, a device-driver may need to respond to some device

state change within a specified amount of time.

In other applications, the maximum stack usage may also be critical in (for

example) embedded systems. In these systems, the memory available to a process

may have severe limitations, and if these limits are exceeded the behaviour of

the embedded system may be unpredictable. An analysis which identifies the

maximum depth of nesting of function or procedure calls can solve this problem,

as the system developer can make just this amount of stack available.

Page 2

A third motivation for calculating polynomial runtime properties is to calculate

more precise relative costs of the individual calls. For example in a flow analysis

of a program we may be interested in which calls are used most often, with

a view to restructuring a program for efficiency. In this scenario, the relative

costs between the individual calls is of interest. In the gcc compiler, a static

branch predictor [2] uses heuristics to restructure the program code, optimizing

the location of code for a branch more likely to occur. The approach described

here can calculate more precise relative costs to improve these heuristics.

In this paper we explore the automatic calculation of each of these costs through

static analysis of the source of programs which are known to be affine size-change

terminating [1,13], where the focus is on recording parameter size-changes only.

The overall approach has three steps:

1. Assume a (degree k) polynomial upper bound related to the runtime or space

cost. The polynomial variables are the parameter sizes.

2. Derive from the source a set of equations constrained by this upper bound.

3. Solve the equations to derive the precise runtime.

If the equations reduce to a vacuous result, then the original assumption of the

degree of the polynomial must have been incorrect, and we repeat the process

with a degree k + 1 assumption. This technique is surprisingly useful, and it is

possible to derive precise runtime bounds on non-trivial programs.

We can also calculate the time or space costs for a subclass of exponential costs,

in particular those of the form φ1· Kφ2+ φ3 where φ1, φ2 and φ3 are each a

limited-degree polynomial in the parameter sizes, and K ∈ ? is a constant.

There has been some research into run-time analysis for functional programs.

For example, [16] explores a technique to evaluate a program’s execution costs

through the construction of recurrences which compute the time-complexity of

expressions in functional languages. It focuses on developing a calculus for costs,

and does not provide automated calculations. In [7], Grobauer explores the use

of recurrences to evaluate a DML program’s execution costs. Our focus is more

with decidability aspects and precise time-costs than either of these approaches.

An alternative approach is to limit the language in some way to ensure a certain

run-time complexity. For example, in [8], Hofmann proposes a restricted type

system which ensures that all definable functions may be computed in polynomial

time. The system uses inductive datatypes and recursion operators. In our work,

we generate time and stack costs of arbitrary functions or procedures, through

analysis of the derived size-change information. A compact summary of a general

technique for the calculation of time and space efficiency is found in the book [15]

by Van Roy and Haridi, where recurrence relations are used to model the costs

of the language elements of the programming language. There is unfortunately

no general solution for an arbitrary set of recurrence relations, and in practice

components of the costs are ignored, capturing at each stage only the most costly

recurrence, and leading to big-O analysis.

2

Page 3

Our paper improves the technique for a specific class of functions, calculating

more precise bounds than those derived from big-O analysis. By exploiting a-

priori knowledge that a particular function terminates, and that the (polynomial)

degree of the particular function is bounded, we can derive a decidable formula,

the solution of which gives the time or space cost of the program.

In the approach presented here, we measure runtime in terms of the number of

calls to each procedure in a simple definition language. This is an appropriate

measure, as the language does not support iteration constructs, and recursive

application of procedures is the only way to construct iteration. Note that this

approach does not restrict the applicability of the technique. Any iteration con-

struct can be expressed as a recursion with some simple source transformation.

In Section 2, preliminary concepts and definitions are introduced. In Section

3, the framework used for constructing the equations is introduced, along with

practical techniques that may be used to solve the equations. In Section 4, we

show examples of relative time costs for compiler optimization, and calculation

of stack depth. In Section 5, we use recurrence relations to indicate how to

classify costs into polynomial or exponential forms. In Section 6, exponential

cost calculations are explored. We conclude in Section 7.

2Preliminaries

v

f,g,h ∈ PName

n

∈ Z

β

∈ Guard

∈ Var

?Variables?

?Procedure names?

?Integer constants?

?Boolean expressions?

β ::= δ | ¬β | β1∨ β2 | β1∧ β2

δ ::= True | False | e1 = e2 | e1 ?= e2 | e1 < e2 | e1 > e2 | e1 ≤ e2 | e1 ≥ e2

∈ AExp

e ::= n | v | n ? e | e1+ e2 | −e

∈ Stat

s ::= if β then s1 else s2 | s1;s2 | f(e1,...,en) | ~

∈ Decl

d ::= f (x1, ... ,xn) = s;

Table 1. The language syntax

e

?Expressions?

s

?Statements?

d

?Definitions?

The language is a simple procedural language, defined in Table 1. This language

is in some sense an abstract language, omitting any parts not relevant to the

runtime. In addition, the expressions are given as if they were all integer values,

when in fact they refer to expressions based on the size of the data types of

the language. For example, a list may be represented here by a size integer

representing the length of the list, and list concatenation represented by addition

of the size values. Finally, an important point is that the language only admits

affine relations between the program variables and expressions.

3

Page 4

2.1Runtime analysis

In the process of performing size-change termination analysis described in [14],

arbitrary sets of functions are processed, constructing a finite set of idempo-

tent SCGs (Size-Change Graphs). These SCGs characterize the function, and

detail all the ways in which a particular function entry point may be re-entered.

In the following description, the functions are all derived from an affine SCT

(Size-Change Termination) analysis [1,13], and hence are known to terminate.

A subclass of these functions in which argument size-changes are linear, termed

LA-SCT (Linear-affine SCT programs) define the class of programs analysed

here. Limiting our analysis to this class of functions is not a severe restriction,

as most useful size-change parameter changes would be linear.

We begin by formally defining the runtime of such functions. The term ¯ y refers

to the vector (y1,...,yn). For the sake of notational brevity, we use a contextual

notation to represent an expression containing at most one function call. For an

expression containing a function call f(¯ y), the corresponding contextual notation

is C[f(¯ y)]. For an expression containing no call, the corresponding contextual

notation is C[].

Definition 1. Given an LA-SCT program p with program parameters ¯ x and

body ep and input arguments ¯ n, the runtime of p, B(p)[¯ n/¯ x], is defined by the

runtime of epinductively as follows:

B(s1;s2)[¯ n/¯ x]

B(ifg thens1elses2)[¯ n/¯ x]

B(C[])[¯ n/¯ x]

B(C[f(¯ m)])[¯ n/¯ x]

In practical terms, this indicates that we are counting function calls as a measure

of runtime. Such calls are the only difficult part of a runtime calculation, as other

program constructs add constant time delays. To clarify this presentation, we

choose to limit the definition to the analysis of function calls as a measure of

runtime.

In the case of a function f(¯ x) containing only a direct call h(¯ y), where ¯ y = ¯ x[ψ],

[ψ] = [y1 ?→ δ1(x1,x2,...),y2 ?→ δ2(x1,x2,...),...] and δ1, δ2 represent affine

relations over the input parameters, we have:

def

= B(s1)[¯ n/¯ x] + B(s2)[¯ n/¯ x]

def

= if g[¯ n/¯ x]thenB(s1)[¯ n/¯ x]elseB(s2)[¯ n/¯ x]

def

= 0

def

= B(ef)[¯ m/¯ y] + 1(whereefisthebodyof f(¯ y))

B(f(¯ x)) = B(h(¯ x[ψ])) + 1

We are primarily interested in runtimes that can be expressed as a polynomial

in the parameter variables.

Definition 2. The degree-k polynomial runtime Bk(p) of an LA-SCT program

p with m parameters x = x1,...,xm is a multivariate degree-k polynomial ex-

pression:

Bk(p)

def

= c1xk

1+ c2xk

2+ ... + cmxk

m+ cm+1xk−1

1

x2+ ... + cn

where c1...cn∈ Q, and Bk(p) is the runtime of the program.

4

Page 5

An example of such a degree-2 polynomial runtime for a program p(x,y) is

B2(p) = x +1

2y2+3

2y

Lastly, we differentiate between an assumption A(p) of the runtime of a program

p, and the actual runtime B(p).

Definition 3. An assumption A(p) of a polynomial runtime of an LA-SCT pro-

gram p with m parameters x = x1,...,xmis a multivariate polynomial expres-

sion:

A(p)= c1xk

where c1...cnare unknown. A(p) contains all possible terms of degree at most

k formed by the product of parameters of p. Note that in this presentation, we

search for an assignment [θ] to the constants c1...cnsuch that B(p) = A(p)[θ].

def

1+ c2xk

2+ ... + cmxk

m+ cm+1xk−1

1

x2+ ... + cn

Initially, assume a polynomial upper bound of degree k on the running time of

such a program p(x,y,...). This upper bound for the particular program p will

be denoted by Ak(p). If a program p had two parameters x and y, then

A1(p) = c1x + c2y + c3

A2(p) = c1x2+ c2y2+ c3xy + c4x + c5y + c6

A3(p) = c1x3+ c2y3+ c3x2y + c4xy2+ c5x2+ c6y2+ c7xy + c8x + c9y + c10

In this presentation, we capture runtime behaviour by deriving sets of equations

of the form Ak(p(¯ x)) =?(Ak(fi(¯ x[ψi]))+1) for each of the sets of calls fiwhich

the values of the input parameters to p to the values of the input parameters on

the call fi. Note that with this formulation, each substitution is linear, and thus

cannot change the degree of the equation.

are calls isolated and identified by the same guard. The substitution ψirelates

3Characterization as a quantifier-elimination problem

The sets of assumptions and runtimes presented in the previous section are

universally quantified over the parameter variables, and this leads to the idea

of formulating this problem as a QE (quantifier-elimination) one. Consider the

following program p1operating over the naturals with parameters x,y ∈ N:

p1(x,y ) = if (x = 0 ∧ y ≥ 1) then

p1a(y,y − 1)

else

if (x ≥ 1) then

p1b(x − 1,y )

else

~ ;// ... exit ...

We can represent the runtime properties for each path through the program p1

with the three equations:

A2(p1)[x ?→ y,y ?→ y − 1] − A2(p1) + 1 = 0

A2(p1)[x ?→ x − 1] − A2(p1) + 1 = 0

A2(p1) = 0

5

Page 6

which reduce to:

−c1x2+ (c1+ c3)y2− c3xy − c4x + (c4− c3− 2c2)y + c2− c5+ 1 = 0

c1− 2c1x − c3y − c4+ 1 = 0

c1x2+ c2y2+ c3xy + c4x + c5y + c6 = 0

We wish to find suitable values for the (real-valued) coefficients c1...c6. That

is, we want to eliminate the universally quantified elements of the equalities.

There are several advantages of this QE formulation of the problem. Firstly,

there is an automatic technique for solving sets of polynomial equalities and

inequalities of this form, developed by Alfred Tarski in the 1930’s, but first

fully described in 1951 [18]. Tarski gives a decision procedure for a theory of

elementary algebra of real numbers. Quantifier elimination is part of this theory,

and after eliminating the quantifiers x and y in the above expressions, what

remains are constraints over the values of the coefficients. However, the algorithm

is not particularly efficient, although more recent methods are usable.

Secondly, precise analysis may be performed by including in the guards for each

of the paths. For example, we can express our QE problem as the single formula1:

?

∀x,y :

x = 0

∧ y ≥ 1

?

⇒ A2(p1)[x ?→ y,y ?→ y − 1] − A2(p1) + 1 = 0

∧

(x ≥ 1) ⇒

A2(p1)[x ?→ x − 1] − A2(p1) + 1 = 0

∧

?

x = 0

∧ y = 0

?

⇒

A2(p1) = 0

In [11], the author clearly shows how quantifier elimination may be used to

generate program invariants using either a theory of Presburger arithmetic, a

theory involving parametric Gr¨ obner bases, or Tarski’s theory of real closed

fields. This last theory is the most expressive, and a claim is made that the

approach is more widely applicable, and generates stronger invariants than the

Gr¨ obner basis approach in [17].

Our construction is different, and in a different field (program running time

rather than program invariants). We construct expressions characterizing the

program run time as a constraint quantified over the program parameters. The

constraint constants are then solved by QE, and algebraic reduction.

3.1 Quantifier elimination

In 1973, Tarski’s method was improved dramatically by the technique of Cylin-

drical Algebraic Decomposition (CAD) first described in [4]. The book [3] has a

good introduction to the method, which leads to a quantifier free formula for a

first order theory of real closed fields. In this theory, atomic formulæ may be of

1The derivation of this particular form will be explained in the next subsection.

6

Page 7

the form φ1= φ2or φ1> φ2, where φ1and φ2are arbitrary polynomials with

integer coefficients. They may be combined with the boolean connectives ⇒, ∧,

∨ and ¬, and variables may be quantified (∀ and ∃).

Definition 4. A Tarski formula T is any valid sentence in the first order theory

of real closed fields. Note that quantifier elimination is decidable in this theory.

Our approach is to construct a particular subset of Tarski formulæ, T[A(p)],

where A(p) is an assumption of the polynomial runtime of an LA-SCT program.

This subset is of the form

T[A(p)] =

∀x,y,...g1 ⇒ F1

∧ g2 ⇒ F2

∧ ... ... ...

where g1,g2,... identify different paths from p(a) to enclosed function calls

fi(b)2. F1,F2,... are formulæ derived from the program p source such that

∀x : gj ⇒ (Fj ⇔ (Ak(p(¯ x)) =

?

i

Ak(fi(¯ x[ψi])) + 1))

The following inference rules can be used to automatically generate these“Tarski”

formulæ from an arbitrary input program. They are presented in a form much

like typing rules, where the type for a statement s is replaced by the runtime cost

A(s). The context (or environment) Γ is a list which specifies the parameters in

the enclosing function.

Γ ? g(¯ x[ψ]) : A(g)[ψ] + 1 B-call

Γ ? s1 : A(s1)

Γ ? ifc thens1elses2 :

Γ ? s2 : A(s2)

?

c : A(s1)

∧ ¬c : A(s2)

B-if

? ˜ : 0

B-nocall

Γ ? s1 : A(s1)

Γ ? s1;s2 : A(s1) + A(s2)

Γ ? s2 : A(s2)

B-seq

Γ,?¯ x?f? s : A(s)

Γ ? f(¯ x)

def

= s : A(s)

B-def

Γ,?¯ x?f? s : A(s)

Γ ? p1; f(¯ x)

def

= s : A(s)

B-defs

Note that each application of a rule preserves the runtime of the statement.

In addition, a substitution ψ is applied in context, and is dependent on both

the enclosing functions parameter names, and the (fresh) names for any other

parameters.

This set of rules produces a guarded expression form for the assumed runtime

A(p). This is then transformed to a normal form, by first flattening the expression

(distributing the guards outwards), and then distributing A(p) in.

2Note that they must cover the parameter space of interest and be distinct.

7

Page 8

For example, for the program p1the above rules generate

∧

A2(p1) =

(x = 0 ∧ y = 0) :

∧ (x = 0 ∧ y ≥ 1) : A2(p1)[x ?→ y,y ?→ y − 1] + 1

(x ≥ 1) :

0

A2(p1)[x ?→ x − 1] + 1

and the equation T[A2(p1)] derived is thus:

T[A2(p1)] =

∀x,y :

?

?

x = 0

∧ y = 0

?

?

⇒

A2(p1) = 0

∧

x = 0

∧ y ≥ 1

⇒ A2(p1)[x ?→ y,y ?→ y − 1] − A2(p1) + 1 = 0

∧

(x ≥ 1) ⇒

A2(p1)[x ?→ x − 1] − A2(p1) + 1 = 0

and our task now is to reduce this to an expression without the quantifiers x

and y, and then find any example of c1...c6satisfying the resultant expression.

The following theorem asserts that the solution of the formula T[Ak(p)] cor-

rectly represents the runtime Bk(p) of any LA-SCT program p with a degree-k

polynomial runtime.

Theorem 1. If Bk(p) is the degree-k polynomial runtime of affine SCT pro-

gram p with parameters ¯ x, and Ak(p) is a degree-k polynomial assumption of the

runtime of LA-SCT program p, and [θ] is the assignment derived from T[Ak(p)],

then

∀¯ n :Ak(p)[θ][¯ n/¯ x] ≡ Bk(p)[¯ n/¯ x]

Proof. By structural induction over the form of the definition for Bk(p)[¯ n/¯ x].

3.2Tool support

There exists a range of tools capable of solving this sort of reduction. The tool

QEPCAD [6] is an implementation of quantifier elimination by partial CAD devel-

oped by Hoon Hong and his team over many years.

Another system is the redlog package [5] which can be added to the computer

algebra system reduce, and may be used to eliminate quantifiers giving com-

pletely automatic results. The following sequence shows redlog commands that

specify the runtime for program p1:

1: A2p1

2: path1 := sub(x=y,y=y-1,A2p1)-A2p1+1;

3: path2 := sub(x=x-1,A2p1)-A2p1+1;

:= c1*x^2+c2*y^2+c3*x*y+c4*x+c5*y+c6;

8

Page 9

In line 1 of the above sequence, we define the A2p1 assumption of the runtime

bounds B2of the program. In lines 2 and 3, A2(p1)[x ?→ y,y ?→ y−1]−A2(p1)+1

and A2(p1)[x ?→ x − 1] − A2(p1) + 1 (The sub command in reduce performs a

series of substitutions in the expression A2p1).

The following sequence shows the redlog commands to solve the problem:

4: TA2p1 := rlqea ex({c1,c2,c3,c4,c5,c6},

rlqe all({x,y},

((x=0 and y=0)

((x=0 and y>=1) impl path1=0) and

((x>=1)impl path2=0)));

impl A2p1=0) and

5: B2p1:= sub( part(part(TA2p1,1),2),A2p1);

In line 4 of the above sequence, the inner rlqe function performs quantifier

elimination on the equation T[A2(p1)], returning the following relations between

the constants c1...c6:

c4 = 1 ∧ 2c2− c4 = 0 ∧ c2− c5 = −1 ∧ c1,c3,c6 = 0

In this example, c1...c6are uniquely determined, and can be found easily with a

few simple reductions, but in the general case, the constraints over the constants

may lead to many solutions. The redlog package can also be used to find an

instance of a solution to an existentially quantified expression, and hence the

outer rlqea function above, which returns an instance of a solution to the above

relations existentially quantified over c1...c6: ∃c1...c6: T[A2(p1)].

The solution returned by redlog is

TA2p1 := {{true,{c1=0, c2=1/2, c3=0, c4=1, c5=3/2, c6=0}}}

Finally, in line 5, we substitute the solution instance back in the original as-

sumption A2(p1) = c1x2+ c2y2+ c3xy + c4x + c5y + c6, giving

B2(p1) = A2(p1)[c1 ?→ 0,c2 ?→1

= x +1

2,c3 ?→ 0,c4 ?→ 1,c5 ?→3

2,c6 ?→ 0]

2y2+3

2y

The example given above appears to lead more naturally to a constraint pro-

gramming based solution to these sort of problems, but most such systems can

only handle linear equations, not the polynomial ones used here.

There are constraint solving systems, for example RISC-CLP(Real) [9], which use

(internally) CAD quantifier elimination to solve polynomial constraints, however

here we prefer to restrict ourselves to just the underlying techniques, and not

clutter up the discussion with other, perhaps confusing, properties of constraint

solving systems.

9

Page 10

4Calculating other program costs

So far we have limited the presentation to examples which calculate polynomial

runtimes for programs. However, the technique is also useful for deriving other

invariant properties of programs, such as the maximum stack depth and the

relative runtime costs.

4.1Stack depth calculation

Consider program p2:

p2(x,y ) = if (x = 0 ∧ y ≥ 1) then

p2a(y,y − 1);

p2b(0,y − 1)

else

if (x ≥ 1) then

p2c(x − 1,y )

else

~ ;// ... exit ...

Note that in this program, we have the sequential composition of two function

calls, and this program has an exponential runtime cost. An interesting question

for this program is to calculate its maximum stack depth. The depth D of our

class of programs is calculated in precisely the same way as the runtime B, with

only a minor change. In the event of sequential composition, we record not the

sum of the two functions composed, but the maximum value of the two functions:

Γ ? s1 : A(s1)

Γ ? s1;s2 : max(A(s1),A(s2))

Γ ? s2 : A(s2)

B-seq

This corresponds with a Tarski formula for a polynomial solution like this:

∧

Given the formula, redlog immediately finds the stack depth cost:

∀x,y : (x = 0 ∧ y ≥ 1 ∧ D[ψ2a] ≥ D[ψ2b]) ⇒ (D[ψ2a] − D + 1 = 0)

∧ (x = 0 ∧ y ≥ 1 ∧ D[ψ2a] < D[ψ2b]) ⇒ (D[ψ2b] − D + 1 = 0)

(x ≥ 1) ⇒ (D[ψ2c] − D + 1 = 0)

D(p2) = x +1

2y2+3

2y

4.2 Relative runtime costs

The third motivation for this approach was to derive relative costs for the dif-

ferent possible paths through a program. For example in program p1, which

function is called more often, and what are the relative costs for each call? This

could be used in compiler optimization, improving the efficiency of the code by

re-ordering and placing more commonly used functions nearby.

10

Page 11

The same approach may be used, calculating B for each path. The equation

T[A(p1a)] for the program choosing the first function call may be written as:

∧

T[A(p1a)] =

⇒ B2(p1a) = y

∀x,y :

?

?

x = 0

∧ y = 0

?

?

⇒

A2(p1) = 0

∧

x = 0

∧ y ≥ 1

⇒ A2(p1)[x ?→ y,y ?→ y − 1] − A2(p1) + 1 = 0

(x ≥ 1) ⇒

A2(p1)[x ?→ x − 1] − A2(p1) = 0

The equation T[A(p1b)] for the program choosing the second function call may

be written as:

∧

⇒ B2(p1b) = x +1

Note that the sum of B2(p1a) and B2(p1b) is exactly B2(p1) derived for the whole

program.

T[A(p1b)] =

∀x,y :

?

?

x = 0

∧ y = 0

?

?

⇒

A2(p1) = 0

∧

x = 0

∧ y ≥ 1

⇒ A2(p1)[x ?→ y,y ?→ y − 1] − A2(p1) = 0

(x ≥ 1) ⇒

A2(p1)[x ?→ x − 1] − A2(p1) + 1 = 0

2(y2+ y)

5 Towards a classification of program costs

The presentation so far has concentrated on LA-SCT programs with costs that

may be expressed as polynomials over the program variables. However many such

programs have costs that are exponential rather than polynomial. For example,

the following program:

p3(x,y,n) = if (x ?= 0 ∧ n ≥ 1) then

p3a(x − 1,y,n)

else

if (x = 0 ∧ n > 1) then

p3b(2y + n,2y,n − 1)

else

~ ;// ... exit ...

This program has a runtime of B(p3) = y2n+1

immediately apparent by observation. The technique such as just described relies

on repeatedly trying ever higher degree polynomial time costs, and would never

discover this runtime.

2n2+3

2n + x − 2y − 2, not

We have an approach to solving programs of this form, but it requires us to find

some way of classifying program costs into either polynomial or exponential.

11

Page 12

In this section we present a characterization of the problem as a recurrence,

explaining the choice of the particular class of exponential cost programs that

can be solved.

The previous discussion employs a simple translation from program source to a

decidable Tarski formula. However this approach gives no indication of the run-

time cost for a function. For example, if we started assuming the program was

polynomial, the algorithm indicates that we should try a degree-2 assumption,

followed by a degree-3 assumption and so on. There is no indication as to when

we should give up. Towards this, we consider a flattened version of the original

program source, in which an arbitrary collection of functions is flattened into a

single function which calls itself. This new flattened source can be easily char-

acterized as a recurrence relation, and the solutions to the recurrence relations

give indications of the maximum polynomial degree.

In addition this presentation highlights a particular class of exponential programs

that can be solved.

A flattened version of an arbitrary program is easily derived in the absence of

mutual recursion. However, in the case of mutually recursive functions, it is

not as clear how a program may be transformed. The papers [19,12] contain

necessary and sufficient conditions to transform all mutual recursion to direct or

self-recursion.

Supposing that our programs are transformed into equivalent programs which

are using only self-recursion, we can define a self-recursive normal form over a

representation of the state of the program variables at any time. Consider an

m-dimensional array a, indexed by the values of parameters n1...nm to the

self-recursive program p(n1...nm):

Definition 5. The array an1,...,nmis in linear self-recursive normal form iff it

is defined as:

an1,...,nm= af1(n1,...,nm),...,fm(n1,...,nm)+ g(n1,...,nm)(1)

where fi(n1,...,nm) = ki,1·n1+...+ki,m·nm+ki,m+1, ∀ki,j∈ ?, ∀i ∈ {1,...,m},

∀j ∈ {1,...,m + 1}, and g(n1,...,nm) = k1· n1+ ... + km· nm+ km+1.

The above recurrence (1) is supposed to iterate for an arbitrary finite number

of times, say ?. We shall explore the expression obtained from (1) after applying

the substitution ni→ fi(n1,...,nm), ∀i ∈ {1,...,m} for ? times.

Theorem 2. All linear self-recursive normal forms have a solution.

Proof. (By construction). Denoting by n the vector (n1,...,nm), the first iter-

ation of (1) leads to:

af1(n),...,fm(n)= af1(f1(n),...,fm(n)),...,fm(f1(n),...,fm(n)))+ g(f1(n),...,fm(n)) (2)

12

Page 13

In order to write this more compactly, let us inductively define the notations

?

?

where

f(1)

is a compressed form of ?f1,m◦ ... ◦ f1,m(n)?, and “◦” stands

for the function composition. In this way, the recurrence (2) can be re-written

as:

a?

The given substitution can be further applied ? − 1 times, to obtain:

f(1)

1,m(n)

?

?

?

def

= (f1(n),...,fm(n))

?

f(?)

1,m(n)

def

=f1

??

f(?−1)

1,m (n)

??

,...,fm

??

f(?−1)

1,m (n)

???

for ? ≥ 2

?

1,m(n)

f(1)

1,m(n)

?= a?

f(2)

1,m(n)

?+ g

??

f(1)

1,m(n)

??

(2a)

a?

f(?−1)

1,m

(n)

?= a?

f(?)

1,m(n)

?+ g

??

f(?−1)

1,m (n)

??

(?)

By combining the recurrences (1)...(?), we obtain an expression for an:

??

By replacing fi(n1,...,nm) with ki,1·n1+...+ki,m·nm+ki,m+1, ∀i ∈ {1,...,m},

we get the general form:

?

where Ei,lis:

an = a?

f(?)

1,m(n)

?+ gf(1)

1,m(n)

??

+ ... + g

??

f(?−1)

1,m (n)

??

(I)

f(l)

1,m(n)

?

= (E1,?,...,Em,?)

m

?

We have established a solution for all recurrences of the self-recursive normal

form defined before, and this confirms the completeness for this class of recursive

programs.

il=1

...

m

?

i1=1

ki,i1·...·kil−1,il·nil+

m

?

il−1=1

...

m

?

i1=1

ki,i1·...·kil−1,m+1+...+

m

?

i1=1

ki,i1·...·ki1,m+1

?

For ease of presentation, and in order to see the complexity of anfrom (I), let

us highlight only the last (dominant) term. It is:

??

Looking at the general form of the dominant term, namely

gf(?−1)

1,m (n)

??

= k1· E1,l−1+ ... + km· Em,l−1+ km+1

ki·

m

?

il−1=1

...

m

?

i1=1

ki,i1· ... · ki?−1,m+1+ ... +

m

?

i1=1

ki,i1· ... · ki1,m+1

we observe that very few cases correspond to a polynomial as an expression for

an. Because of the large number of coefficients in the expression of an, it is almost

impossible to provide a precise boundary between the cases when anis a poly-

nomial and when it is an exponential. However, the formula does immediately

give the following classifications:

13

Page 14

1. if ∀i ∈ {1,...,m}, we have ki= 0, then an= ? · km+1is a polynomial in ?

of degree 1;

2. if m = 1 then

(a) if k1,1= 1 then anis a polynomial of degree 2;

(b) if k1,1?= 1 then anis an exponential of base k1,1.

3. if ∃i ∈ {1,...,m} such that ki?= 0 and ∃u,v ∈ {1,...,m} such that ku,v / ∈

{0,1} then ancontains at least one exponential of base ku,v.

The third classification above covers a considerable number of situations when

anis an exponential.

A useful slight generalization of recurrence (1) can be done by taking g as a

non-linear polynomial. It is easy to see that if m = 1, and k1,1= 1, then for a

polynomial g of degree k, the solution of anis a polynomial of degree k + 1. In

this way, we enlarge the class of self-recursive normal form equations.

5.1A case-study

Let us take a useful example which corresponds to particular values for m, fol-

lowed by a practical application of its use in computing the runtime of a given

program.

When trying to compute the runtime cost of p3, we get the following identities,

formed by a guard and a recurrence relation:

x ?= 0 ∧ n ≥ 1 implies B(x,y,n) = B(x − 1,y,n) + 1

x = 0 ∧ n > 1 implies B(x,y,n) = B(2y + n,2y,n − 1) + 1

By inspection of the first identity, and by iterating x → x − 1 for x times,

we get B(x,y,n) = B(0,y,n) + x. By applying the second identity, we have

B(0,y,n) = B(2y + n,2y,n − 1) + 1 = B(0,2y,n − 1) + 2y + n + 1. We rewrite

this latter identity, omitting the first argument (without loss of generality), to

the equivalent recurrence relation:

ay,n = a2y,n−1+ 2y + n + 1

This is a particular instance of recurrence (1), where m is replaced by y, and

f(n,m) = 2m, g(n,m) = 2m + n + 1. Since k1= 2, the solution of ay,nis an

exponential (case 2(b)). This implies that our automated tool should be fed with

an input having a generic form like this:

B(p3) = φ1· Kφ2+ φ3

This allows for a runtime with quite a complex exponential form.

14

Page 15

6Exponential cost calculations

Having established a classification of program costs, we now revert to the original

approach, where we assume an exponential runtime A for the program, initially

for a base of K, and using polynomials of (say) degree 2. The assumed runtime

is A(p3) = φ1· Kφ2+ φ3, where φ1, φ2and φ3are three polynomials of degree 2.

The three polynomials bear a peculiar relationship to each other due to the

linearity of the parameter relationships. For example, for any single recursive

call path, since the changes in the parameters are linear, then the runtime for

this call path cannot be exponential. As a result of this, for any single recursive

call path, φ3[ψ]−φ3+1 = 0, and in the case of a base of K, the following relation

holds:

(φ1[ψ] = φ1

∨

∨ (Kφ1[ψ] = φ1

This relationship between the polynomials may be exploited by constructing the

equations in a similar form to the previous presentation, solving them in a similar

manner, and finally deriving a sample solution. The redlog package is used to

define

∧ φ2[ψ] = φ2)

(φ1[ψ] = Kφ1 ∧ φ2[ψ] = φ2− 1)

∧ φ2[ψ] = φ2+ 1)

φ1 = c1x2+ c2y2+ c3n2+ c4xy + c5xn + c6yn + c7x + c8y + c9n + c10

φ2 = c11x2+ c12y2+ c13n2+ c14xy + c15xn + c16yn + c17x + c18y + c19n

φ3 = c21x2+ c22y2+ c23n2+ c24xy + c25xn + c26yn + c27x + c28y + c29n + c30

A = φ1· Kφ2+ φ3

The substitutions [ψ3a] = [x ?→ x−1] and [ψ3b] = [x ?→ 2y+n,y ?→ 2y,n ?→ n−1]

for the two paths are applied to φ1, φ2and φ3, yielding the primed polynomials,

and the equation T[A(p3)] for program p3may be written as:

∨ (Kφ1[ψ3b] = φ1

T[A(p3)] is easily reduced by redlog, giving a family of solutions for the bounds:

A(p3) = αy2n+1

∀x,y,n :

?

x,y > 0

n ≥ 0

∧

?

⇒

φ3[ψ3a] − φ3+ 1 = 0

∧

(φ1[ψ3a] = φ1

(φ1[ψ3a] = Kφ1 ∧ φ2[ψ3a] = φ2− 1)

∨ (Kφ1[ψ3a] = φ1

∧ φ2[ψ3a] = φ2)

∨

∧ φ2[ψ3a] = φ2+ 1)

∧

x = 0

∧ y > 0

∧ n ≥ 0

⇒

(φ3[ψ3b] − φ3+ 1 = 0)

∧

(φ1[ψ3b] = φ1

(φ1[ψ3b] = Kφ1 ∧ φ2[ψ3b] = φ2− 1)

∧ φ2[ψ3b] = φ2+ 1)

∧ φ2[ψ3b] = φ2)

∨

2n2+3

2n + x − 2y + c30

where α indicates that any value here might be a solution, and c30is unknown.

To constrain the solution further, we add in boundary cases for the system, for

example A(p3(0,1,1)) = 0, A(p3(0,2,1)) = 0, giving:

B(p3) = y2n+1

2n2+3

2n + x − 2y − 2

15