We consider the system pical. Alphabet: NIL : [] --> A in : [] --> N -> (N -> A) -> A new : [] --> (N -> A) -> A out : [] --> N -> N -> A -> A sum : [] --> A -> A -> A tau : [] --> A -> A Rules: sum NIL x => x new (/\x.y) => y new (/\x.sum (f x) (g x)) => sum (new (/\y.f y)) (new (/\z.g z)) new (/\x.out x y (f x)) => NIL new (/\x.out y z (f x)) => out y z (new (/\u.f u)) new (/\x.in y (/\z.f x z)) => in y (/\u.new (/\v.f v u)) new (/\x.tau (f x)) => tau (new (/\y.f y)) new (/\x.in x (/\y.f x y)) => NIL Using the transformations described in [Kop11], this system can be brought in a form without leading free variables in the left-hand side, and where the left-hand side of a variable is always a functional term or application headed by a functional term. We now transform the resulting AFS into an AFSM by replacing all free variables by meta-variables (with arity 0). This leads to the following AFSM: Alphabet: NIL : [] --> A in : [N * N -> A] --> A new : [N -> A] --> A out : [N * N * A] --> A sum : [A * A] --> A tau : [A] --> A ~AP1 : [N -> A * N] --> A ~AP2 : [N -> N -> A * N] --> N -> A Rules: sum(NIL, X) => X new(/\x.X) => X new(/\x.sum(~AP1(F, x), ~AP1(G, x))) => sum(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) new(/\x.out(x, X, ~AP1(F, x))) => NIL new(/\x.out(X, Y, ~AP1(F, x))) => out(X, Y, new(/\y.~AP1(F, y))) new(/\x.in(X, /\y.~AP1(~AP2(F, x), y))) => in(X, /\z.new(/\u.~AP1(~AP2(F, u), z))) new(/\x.tau(~AP1(F, x))) => tau(new(/\y.~AP1(F, y))) new(/\x.in(x, /\y.~AP1(~AP2(F, x), y))) => NIL ~AP1(F, X) => F X ~AP2(F, X) => F X Symbol ~AP2 is an encoding for application that is only used in innocuous ways. We can simplify the program (without losing non-termination) by removing it. This gives: Alphabet: NIL : [] --> A in : [N * N -> A] --> A new : [N -> A] --> A out : [N * N * A] --> A sum : [A * A] --> A tau : [A] --> A ~AP1 : [N -> A * N] --> A Rules: sum(NIL, X) => X new(/\x.X) => X new(/\x.sum(~AP1(F, x), ~AP1(G, x))) => sum(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) new(/\x.out(x, X, ~AP1(F, x))) => NIL new(/\x.out(X, Y, ~AP1(F, x))) => out(X, Y, new(/\y.~AP1(F, y))) new(/\x.in(X, /\y.~AP1(F(x), y))) => in(X, /\z.new(/\u.~AP1(F(u), z))) new(/\x.tau(~AP1(F, x))) => tau(new(/\y.~AP1(F, y))) new(/\x.in(x, /\y.~AP1(F(x), y))) => NIL ~AP1(F, X) => F X We observe that the rules contain a first-order subset: sum(NIL, X) => X Moreover, the system is finitely branching. Thus, by [Kop12, Thm. 7.55], we may omit all first-order dependency pairs from the dependency pair problem (DP(R), R) if this first-order part is Ce-terminating when seen as a many-sorted first-order TRS. According to the external first-order termination prover, this system is indeed Ce-terminating: || proof of resources/system.trs || # AProVE Commit ID: d84c10301d352dfd14de2104819581f4682260f5 fuhs 20130616 || || || Termination w.r.t. Q of the given QTRS could be proven: || || (0) QTRS || (1) QTRSRRRProof [EQUIVALENT] || (2) QTRS || (3) RisEmptyProof [EQUIVALENT] || (4) YES || || || ---------------------------------------- || || (0) || Obligation: || Q restricted rewrite system: || The TRS R consists of the following rules: || || sum(NIL, %X) -> %X || ~PAIR(%X, %Y) -> %X || ~PAIR(%X, %Y) -> %Y || || Q is empty. || || ---------------------------------------- || || (1) QTRSRRRProof (EQUIVALENT) || Used ordering: || Polynomial interpretation [POLO]: || || POL(NIL) = 2 || POL(sum(x_1, x_2)) = 2 + 2*x_1 + x_2 || POL(~PAIR(x_1, x_2)) = 2 + x_1 + x_2 || With this ordering the following rules can be removed by the rule removal processor [LPAR04] because they are oriented strictly: || || sum(NIL, %X) -> %X || ~PAIR(%X, %Y) -> %X || ~PAIR(%X, %Y) -> %Y || || || || || ---------------------------------------- || || (2) || Obligation: || Q restricted rewrite system: || R is empty. || Q is empty. || || ---------------------------------------- || || (3) RisEmptyProof (EQUIVALENT) || The TRS R is empty. Hence, termination is trivially proven. || ---------------------------------------- || || (4) || YES || We use the dependency pair framework as described in [Kop12, Ch. 6/7], with dynamic dependency pairs. After applying [Kop12, Thm. 7.22] to denote collapsing dependency pairs in an extended form, we thus obtain the following dependency pair problem (P_0, R_0, minimal, all): Dependency Pairs P_0: 0] new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> sum#(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) 1] new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> new#(/\y.~AP1(F, y)) 2] new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> ~AP1#(F, y) 3] new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> new#(/\y.~AP1(G, y)) 4] new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> ~AP1#(G, y) 5] new#(/\x.out(X, Y, ~AP1(F, x))) =#> new#(/\y.~AP1(F, y)) 6] new#(/\x.out(X, Y, ~AP1(F, x))) =#> ~AP1#(F, y) 7] new#(/\x.in(X, /\y.~AP1(F(x), y))) =#> new#(/\z.~AP1(F(z), u)) 8] new#(/\x.in(X, /\y.~AP1(F(x), y))) =#> ~AP1#(F(z), u) 9] new#(/\x.in(X, /\y.~AP1(F(x), y))) =#> F(z) 10] new#(/\x.tau(~AP1(F, x))) =#> new#(/\y.~AP1(F, y)) 11] new#(/\x.tau(~AP1(F, x))) =#> ~AP1#(F, y) 12] ~AP1#(F, X) =#> F(X) Rules R_0: sum(NIL, X) => X new(/\x.X) => X new(/\x.sum(~AP1(F, x), ~AP1(G, x))) => sum(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) new(/\x.out(x, X, ~AP1(F, x))) => NIL new(/\x.out(X, Y, ~AP1(F, x))) => out(X, Y, new(/\y.~AP1(F, y))) new(/\x.in(X, /\y.~AP1(F(x), y))) => in(X, /\z.new(/\u.~AP1(F(u), z))) new(/\x.tau(~AP1(F, x))) => tau(new(/\y.~AP1(F, y))) new(/\x.in(x, /\y.~AP1(F(x), y))) => NIL ~AP1(F, X) => F X Thus, the original system is terminating if (P_0, R_0, minimal, all) is finite. We consider the dependency pair problem (P_0, R_0, minimal, all). We place the elements of P in a dependency graph approximation G (see e.g. [Kop12, Thm. 7.27, 7.29], as follows: * 0 : * 1 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 * 2 : * 3 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 * 4 : * 5 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 * 6 : * 7 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 * 8 : * 9 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 * 10 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 * 11 : * 12 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 This graph has the following strongly connected components: P_1: new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> new#(/\y.~AP1(F, y)) new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) =#> new#(/\y.~AP1(G, y)) new#(/\x.out(X, Y, ~AP1(F, x))) =#> new#(/\y.~AP1(F, y)) new#(/\x.in(X, /\y.~AP1(F(x), y))) =#> new#(/\z.~AP1(F(z), u)) new#(/\x.in(X, /\y.~AP1(F(x), y))) =#> F(z) new#(/\x.tau(~AP1(F, x))) =#> new#(/\y.~AP1(F, y)) ~AP1#(F, X) =#> F(X) 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). Thus, the original system is terminating if (P_1, R_0, minimal, all) is finite. We consider the dependency pair problem (P_1, R_0, minimal, all). 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: new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) >? new#(/\y.~AP1(F, y)) new#(/\x.sum(~AP1(F, x), ~AP1(G, x))) >? new#(/\y.~AP1(G, y)) new#(/\x.out(X, Y, ~AP1(F, x))) >? new#(/\y.~AP1(F, y)) new#(/\x.in(X, /\y.~AP1(F(x), y))) >? new#(/\z.~AP1(F(z), ~c0)) new#(/\x.in(X, /\y.~AP1(F(x), y))) >? F(~c2) ~c1 new#(/\x.tau(~AP1(F, x))) >? new#(/\y.~AP1(F, y)) ~AP1#(F, X) >? F(X) sum(NIL, X) >= X new(/\x.X) >= X new(/\x.sum(~AP1(F, x), ~AP1(G, x))) >= sum(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) new(/\x.out(x, X, ~AP1(F, x))) >= NIL new(/\x.out(X, Y, ~AP1(F, x))) >= out(X, Y, new(/\y.~AP1(F, y))) new(/\x.in(X, /\y.~AP1(F(x), y))) >= in(X, /\z.new(/\u.~AP1(F(u), z))) new(/\x.tau(~AP1(F, x))) >= tau(new(/\y.~AP1(F, y))) new(/\x.in(x, /\y.~AP1(F(x), y))) >= NIL ~AP1(F, X) >= F X new(F) >= new#(F) ~AP1(F, X) >= ~AP1#(F, X) We apply [Kop12, Thm. 6.75] and use the following argument functions: pi( ~AP1#(F, X) ) = #argfun-~AP1##(F X) We orient these requirements with a polynomial interpretation in the natural numbers. The following interpretation satisfies the requirements: #argfun-~AP1## = \y0.y0 NIL = 0 in = \y0G1.3 + 2y0 + G1(0) + G1(y0) new = \G0.2 + 3G0(0) new# = \G0.3G0(0) out = \y0y1y2.3 + 2y0 + 2y1 + 2y2 sum = \y0y1.3 + y1 + 2y0 tau = \y0.3 + 3y0 ~AP1 = \G0y1.2 + 2y1 + 2G0(0) + 2G0(y1) ~AP1# = \G0y1.0 ~c0 = 0 ~c1 = 0 ~c2 = 0 Using this interpretation, the requirements translate to: [[new#(/\x.sum(~AP1(_F0, x), ~AP1(_F1, x)))]] = 27 + 12F1(0) + 24F0(0) > 6 + 12F0(0) = [[new#(/\x.~AP1(_F0, x))]] [[new#(/\x.sum(~AP1(_F0, x), ~AP1(_F1, x)))]] = 27 + 12F1(0) + 24F0(0) > 6 + 12F1(0) = [[new#(/\x.~AP1(_F1, x))]] [[new#(/\x.out(_x0, _x1, ~AP1(_F2, x)))]] = 21 + 6x0 + 6x1 + 24F2(0) > 6 + 12F2(0) = [[new#(/\x.~AP1(_F2, x))]] [[new#(/\x.in(_x0, /\y.~AP1(_F1(x), y)))]] = 21 + 12x0 + 6F1(0,x0) + 18F1(0,0) > 6 + 12F1(0,0) = [[new#(/\x.~AP1(_F1(x), ~c0))]] [[new#(/\x.in(_x0, /\y.~AP1(_F1(x), y)))]] = 21 + 12x0 + 6F1(0,x0) + 18F1(0,0) > F1(0,0) = [[_F1(~c2) ~c1]] [[new#(/\x.tau(~AP1(_F0, x)))]] = 27 + 36F0(0) > 6 + 12F0(0) = [[new#(/\x.~AP1(_F0, x))]] [[#argfun-~AP1##(_F0 _x1)]] = max(x1, F0(x1)) >= F0(x1) = [[_F0(_x1)]] [[sum(NIL, _x0)]] = 3 + x0 >= x0 = [[_x0]] [[new(/\x._x0)]] = 2 + 3x0 >= x0 = [[_x0]] [[new(/\x.sum(~AP1(_F0, x), ~AP1(_F1, x)))]] = 29 + 12F1(0) + 24F0(0) >= 27 + 12F1(0) + 24F0(0) = [[sum(new(/\x.~AP1(_F0, x)), new(/\y.~AP1(_F1, y)))]] [[new(/\x.out(x, _x0, ~AP1(_F1, x)))]] = 23 + 6x0 + 24F1(0) >= 0 = [[NIL]] [[new(/\x.out(_x0, _x1, ~AP1(_F2, x)))]] = 23 + 6x0 + 6x1 + 24F2(0) >= 19 + 2x0 + 2x1 + 24F2(0) = [[out(_x0, _x1, new(/\x.~AP1(_F2, x)))]] [[new(/\x.in(_x0, /\y.~AP1(_F1(x), y)))]] = 23 + 12x0 + 6F1(0,x0) + 18F1(0,0) >= 19 + 8x0 + 6F1(0,x0) + 18F1(0,0) = [[in(_x0, /\x.new(/\y.~AP1(_F1(y), x)))]] [[new(/\x.tau(~AP1(_F0, x)))]] = 29 + 36F0(0) >= 27 + 36F0(0) = [[tau(new(/\x.~AP1(_F0, x)))]] [[new(/\x.in(x, /\y.~AP1(_F0(x), y)))]] = 23 + 24F0(0,0) >= 0 = [[NIL]] [[~AP1(_F0, _x1)]] = 2 + 2x1 + 2F0(0) + 2F0(x1) >= max(x1, F0(x1)) = [[_F0 _x1]] [[new(_F0)]] = 2 + 3F0(0) >= 3F0(0) = [[new#(_F0)]] [[~AP1(_F0, _x1)]] = 2 + 2x1 + 2F0(0) + 2F0(x1) >= max(x1, F0(x1)) = [[#argfun-~AP1##(_F0 _x1)]] By the observations in [Kop12, Sec. 6.6], this reduction pair suffices; we may thus replace the dependency pair problem (P_1, R_0, minimal, all) by (P_2, R_0, minimal, all), where P_2 consists of: ~AP1#(F, X) =#> F(X) Thus, the original system is terminating if (P_2, R_0, minimal, all) is finite. We consider the dependency pair problem (P_2, R_0, minimal, all). 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: ~AP1#(F, X) >? F(X) sum(NIL, X) >= X new(/\x.X) >= X new(/\x.sum(~AP1(F, x), ~AP1(G, x))) >= sum(new(/\y.~AP1(F, y)), new(/\z.~AP1(G, z))) new(/\x.out(x, X, ~AP1(F, x))) >= NIL new(/\x.out(X, Y, ~AP1(F, x))) >= out(X, Y, new(/\y.~AP1(F, y))) new(/\x.in(X, /\y.~AP1(F(x), y))) >= in(X, /\z.new(/\u.~AP1(F(u), z))) new(/\x.tau(~AP1(F, x))) >= tau(new(/\y.~AP1(F, y))) new(/\x.in(x, /\y.~AP1(F(x), y))) >= NIL ~AP1(F, X) >= F X ~AP1(F, X) >= ~AP1#(F, X) We apply [Kop12, Thm. 6.75] and use the following argument functions: pi( ~AP1#(F, X) ) = #argfun-~AP1##(F X) We orient these requirements with a polynomial interpretation in the natural numbers. The following interpretation satisfies the requirements: #argfun-~AP1## = \y0.1 + y0 NIL = 0 in = \y0G1.3 + y0 + G1(0) new = \G0.2 + 3G0(0) out = \y0y1y2.3 + y0 + y1 + y2 sum = \y0y1.3 + y0 + y1 tau = \y0.y0 ~AP1 = \G0y1.3 + y1 + G0(y1) ~AP1# = \G0y1.0 Using this interpretation, the requirements translate to: [[#argfun-~AP1##(_F0 _x1)]] = 1 + max(x1, F0(x1)) > F0(x1) = [[_F0(_x1)]] [[sum(NIL, _x0)]] = 3 + x0 >= x0 = [[_x0]] [[new(/\x._x0)]] = 2 + 3x0 >= x0 = [[_x0]] [[new(/\x.sum(~AP1(_F0, x), ~AP1(_F1, x)))]] = 29 + 3F0(0) + 3F1(0) >= 25 + 3F0(0) + 3F1(0) = [[sum(new(/\x.~AP1(_F0, x)), new(/\y.~AP1(_F1, y)))]] [[new(/\x.out(x, _x0, ~AP1(_F1, x)))]] = 20 + 3x0 + 3F1(0) >= 0 = [[NIL]] [[new(/\x.out(_x0, _x1, ~AP1(_F2, x)))]] = 20 + 3x0 + 3x1 + 3F2(0) >= 14 + x0 + x1 + 3F2(0) = [[out(_x0, _x1, new(/\x.~AP1(_F2, x)))]] [[new(/\x.in(_x0, /\y.~AP1(_F1(x), y)))]] = 20 + 3x0 + 3F1(0,0) >= 14 + x0 + 3F1(0,0) = [[in(_x0, /\x.new(/\y.~AP1(_F1(y), x)))]] [[new(/\x.tau(~AP1(_F0, x)))]] = 11 + 3F0(0) >= 11 + 3F0(0) = [[tau(new(/\x.~AP1(_F0, x)))]] [[new(/\x.in(x, /\y.~AP1(_F0(x), y)))]] = 20 + 3F0(0,0) >= 0 = [[NIL]] [[~AP1(_F0, _x1)]] = 3 + x1 + F0(x1) >= max(x1, F0(x1)) = [[_F0 _x1]] [[~AP1(_F0, _x1)]] = 3 + x1 + F0(x1) >= 1 + max(x1, F0(x1)) = [[#argfun-~AP1##(_F0 _x1)]] 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. As all dependency pair problems were succesfully simplified with sound (and complete) processors until nothing remained, we conclude termination. +++ Citations +++ [Kop11] C. Kop. Simplifying Algebraic Functional Systems. In Proceedings of CAI 2011, volume 6742 of LNCS. 201--215, Springer, 2011. [Kop12] C. Kop. Higher Order Termination. PhD Thesis, 2012.