We consider the system plode. Alphabet: cons : [nat * list] --> list explode : [list * nat -> nat * nat] --> nat implode : [list * nat -> nat * nat] --> nat nil : [] --> list op : [nat -> nat * nat -> nat] --> nat -> nat Rules: op(f, g) x => f (g x) implode(nil, f, x) => x implode(cons(x, y), f, z) => implode(y, f, f z) explode(nil, f, x) => x explode(cons(x, y), f, z) => explode(y, op(f, f), f z) This AFS is converted to an AFSM simply by replacing all free variables by meta-variables (with arity 0). We use the dependency pair framework as described in [Kop12, Ch. 6/7], with static dependency pairs (see [KusIsoSakBla09] and the adaptation for AFSMs and accessible arguments in [Kop13]). In order to do so, we start by eta-expanding the system, which gives: op(F, G, X) => F (G X) implode(nil, F, X) => X implode(cons(X, Y), F, Z) => implode(Y, F, F Z) explode(nil, F, X) => X explode(cons(X, Y), F, Z) => explode(Y, /\x.op(F, F, x), F Z) We thus obtain the following dependency pair problem (P_0, R_0, static, formative): Dependency Pairs P_0: 0] implode#(cons(X, Y), F, Z) =#> implode#(Y, F, F Z) 1] explode#(cons(X, Y), F, Z) =#> explode#(Y, /\x.op(F, F, x), F Z) 2] explode#(cons(X, Y), F, Z) =#> op#(F, F, U) Rules R_0: op(F, G, X) => F (G X) implode(nil, F, X) => X implode(cons(X, Y), F, Z) => implode(Y, F, F Z) explode(nil, F, X) => X explode(cons(X, Y), F, Z) => explode(Y, /\x.op(F, F, x), F Z) Thus, the original system is terminating if (P_0, R_0, static, formative) is finite. We consider the dependency pair problem (P_0, R_0, static, formative). We place the elements of P in a dependency graph approximation G (see e.g. [Kop12, Thm. 7.27, 7.29], as follows: * 0 : 0 * 1 : 1, 2 * 2 : This graph has the following strongly connected components: P_1: implode#(cons(X, Y), F, Z) =#> implode#(Y, F, F Z) P_2: explode#(cons(X, Y), F, Z) =#> explode#(Y, /\x.op(F, F, x), F Z) By [Kop12, Thm. 7.31], we may replace any dependency pair problem (P_0, R_0, m, f) by (P_1, R_0, m, f) and (P_2, R_0, m, f). Thus, the original system is terminating if each of (P_1, R_0, static, formative) and (P_2, R_0, static, formative) is finite. We consider the dependency pair problem (P_2, R_0, static, formative). We will use the reduction pair processor [Kop12, Thm. 7.16]. It suffices to find a standard reduction pair [Kop12, Def. 6.69]. Thus, we must orient: explode#(cons(X, Y), F, Z) >? explode#(Y, /\x.op(F, F, x), F Z) op(F, G, X) >= F (G X) implode(nil, F, X) >= X implode(cons(X, Y), F, Z) >= implode(Y, F, F Z) explode(nil, F, X) >= X explode(cons(X, Y), F, Z) >= explode(Y, /\x.op(F, F, x), F Z) We apply [Kop12, Thm. 6.75] and use the following argument functions: pi( op(F, G, X) ) = #argfun-op#(F (G X)) Since this representation is not advantageous for the higher-order recursive path ordering, we present the strict requirements in their unextended form, which is not problematic since for any F, s and substituion gamma: (F s)gamma beta-reduces to F(s)gamma.) We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[explode(x_1, x_2, x_3)]] = explode(x_1, x_3, x_2) [[explode#(x_1, x_2, x_3)]] = x_1 We choose Lex = {explode, implode} and Mul = {#argfun-op#, @_{o -> o}, cons, nil, op}, and the following precedence: implode > explode > @_{o -> o} > nil > op > cons > #argfun-op# Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: cons(X, Y) > Y #argfun-op#(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) implode(nil, F, X) >= X implode(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) explode(nil, F, X) >= X explode(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) With these choices, we have: 1] cons(X, Y) > Y because [2], by definition 2] cons*(X, Y) >= Y because [3], by (Select) 3] Y >= Y by (Meta) 4] #argfun-op#(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) because [5], by (Star) 5] #argfun-op#*(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) because [6], by (Select) 6] @_{o -> o}(F, @_{o -> o}(G, X)) >= @_{o -> o}(F, @_{o -> o}(G, X)) because @_{o -> o} in Mul, [7] and [8], by (Fun) 7] F >= F by (Meta) 8] @_{o -> o}(G, X) >= @_{o -> o}(G, X) because @_{o -> o} in Mul, [9] and [10], by (Fun) 9] G >= G by (Meta) 10] X >= X by (Meta) 11] implode(nil, F, X) >= X because [12], by (Star) 12] implode*(nil, F, X) >= X because [13], by (Select) 13] X >= X by (Meta) 14] implode(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) because [15], by (Star) 15] implode*(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) because [16], [19], [21] and [23], by (Stat) 16] cons(X, Y) > Y because [17], by definition 17] cons*(X, Y) >= Y because [18], by (Select) 18] Y >= Y by (Meta) 19] implode*(cons(X, Y), F, Z) >= Y because [20], by (Select) 20] cons(X, Y) >= Y because [17], by (Star) 21] implode*(cons(X, Y), F, Z) >= F because [22], by (Select) 22] F >= F by (Meta) 23] implode*(cons(X, Y), F, Z) >= @_{o -> o}(F, Z) because implode > @_{o -> o}, [21] and [24], by (Copy) 24] implode*(cons(X, Y), F, Z) >= Z because [25], by (Select) 25] Z >= Z by (Meta) 26] explode(nil, F, X) >= X because [27], by (Star) 27] explode*(nil, F, X) >= X because [28], by (Select) 28] X >= X by (Meta) 29] explode(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) because [30], by (Star) 30] explode*(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) because [31], [32], [34] and [42], by (Stat) 31] cons(X, Y) > Y because [2], by definition 32] explode*(cons(X, Y), F, Z) >= Y because [33], by (Select) 33] cons(X, Y) >= Y because [2], by (Star) 34] explode*(cons(X, Y), F, Z) >= /\y.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, y))) because [35], by (F-Abs) 35] explode*(cons(X, Y), F, Z, x) >= #argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))) because explode > #argfun-op# and [36], by (Copy) 36] explode*(cons(X, Y), F, Z, x) >= @_{o -> o}(F, @_{o -> o}(F, x)) because explode > @_{o -> o}, [37] and [39], by (Copy) 37] explode*(cons(X, Y), F, Z, x) >= F because [38], by (Select) 38] F >= F by (Meta) 39] explode*(cons(X, Y), F, Z, x) >= @_{o -> o}(F, x) because explode > @_{o -> o}, [37] and [40], by (Copy) 40] explode*(cons(X, Y), F, Z, x) >= x because [41], by (Select) 41] x >= x by (Var) 42] explode*(cons(X, Y), F, Z) >= @_{o -> o}(F, Z) because explode > @_{o -> o}, [43] and [44], by (Copy) 43] explode*(cons(X, Y), F, Z) >= F because [38], by (Select) 44] explode*(cons(X, Y), F, Z) >= Z because [45], by (Select) 45] Z >= Z by (Meta) By the observations in [Kop12, Sec. 6.6], this reduction pair suffices; we may thus replace a dependency pair problem (P_2, R_0) by ({}, R_0). By the empty set processor [Kop12, Thm. 7.15] this problem may be immediately removed. Thus, the original system is terminating if (P_1, R_0, static, formative) is finite. We consider the dependency pair problem (P_1, R_0, static, formative). We will use the reduction pair processor [Kop12, Thm. 7.16]. It suffices to find a standard reduction pair [Kop12, Def. 6.69]. Thus, we must orient: implode#(cons(X, Y), F, Z) >? implode#(Y, F, F Z) op(F, G, X) >= F (G X) implode(nil, F, X) >= X implode(cons(X, Y), F, Z) >= implode(Y, F, F Z) explode(nil, F, X) >= X explode(cons(X, Y), F, Z) >= explode(Y, /\x.op(F, F, x), F Z) We apply [Kop12, Thm. 6.75] and use the following argument functions: pi( op(F, G, X) ) = #argfun-op#(F (G X)) Since this representation is not advantageous for the higher-order recursive path ordering, we present the strict requirements in their unextended form, which is not problematic since for any F, s and substituion gamma: (F s)gamma beta-reduces to F(s)gamma.) We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[explode(x_1, x_2, x_3)]] = explode(x_1, x_3, x_2) [[implode#(x_1, x_2, x_3)]] = implode#(x_2, x_1, x_3) We choose Lex = {explode, implode, implode#} and Mul = {#argfun-op#, @_{o -> o}, cons, nil, op}, and the following precedence: cons > explode > implode > implode# > @_{o -> o} > #argfun-op# > nil > op Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: implode#(cons(X, Y), F, Z) > implode#(Y, F, @_{o -> o}(F, Z)) #argfun-op#(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) implode(nil, F, X) >= X implode(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) explode(nil, F, X) >= X explode(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) With these choices, we have: 1] implode#(cons(X, Y), F, Z) > implode#(Y, F, @_{o -> o}(F, Z)) because [2], by definition 2] implode#*(cons(X, Y), F, Z) >= implode#(Y, F, @_{o -> o}(F, Z)) because [3], [6], [7], [9] and [10], by (Stat) 3] cons(X, Y) > Y because [4], by definition 4] cons*(X, Y) >= Y because [5], by (Select) 5] Y >= Y by (Meta) 6] F >= F by (Meta) 7] implode#*(cons(X, Y), F, Z) >= Y because [8], by (Select) 8] cons(X, Y) >= Y because [4], by (Star) 9] implode#*(cons(X, Y), F, Z) >= F because [6], by (Select) 10] implode#*(cons(X, Y), F, Z) >= @_{o -> o}(F, Z) because implode# > @_{o -> o}, [9] and [11], by (Copy) 11] implode#*(cons(X, Y), F, Z) >= Z because [12], by (Select) 12] Z >= Z by (Meta) 13] #argfun-op#(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) because [14], by (Star) 14] #argfun-op#*(@_{o -> o}(F, @_{o -> o}(G, X))) >= @_{o -> o}(F, @_{o -> o}(G, X)) because [15], by (Select) 15] @_{o -> o}(F, @_{o -> o}(G, X)) >= @_{o -> o}(F, @_{o -> o}(G, X)) because @_{o -> o} in Mul, [16] and [17], by (Fun) 16] F >= F by (Meta) 17] @_{o -> o}(G, X) >= @_{o -> o}(G, X) because @_{o -> o} in Mul, [18] and [19], by (Fun) 18] G >= G by (Meta) 19] X >= X by (Meta) 20] implode(nil, F, X) >= X because [21], by (Star) 21] implode*(nil, F, X) >= X because [22], by (Select) 22] X >= X by (Meta) 23] implode(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) because [24], by (Star) 24] implode*(cons(X, Y), F, Z) >= implode(Y, F, @_{o -> o}(F, Z)) because [3], [25], [26] and [27], by (Stat) 25] implode*(cons(X, Y), F, Z) >= Y because [8], by (Select) 26] implode*(cons(X, Y), F, Z) >= F because [6], by (Select) 27] implode*(cons(X, Y), F, Z) >= @_{o -> o}(F, Z) because implode > @_{o -> o}, [26] and [28], by (Copy) 28] implode*(cons(X, Y), F, Z) >= Z because [12], by (Select) 29] explode(nil, F, X) >= X because [30], by (Star) 30] explode*(nil, F, X) >= X because [31], by (Select) 31] X >= X by (Meta) 32] explode(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) because [33], by (Star) 33] explode*(cons(X, Y), F, Z) >= explode(Y, /\x.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))), @_{o -> o}(F, Z)) because [34], [37], [39] and [47], by (Stat) 34] cons(X, Y) > Y because [35], by definition 35] cons*(X, Y) >= Y because [36], by (Select) 36] Y >= Y by (Meta) 37] explode*(cons(X, Y), F, Z) >= Y because [38], by (Select) 38] cons(X, Y) >= Y because [35], by (Star) 39] explode*(cons(X, Y), F, Z) >= /\y.#argfun-op#(@_{o -> o}(F, @_{o -> o}(F, y))) because [40], by (F-Abs) 40] explode*(cons(X, Y), F, Z, x) >= #argfun-op#(@_{o -> o}(F, @_{o -> o}(F, x))) because explode > #argfun-op# and [41], by (Copy) 41] explode*(cons(X, Y), F, Z, x) >= @_{o -> o}(F, @_{o -> o}(F, x)) because explode > @_{o -> o}, [42] and [44], by (Copy) 42] explode*(cons(X, Y), F, Z, x) >= F because [43], by (Select) 43] F >= F by (Meta) 44] explode*(cons(X, Y), F, Z, x) >= @_{o -> o}(F, x) because explode > @_{o -> o}, [42] and [45], by (Copy) 45] explode*(cons(X, Y), F, Z, x) >= x because [46], by (Select) 46] x >= x by (Var) 47] explode*(cons(X, Y), F, Z) >= @_{o -> o}(F, Z) because explode > @_{o -> o}, [48] and [49], by (Copy) 48] explode*(cons(X, Y), F, Z) >= F because [43], by (Select) 49] explode*(cons(X, Y), F, Z) >= Z because [50], by (Select) 50] Z >= Z by (Meta) By the observations in [Kop12, Sec. 6.6], this reduction pair suffices; we may thus replace a dependency pair problem (P_1, R_0) by ({}, R_0). By the empty set processor [Kop12, Thm. 7.15] this problem may be immediately removed. As all dependency pair problems were succesfully simplified with sound (and complete) processors until nothing remained, we conclude termination. +++ Citations +++ [Kop12] C. Kop. Higher Order Termination. PhD Thesis, 2012. [Kop13] C. Kop. Static Dependency Pairs with Accessibility. Unpublished manuscript, http://cl-informatik.uibk.ac.at/users/kop/static.pdf, 2013. [KusIsoSakBla09] K. Kusakari, Y. Isogai, M. Sakai, and F. Blanqui. Static Dependency Pair Method Based On Strong Computability for Higher-Order Rewrite Systems. In volume 92(10) of IEICE Transactions on Information and Systems. 2007--2015, 2009.