{'fraction_non_alphanumeric': 0.04636176081967593, 'fraction_numerical': 0.007719233176476043, 'mean_word_length': 3.9930555555555554, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 43, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Local Higher-Order Fixpoint Iteration

Local fixpoint iteration describes a technique that restricts fixpoint iteration in function spaces to needed arguments only. It has been studied well for first-order functions in abstract interpretation and also in model checking. Here we consider the problem for least and greatest fixpoints of arbitrary type order. We define an abstract algebra of simply typed higher-order functions with fixpoints that can express fixpoint evaluation problems as they occur routinely in various applications, including program verification. We present an algorithm that realises local fixpoint iteration for such higher-order fixpoints, prove its correctness and study its optimisation potential in the context of several applications.


Introduction
Fixpoints are ubiquitous in computer science. They serve to explain the meaning of recursion in programming languages [35], database queries [1], formal languages and automata theory [31]; they are being used as logical quantifiers in descriptive complexity [19] or as specialised operators, for instance in temporal logics [15], etc.
Fixpoints often link a denotational and an algorithmic view onto computational problems, most specifically through Kleene's Fixpoint Iteration Theorem [21]: start with the least, resp. greatest value of the underlying lattice, and then keep applying the function under consideration until the sequence becomes stable. This theorem provides the algorithmic foundations for many applications in which fixpoints play an important role. For instance in model checking, fixpoint operators are used to describe correctness properties [17], and methods based on fixpoint iteration are being used to establish the satisfaction of such properties by models of programs [5]. Fixpoints are used in programming language semantics to explain the meaning of recursive programs. This extends to static analysis methods. For instance in the original formulation of abstract interpretation [13], collecting semantics extends program semantics to powersets of semantic values ordered by subset inclusion [14]. Computing program properties then amounts to solving fixpoint equations over a number of specific (powerset) domains. Fixpoint iteration also provides a standard means for the evaluation of recursive database queries [1].
In many applications, the elements of the lattices in which fixpoints are being sought, are functions themselves. In strictness analyses for functional languages [27,11] for instance, properties under consideration are sets of functions. Denotational semantics is perhaps the application domain which is most easily seen to need lattices of functions, possibly of higher order, in order to explain the meaning of, for example, functional programs of higher order. Certain infinite-state model checking problems, in particular so-called higher-order model checking [29] are tightly linked to the evaluation of fixpoints in functions spaces as well [22].
We are concerned with the problem of finding fixpoints in such a lattice of functions of some higher order. Kleene fixpoint iteration in its pure form can still be employed here, but in many situations it is naïve and inefficient for the following reason. Suppose one is not interested in the entire fixpoint f (which is a function of some type M → N) but only in the value of this f on some particular argument x ∈ M. Naïve fixpoint iteration would start by approximating this function with the least one f 0 := → ⊥ N that maps anything to the least element of the lattice N, and successively compute better approximations f 1 , f 2 , . . . until f i+1 = f i for some i. Then it would return f i (x) which equals f (x).
This procedure has then also computed values f (y) for any y ∈ M. It has been observed that a more efficient approach would be goal-driven and avoid the computation of f on any unnecessary argument. Note that, since f is defined recursively, the value f (x) may depend on some but not all values f (y) for y ∈ M. The term neededness analysis was coined to describe the goal-driven evaluation of fixpoints in function lattices, avoiding the computation of function values on arguments that do not contribute to the computation of the one value of interest.
Neededness analysis has been studied well for lattices of first-order functions as they often arise in abstract interpretation [20]. In groundness analyses for logical programs such as [12], instead of neededness, one rather speaks of a fixpoint computations being local [18], when a solver tries to only compute the values of as few variables as possible. Neededness analysis has also been studied in the context of model checking complex program properties which cannot be described in the standard temporal logics of regular expressivity (CTL, µ-calculus) but in extensions using predicate transformers [2]. This can be seen as a notion of on-the-fly model checking for fixpoints of order 1. Since "local" is also a synonym for "on-the-fly" in model checking [8], we stick to the term local fixpoint iteration here rather than the more cumbersome neededness analysis, when referring to a method to avoid the computation of all arguments of fixpoints which are functions themselves.
In this paper we consider the applicability of local fixpoint iteration in function lattices to arbitrary higher orders. To this end, we define a simple abstract and typed higher-order fixpoint algebra in Sect. 2 which can be used to describe evaluation problems involving fixpoints in such lattices. We then give a generic local algorithm for evaluating fixpoint terms in higher-order lattices in Sect. 3. It optimises the naïve fixpoint iteration method by localising the evaluation of recursively defined functions at the top order. A formal proof of its correctness is omitted due to space constraints. In Sect. 4 we present some computation problems which are special instances of the evaluation of higher-order fixpoints in various domains and discuss local evaluation's optimisation potential by comparing numbers of iteration, resp. argument computation steps on some hand-crafted examples. In Sect. 5 we briefly sketch limitations to the local approach of fixpoint iteration for higher-order fixpoints, in the form of obstacles to overcome which do not exist in the first-order case. We conclude in Sect. 6 with an outlook onto further work in this area.

An Abstract Higher-Order Fixpoint Algebra
Types and higher-order lattices. Let be some base type. Types are derived from the grammar where the annotations v are called variances, and they specify the dependency of the values of a function of type τ v 1 1 × · · · × τ v n n → τ on their arguments. In particular, if v i = +, then this dependency is monotonic, if v i = − then it is antitonic, and it v i = ± then it is unspecified.
The order of a type τ is ord( ) := 0 and ord(τ v 1 1 × · · · × τ v n n → τ) := max{ord(τ), ord(τ 1 ) + 1, . . . , ord(τ n ) + 1} As usual, a function f on a partially ordered set (M, ≤) is monotonic if for all x, y ∈ M with x ≤ y we have f (x) ≤ f (y). It is antitonic if for all such x, y we have f (y) ≤ f (x). A lattice is a partial order in which suprema and infima, denoted x ⊔ y, x ⊓ y, resp. X and X for any X ⊆ M exist, for as long as X is finite. A lattice is complete if these also exist for arbitrary X . Complete lattices always contain a least and a greatest element, usually denoted ⊥ and ⊤ here. A finite lattice is trivially complete.
Let M = (M, ≤) and M i = (M i , ≤ i ) for some i = 1, . . . , n be complete lattices. Remember the following constructions on lattices: Inverse: For notational convenience we also let M + := M . It should be clear that these two operations not only preserve the property of being a lattice but also completeness.
Flattening: M ± := (M, =), where = denotes equality as usual. Note that M ± is in general not a lattice anymore, let alone a complete one.
The product lattice is complete if all its components are complete. Higher-order: for all x ∈ M 1 . The lattice of componentwise ordered monotonic functions from M 1 to M 2 is complete if M 2 is complete. Completeness of M 1 is not required, not even the property of being a lattice since ≤ 1 is not used in the definition of ⊑.
We can use these constructions to associate, with each type τ, a complete lattice M τ , given a complete lattice M interpreting the ground type : Note that each τ M is indeed a complete lattice given the remarks above, as the flattening operation that breaks the lattice property is only used on the argument side of the function operator. Moreover, if M is finite, then so is τ M for all τ.
Abstract higher-order fixpoint algebra. Let M be a complete lattice and Func = { f : τ f , g : τ g , . . .} be a set of computable and typed functions on M , possibly of higher-order. Note that if τ f = , then f is not really a function but rather a constant. For simplicity we speak of functions in this case as well. Let Var := {x : τ x , y : τ y , . . .} be a set of typed variables. We write τ x , resp. τ f for the uniquely determined type of variable x, resp. function f . We will also simply write x ∈ Var instead of (x, τ x ) ∈ Var and likewise for the members of Func.
Terms of the abstract higher-order fixpoint algebra over Func, µHO(Func) or simply µHO when Func is clear from the context, are built via ϕ, ϕ 1 , . . . , ϕ n : A term ϕ is closed if it contains no free variables, where an occurrence of a variable x is free if it is not under the scope of some λ . . . x . . . or µx or νx in the syntax tree of ϕ. In the following, we are mainly interested in closed terms; others will usually only occur as subterms of these. Hence, we will often simply speak of terms when in fact we mean closed terms at syntactic top-level. Figure 1: The typing rules for abstract higher-order fixpoint algebra.
We assume terms to be well-named, i.e. each variable is bound at most once. Clearly, any term can always be made well-named by renaming bound variables.
In order to give terms a well-defined semantics via the Knaster-Tarski Theorem, each ϕ in a term µx.ϕ or νx.ϕ needs to denote a function that is monotone in its argument x. Monotonicity is guaranteed for well-typed terms, to be explained next, and then formally stated as Lemma 2.1 below. Note that the variances are used to track information about the monotonicity or antitonicity of functions in particular arguments, and that a monotonic function can be built for instance by composing two antitonic ones.
A typing statement is a triple Γ ⊢ ϕ : τ where ϕ is a term, τ is a type, and Γ is a typing context consisting of typing hypotheses of the form x v for x ∈ Var and v being a variance. For a typing context Γ, let Γ + := Γ; let Γ − result from Γ by replacing in it every x + by x − and vice-versa; and let Γ ± = Γ + ∩ Γ − , i.e. the context which only contains typing hypotheses of the form x ± from Γ. The typing context Γ[x v ] is obtained by removing x v ′ from Γ for any v ′ , and adding x v instead.
A term ϕ has type τ if the typing statement / 0 ⊢ ϕ : τ is derivable using the typing rules given in Fig. 1. The rules are standard; they state, for instance, that in function application ϕ(ϕ 1 , . . . , ϕ n ), ϕ must have a function type with n arguments which are the types of the respective argument terms. Moreover, the arguments themselves have to be typbale in the respective derived typing contexts. For example, if ϕ is antitonic in its first argument, then ϕ 1 has to be typable in the typing context Γ − , where Γ is the context used to type the whole application. This reflects the fact that an antitonic function from some lattice is a monotonic function from the inverse of this lattice (cf. the lattice definitions above and the definition of the semantics below). The rules for fixpoint formulas σ x τ .ϕ require the term ϕ to be of the same type as x, since being a fixpoint intuitively means x = ϕ(x), and at the same time ensure that ϕ is monotonic in x. A term is well-typed, if it is of some type.
Variance annotations are only used to guarantee well-typedness (and therefore the existence of fixpoints). We will always assume that terms are well-typed, and therefore often drop typing annotations for better readability. Note that for closed terms, a unique type for each subterm can easily be recovered. is defined inductively as follows.
The fourth clause, in particular its right-hand side, denotes the function that maps a tuple ( where the subscript index denotes the variable environment that results from η by replacing its bindings for x 1 , . . . , x n accordingly. For the last two clauses, note that the values on the right-hand side are well-defined according to the Knaster-Tarski Theorem [32] since each τ x M is a complete lattice. Note that the semantics of µHO are easily seen to be invariant under β -reduction.
Proof. By a straightforward induction on the syntax tree of ϕ.
Remark 2.2. Over finite lattices, each of the type lattices is finite as well. According to Kleene's Fixpoint Theorem, the least and greatest fixpoints of a term σ x. ϕ in µHO under a variable interpretation η can be computed by a sequence of approximations as follows: Evaluation problems. We consider the following generic evaluation problem: given a (closed) term ϕ of µHO(Func) with symbols in Func interpreted in the higher-order lattices over a finite M , compute ϕ M . This problem is clearly decidable when all basic functions in Func are computable. A naïve algorithm will simply compute the value of each subterm in a bottom-up fashion using Kleene iteration to evaluate fixpoint expressions, and possibly storing function values as tables. Note that if M is finite, so is τ M for any τ, but the size and height of τ M are k-fold exponential in the size, resp. height of M when k = ord(τ).
Even for low orders, such a naïve algorithm may perform far too many unnecessary computation steps. Consider the following special local variant of the evaluation problem: given a finite complete lattice M , a closed term ϕ 0 := µx. ϕ of type τ v → (which is then necessarily the same as τ x ) for some v, τ, ϕ, and a term ψ of type τ, compute ϕ 0 (ψ) M .
Note how this problem formulation describes a situation in which naïve fixpoint iteration obviously performs too many evaluation steps in general: it computes ϕ 0 M using Kleene iteration which results in a function of type τ v → . Depending on the order of τ, this function is huge in terms of its arguments but still finite. We would then also compute ψ M . Then we obtain the value ϕ 0 (ψ) M by application, for instance through a simple look-up in the table representing ϕ 0 M , where ψ M occurs as some argument. Clearly, the value of ϕ 0 M on all other arguments is irrelevant, and the reason for their computation is questionable.
x encodes an even number, for instance even( x) = ¬x 0 ; • half and dbl represent the operations "÷2" and "·2" on bit strings; • add( x, y) yields a bit string representing the addition of the two values modulo 2 n .
It is not difficult to find Boolean functions realising these operations.
Intuitively, ϕ n defines a search procedure. Note that any value of x encodes a number in the range [2 n ] = {0, . . . , 2 n − 1} which we will simply denote x as well. For any value x, define a sequence ( that the Boolean function ∧ only evaluates its second argument when the first one is not ⊥, this graph suggests how local fixpoint iteration of this first-order function F can be more efficient when the value of the fixpoint F is only needed on one particular argument. The effect of global fixpoint iteration is depicted in Fig. 2 (left). Here, the iteration starts with the least function F 0 : → ⊥, and it terminates when the current approximation equals the last one. Local fixpoint iteration on the other hand only adds the arguments successively to those tables. Consider the case of evaluating ϕ 3 (1, 0, 1) which means iterating the numerical series beginning at 5. First we only tabulate the approximant F 0 on the value under consideration, i.e. 5. In order to compute F 1 (5) we need F 0 (0), so 0 gets added as a new argument and receives the initial value ⊥ there. Then we compute F 2 (5) and F 1 (0), and so on. The iteration stabilises when no change is being recorded anymore, thus computing values as they are shown in the table of Fig. 2 (middle).
The effect of computing ϕ 3 (1, 1, 0), i.e. beginning the numerical series at 3 is similar. Here, however, 0 is never reached. Hence, all values encountered are ⊥, and the iteration stabilises when no further arguments are needed, as shown in Fig. 2 (right).
Even though the local iteration computes a value of F 4 while the global one only reaches F 3 , it should be clear that local evaluation performs fewer computation steps in general.

Remark 2.3.
It is well-known that fixpoint iteration does not need to record the entire history of its computation but, for each variable, merely the value of the last iteration. In the left table (with only one fixpoint variable) in Fig. 2, this corresponds to two successive rows: the upper for the last approximate value of a function, and the lower for the current value. In the two tables on the right using local iteration, this corresponds to diagonals, but the picture is more complicated in general, for instance for fixpoint terms in which the fixpoint variable has multiple occurrences.
The tables shown in Fig. 2 not only give an idea of how local fixpoint iteration works, their width and height are also good measures for the space, resp. time needed to compute such a higher-order fixpoint.

Local Fixpoint Evaluation for Full µHO
The algorithm. Procedure EVAL in Alg. 1 solves the evaluation problem for µHO terms of arbitrary higher order and finite lattices using local fixpoint iteration. It takes four parameters: (1) a term ϕ ∈ µHO(Func) over some Func. It is not necessarily of type , but the algorithm is assumed to be started with a full list of arguments (see below) in order to realise local fixpoint iteration. (2) A finite, and, hence, complete lattice M with an interpretation of any f : τ f ∈ Func as an object in τ f M .
(3) A list T 1 , . . . , T k of arguments to ϕ. The following invariant is maintained: if the type 1 of ϕ is τ 1 → · · · → τ k → , then A global variable ENV that is used to interpret free variables. Values of λ -bound variables are stored as full functions 2 , values of fixpoint variables may be stored as partial approximations as described at the end of the previous section.
In order to bridge the gap between a variable assignment η, which assigns a value to each variable which is defined at every argument, and the global variable ENV which only stores partial approximations for fixpoint-bound variables, consider the following definition. It turns a state of ENV into a well-defined variable assignment: Here,σ x is ⊥ , resp. ⊤ for variables that are bound to a least, resp. greatest fixpoint. Note that, due to the invariants, a state of Alg. 1, i.e. a call of EVAL(ϕ, T 1 , . . . , T k ) with a value of ENV and over some higher-order lattice M , can be thought of as computing the object ϕ M η ENV (T 1 , . . . , T k ), which is always a member of M . The algorithm computes this value recursively by descending through the syntax tree of ϕ. Fixpoints are resolved by Kleene iteration until the semantics computed stabilises, but the value is only computed at the arguments indicated plus all those arguments that are discovered as necessary to obtain the value for the original argument.
We explain the algorithm's functionality by considering the different cases for its argument ϕ. Upon reaching a basic function symbol, EVAL simply applies the semantics of this basic function to the arguments in the argument list. When EVAL reaches a variable x and the value of that variable at argument (T 1 , . . . , T k ) is defined, then its value is returned. Otherwise, the variable must be fixpoint-bound, and EVAL has discovered a new tuple of arguments at which the value of this fixpoint is needed. This value is initialised asσ x , which also registers (T 1 , . . . , T k ) in ENV. In this case the initial value is returned.
Algorithm 1 Neededness-based evaluation for abstract higher-order fixpoint algebra. procedure EVAL(ϕ, T 1 , . . . , T k ): ⊲ global (partial) ENV : At a λ -abstraction, a number of arguments corresponding to the abstracted variables are transferred from the argument list to ENV, i.e. they are now treated as bound variables. In an application ϕ(ϕ 1 , . . . , ϕ k ), EVAL computes, for each argument, its full semantics by a number of recursive calls to EVAL 3 . The obtained values (as functions) are then added to the list of arguments.
Upon reaching a fixpoint binder for variable x, EVAL (re-)sets ENV(x) to the singleton definition that initialises the value of the fixpoint at (T 1 , . . . , T k ) to the default value ofσ x . Then, for each argument tuple that is already discovered as necessary for the value at (T 1 , . . . , T k ), the algorithm computes a new value. Note that, during this process EVAL can reach the variable case and discover new argument tuples. This procedure of updating the value at all known argument tuples is repeated until both no new arguments are discovered for one round, and the value of the fixpoint at each of the tuples agrees with that of the last round. If this has happened, the value of the last iteration at (T 1 , . . . , T k ) is returned.
Correctness. The formal correctness proof for Alg. 1 uses the following lemma which formalises the converse of Lemma 2.1. Take a term ϕ that is typed with hypotheses Γ, x v . Not only is it monotone (if v = +), respectively antitone (if v = −) in the value of x. If the value of ϕ also differs genuinely under two variable interpretations that only differ in x, then x must occur freely in ϕ and there are arguments to the value of x on which this difference manifests itself. We write x ⊏ y to denote that x ⊑ y but x = y. Lemma 3.1. Let M be a finite, and hence, complete lattice, η be a variable interpretation, f 1 , f 2 ∈ τ ′ with τ ′ = τ ′ 1 → · · · → τ ′ k → for some τ ′ 1 , . . . , τ ′ k , let T 1 , . . . , T n be values with T i ∈ τ i for i = 1, . . . , n, v ∈ {+, −}, and ϕ be a µHO term such that Γ, then x appears freely in ϕ, and there are T ′ 1 , . . . , T ′ n such that Proof. By induction on the structure of ϕ. Details are omitted.
Next we state correctness of Alg. 1. It is not hard to imagine local fixpoint iteration to be sound (for least fixpoints, resp. complete for greatest ones) since it clearly only performs part of a global fixpoint iteration that is sound and complete according to Kleene's Theorem. For completeness one has to see that the value of a fixpoint function on some argument is determined solely by the value of that function on its dependent arguments. Hence, it suffices to iterate on these until stability is reached.
Theorem 3.2. Let M be a finite, and, hence, complete lattice, η be a variable interpretation, ϕ be a term of type τ 1 → · · · → τ k → , let T 1 , . . . , T k be values with T i ∈ τ i M , and ENV be such that η = η ENV .
Proof. The proof is, again, by induction on the structure of ϕ. Details are omitted.
A natural question that arises is the one after the time and space complexity of local higher-order fixpoint iteration. Two aspects need to be considered here. First of all, it should be obvious that local evaluation cannot improve the worst-case. It is in fact not hard to construct examples which a fixpoint term of higher-order such that its evaluation causes all argument values to be explored. Consider the (order-1) term νF(x).F((x ∧ ♦¬x) ∨ (¬x ∧ x)) (ff) with ∧, ∨, ¬, ♦, interpreted in the usual way known from modal logic, over the powerset lattice induced by the Kripke structure n−1 . . . 2 1 0 Even though the term evaluates to {0, . . . , n − 1}, local fixpoint iteration will successively discover all 2 n arguments to the first-order function F before termination. It is also possible to extend this example to an arbitrary higher order. Second, the question after the space and time complexity of Alg. 1 cannot be answered without making assumptions on the representation of the lattice and the complexity of evaluating base functions. So far, no assumptions have been made explicitly, even though it is clear that such functions should at least be computable for otherwise Alg. 1 would not be well-defined. A reasonable assumption is that each base function of order k can be evaluated in time and space that is at most (k − 1)-fold exponential in the size of the underlying lattice, with 0-fold meaning polynomial and (−1)-fold meaning logarithmic. Logarithmic bounds may seem highly restrictive at first glance, but they make sense in cases where the underlying lattice is obtained as the powerset lattice of some other structure, see the example above. If this assumption is met, then it is not too hard to see that Alg. 1 runs in time and space that is at most k-fold exponential with k being the order of the input term. This also assumes that the lattice is given in a logarithmically sized representation. Otherwise, the complexity drops by one exponential.

Applications
We present four applications of fixpoint evaluation in higher-order lattices using local fixpoint evaluation, and estimate how many computation steps can be saved compared to a naïve bottom-up and global fixpoint iteration.
Constrained reachability problems. Reachability problems -to decide whether some node is reachable from another in a directed graph -are ubiquitous in computer science. In some applications, simple reachability is too coarse; instead one wants to put constraints on the form of path under which the target node can be reached from the source, for instance in terms of distance, weight, shape or allowed sequence of edges. The latter can easily be formalised as a reachability problem constrained by some formal language. This has been investigated thoroughly for regular [6] and context-free languages [7,3,24] for applications in database theory, model checking, or in static program analysis for heap-manipulating programs [25,16]. Little has been done for larger classes of languages. We consider the context-sensitive language L abc := {a n b n c n | n ≥ 1} over the alphabet Σ := {a, b, c}, and the problem whether for some given nodes s,t of a directed, edge-labelled graph G = (V, E) there is a path from s to t whose edge labels form a word in L abc . Reachability problems can be interpreted in powerset lattices (2 V , ⊆) as they can be seen as least fixpoints of functions from sets of nodes to sets of nodes. However, if G is backwards-deterministic, i.e. for all v, u, w ∈ V , a ∈ Σ we have (v, a, u) ∈ E ∧ (w, a, u) ∈ E ⇒ v = w, it is possible to formalise such problems over a smaller lattice.
Consider the graph G n depicted in Fig. 3 on the left. It contains a central state 0 and around this three loops: an a-loop with n − 1 states, a b-loop with n states and a c-loop with n + 1 states. It is backwardsdeterministic. Let be interpreted by the lattice shown in Fig. 3 on the right. Intuitively, ⊥ can be read as "a path from source to the target has not been found yet", and ⊤ signals that such a path has been found.
We use base functions F := {0 : , a, b, c : + → , ite : ± × + → } as follows. The constant 0 denotes the state 0. For any v ∈ V , a(v) is the a-predecessor of v; likewise for b and c. The value is ⊥ if no such predecessor exists, in particular when applied to ⊥. The value on ⊤ is ⊤ itself. For instance, In the powerset lattice (2 V , ⊆), ite could simply be interpreted as set union. However, here we Using fixpoint unfolding and β -reduction one can see that the value of ϕ reach becomes ⊤ when a(b(c(0)) = 0 or a (a(b(b(c(c(0)))))) = 0 or a 3 (b 3 (c 3 (0))) = 0 and so on. Hence, evaluating ϕ reach solves the reachability question "is there a path from 0 to 0 under some word in L abc ?" We analyse how much computation power is being saved when computing the answer to the question of whether there is an L abc -path from 0 to 0 in G n . We compare four situations arising from the use of the standard powerset lattice vs. the optimised flat lattice of Fig. 3, as well as local vs. global enumeration of all arguments to higher-order functions.
Note that the three cycles in G n have lengths n, n + 1 and n + 2 respectively, which are always coprime for each n ≥ 2. Hence, the shortest L abc -path from 0 to 0 is the one that performs (n + 1)(n + 2) many rounds on the a-cycle, then n(n + 2) rounds on the b-cycle and then n(n + 1) rounds on the c-cycle.
The following table shows the computational effort needed to evaluate ϕ reach in terms of the number of arguments, resp. width of the table representing the function F. It also shows the space that is needed in order to represent one argument, i.e. a triple ( f , g, x) where f , g are first-order functions and x is a lattice element. Finally, in all cases the height of the table, i.e. the number of fixpoint iterations needed until F stabilises, is in O(n 3 ). Parsing of programming languages with indentation. Some programming languages like HASKELL or PYTHON use indentation as a syntax element. Such an effect can be described conveniently by the higher-order grammar G ind shown in Fig. 4 (left), over the terminal alphabet Σ = {b, c, } (for "block", "code" and "space"). We refrain from defining higher-order grammars [26,34] formally, since the technicalities needed for this small example are quite intuitive: B(I) generates a block of code at indentation level I. The block can either be empty, contain one line followed by the rest of this block at the same indentation level, or start a new block at a greater indentation level. The symbol S is used to generate a sequence of space characters ' '. Finally, P generates a program as a block at some initial indentation level. An example word, generated from this grammar and formatted in order to visualise indentation best, is shown in the middle of Fig. 4. Suppose a word w = a 0 . . . a n−1 ∈ Σ * is given. This gives rise to an interpretation of the symbols in the grammar above as follows. Let M w be the lattice shown in Fig. 4 on the right. We use the following base functions, derived from the terminal symbols and the constructors in the higher-order grammar.
Func ind = {b, c, , ε : ± × ± → τ , ·, | : τ + × τ + → τ, start, end : } Intuitively, b, c, and ε are used to mark sections of the word in which the corresponding symbols (resp. the empty word) occur. The top and bottom element of the lattice are used to signal true/false. The interpretation of these functions is therefore simply for a ∈ Σ. The two constructors | and · denoting disjunctive choice and concatenation in the higher-order grammar are interpreted as follows.
Finally, we need two constants start and end which are interpreted as 0 and n, respectively. The nonterminals in the higher-order grammar can be seen as (fixpoint) variables, hence we have Var = {P, S, I : τ, B : τ + → τ}. Then G ind immediately becomes a second-order term of µHO over Func ind and Var, since recursion in grammars is captured by least fixpoints. The problem of evaluating P(start, end) over M w is then equivalent to parsing w w.r.t. G ind .
Clearly, the space and time needed to evaluate P(start, end) is dominated by the fixpoint iteration for B as the only second-order variable. The number of possible arguments to it is 2 O(n 2 ) . Local fixpoint iteration only discovers a fraction of these, though. Note that B is initially evaluated on S, and -when the recursive is called on argument I -it needs the values of B on I itself as well as on S · I. Hence, it only ever discovers S, S 2 , S 3 , . . .. Moreover, it is not hard to see that S k maps two positions (i, j) of an underlying word w = a 0 . . . a n−1 to ⊤, if j − 1 − i ≥ k and a h = for h = i, . . . , j − 1. Hence, the number of possible arguments to B discovered in this way is bounded by n − 1 and so, again, local higher-order fixpoint iteration realises an exponential reduction in space complexity in this example.
Model checking Higher-Order Fixpoint Logic. Fixpoints play a fundamental role in model checking, where properties of the runtime behaviour of programs are typically expressed in temporal logics, the most prominent of which are LTL and CTL. Fixpoints are used there to express limit behaviour as in reachability, safety and fairness [17]. The true power of fixpoints is unleashed in logics that extend modal logic by extremal fixpoint quantifiers like the well-known modal µ-calculus [23]. A lesser known extension of this is Higher-Order Fixpoint Logic (HFL) [33], a highly expressive specification logic that mixes modal logic, a typed λ -calculus and fixpoint quantifiers. Its model checking problem is decidable over finite transition systems, albeit k-fold exponential in the order of involved function types [4,10].
We refer to the literature for a self-contained definition of HFL [33]. With the preliminary work on abstract higher-order fixpoint algebra in Sect. 2 we can simply present HFL as a special instantiation of this algebra. The base type is interpreted as the powerset lattice (2 S , ⊆) of the state set of a transition system with edge labels from some set A and propositional labels from some set P. This gives rise to an interpretation of all higher-order types as functions on sets of states; a function of type + → for instance is known as a (monotonic) predicate transformer.
The set of ground functions then is F := {∧, ∨ : : + → | a ∈ A } ∪ {p : | p ∈ P} reflecting the Boolean, modal and propositional parts of the logic. Well-typed terms of the higher-order fixpoint algebra over this F are exactly the formulas of HFL; and the standard semantics is the same as the one derived from the generic semantics in Sect. 2 for this set of terms.
Consider the following formula describing the property ϕ = "there is an infinite b-path such that the i-th node on this path is the start of an a-path of length 2 i ending in a p-node, for any i ≥ 0", as well as the family of transition systems T n on the right.
Only state 1 satisfies ϕ. Now note that F is a second-order fixpoint taking as arguments a term interpreted as a first-order function of the kind 2 Abstract interpretation of functional languages. Strictness analysis for (lazy) functional languages tries to figure out whether an argument to a function must always be evaluated. In this case compilers may force the evaluation of the argument thus saving space and time to create closures and allowing for parallelisation. Strictness analysis may be formulated as an abstract interpretation as e.g. in [11]. • constants of base domains such as integers or boolean values are abstracted to 1 (not undefined); • first-order functions such as addition are strict in all arguments, e.g., x + y = 0 unless x = y = 1; • if-then-else: ite(x, y, z) = x ∧ (y ∨ z), where elements of 2 are read as boolean values. If-then-else might only be defined if both the condition and at least one of the then-else arguments might be defined. Otherwise it is definitely undefined. Note that, in this example, we use ite in the traditional sense of functional programming. As an example of the application of EVAL to the abstract interpretation of functional languages, we choose F := {ite : + × + × + → } and Var = {x : , f : + → , p : + → , I : I( f , p, f (x)), x). It essentially describes an iterated application of some function f until a predicate p holds. In order to show that ϕ is strict in x for given functions f 0 and p 0 , one needs to evaluate ϕ( f 0 , p 0 , 0) by fixpoint unfolding and β -reduction. If p 0 (0) = 0, that is, the termination predicate is itself strict, then EVAL terminates in one step proving strictness of ϕ in its third argument. If p 0 (0) = 1, that is, p is essentially a constant true or constant false predicate, we need to evaluate 1 ∧ (ϕ( f 0 , p 0 , f 0 (0)) ∨ 0) = ϕ( f 0 , p 0 , f 0 (0)) next. If f 0 (0) = 0, that is, f 0 is strict itself, we have reached a fixpoint and can conclude strictness in x as well.
If, however, f 0 (0) = 1, we obtain an overall result of 1, not showing strictness in x. This is plausible for constant functions f and p. Using local iteration this is in fact the only computation that takes place, whereas a naïve global fixpoint computation would start by tabulating all possible triples of type ( + → ) + × ( + → ) + × + , which, for the lattice 2, amounts to 4 · 4 · 2 = 32 table columns.

Limitations of Neededness Analysis and Optimisation
As mentioned in the introduction to Sect. 3, Algorithm EVAL does not use local evaluation on operandside subterms but rather computes their value fully. If such an operand has a function type, its value on all its arguments might not be needed either. Consider the first example from Sect. 4 about formal-language constrained reachability problems. Clearly, the values of the order-1-functions stored in the parameters f and g are not needed at most arguments. Hence, computing their value fully appears to be wasteful.
Algorithm EVAL computes values of operand-side subterms fully due to the termination criterion for the computation of fixpoint terms: iteration stops when both no new argument tuples have been discovered during a round of the repeat-loop computing the semantics, and the value of the fixpoint in question is stable on all existing tuples. This, of course, requires some way of deciding whether a discovered argument is actually new. Going back to the example in Sect. 4, Algorithm EVAL successively discovers the argument tuples [a, b, c(0)], [a 2 , b 2 , c 2 (0)], . . . Eventually, these argument tuples begin to repeat, which is when the loop terminates. However, deciding whether e.g. [a i , b i , c i (0)] is the same argument tuple as [a j , b j , c j (0)] requires knowing the value of the function type arguments at all their arguments. One could assume that it is enough to know just their value on arguments actually needed in the iteration, but this approach fails readily: already for [a, b, c(0)] and [a 2 , b 2 , c 2 (0)], for n ≥ 2, we see that c i (0) = 3n − (i + 1) for i ∈ {1, 2}, whence a i (b i (c i (0))) = ⊥ for either i, and, in fact, all i ≤ n(n − 1)(n − 2), since these differ on hitherto undiscovered arguments. Hence, any algorithm that tests equality of function type arguments only on tuples already identified as necessary for the computation must fail here. Moreover, since the base functions a, b, c are actually interpreted, instead of e.g. tree constructors as in the case of higher-order model checking, a simple flow analysis (e.g. 0-CFA) fails to detect which functions are duplicates unless one also inspects the behavior of the base functions. Hence, safe approach to avoid the error sketched above is to compute values of argument-side functions -which are necessarily not of the highest type order occurring in the term under consideration -in full.
However, this does not mean that this is always necessary. In the example from Sect. 4, one can readily see that the value of e.g. f will always be ⊥ on all arguments that are not in {0, . . . , n − 1}, since f only contains powers of a. This kind of domain-specific approach, together with e.g. flow analysis and the choice of an appropriate lattice, could be used to cut down the amount of computations necessary.

Conclusion
We have lifted the notion of local fixpoint iteration, resp. neededness analysis, for the evaluation of first-order fixpoint functions to fixpoint functions at arbitrary higher order. For generality purposes we have defined an abstract algebra µHO combining a simply typed λ -calculus over (possibly higher-order) base functions with fixpoints at arbitrary type orders. The examples in Sect. 4 show that this can vastly reduce the number of values that are being computed in fixpoint iterations, compared to the naïve global approach.
A conceptual implementation of µHO and Alg. 1 is available. 4 It does not compete with specialised tools like higher-order model checkers but rather focuses on displaying the effect that local fixpoint iteration has in comparison to global iteration for higher-order fixpoints.
Work on fixpoint iteration for higher-order functions can be continued in several directions. The most pressing issue is an extension to fully local fixpoint iteration, which would also employ local evaluation at orders beneath the top one, bearing in mind the obstacles to overcome which have been discussed in Sect. 5. Significant progress on this front likely requires giving up the full genericity of the algorithm. For example, many intersection-type based HORS model checkers (e.g. [9,30]) require backwards reasoning alongside the base functions. For example, acceptance of an automaton in a node of a tree depends on its children, i.e. the arguments to the tree constructor in question, and the relationship is readily available. Conversely, in the present form, our algorithm makes no assumptions on the (behavior of) the base functions, whence it can not infer which values of a given argument might yield a desired function value.
The acute reader may have wondered why µHO does not feature operators ⊔, ⊓ for suprema and infima at arbitrary types. It would in fact be possible to add these, and algorithm EVAL can be extended accordingly to handle them just like other base functions are being handled. They are not included in the syntax of µHO here for the following reason: when ⊔, ⊓ are present in the syntax one would expect the distributivity laws like ϕ ⊔ (ψ ⊓ χ) ≡ (ϕ ⊓ ψ) ⊔ (ϕ ⊓ χ) to hold. But in arbitrary lattices, such laws do not necessarily hold; they only do in distributive latttices. In order not to confuse the issue or make false assumptions we therefore prefer to introduce ⊔, ⊓ as base functions when necessary and appropriate. This prevents us from restricting the semantics of µHO terms to distributive lattices only. Note that the lattices depicted in Figs. 3 and 4 are not distributive.
Algorithm EVAL makes no assumptions on the order in which needed arguments are evaluated. In data flow analyses, giving precedence to the arguments in the form of heuristics has turned out to be beneficial for efficiency purposes, c.f. [28,Chp. 6]. It remains to be seen whether such heuristics can be extended to higher orders as well.
Most static program analyses in abstract interpretation work with rather rich lattices as base domains which cannot be cast into the scheme of a simply typed λ -calculus over a single base type as it is used here. We remark, though, that an extension to a many-sorted logic over several base types is straightforward, not only regarding the type system but, most importantly, algorithm EVAL. The same holds for product types on the right of function arrows. It then remains to be seen how far the type system can be enriched without seriously interfering with the ability to evaluate higher-order fixpoints locally.