From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) take n ( from ( S m )) m one could continue with Case , Eval , ParSplit ⇒ infinite tree Instead: Ins rule to obtain finite graphs
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins take n ( from ( S m )) m Ins rule: if leaf t is instance of t ′ , then add instantiation edge from t to t ′ one may re-use an existing node for t ′ , if possible
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins m take n ( from ( S m )) n S m Ins rule: if leaf t is instance of t ′ , then add instantiation edge from t to t ′ since instantiation is [ u/n, m/ ( S m )] , add child nodes n and ( S m )
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins take n ( from ( S m )) m ParSplit rule: S m ParSplit n if head of term is a constructor like S , m then continue with the parameter
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins take n ( from ( S m )) m S m ParSplit n Termination Graph no expansion rule applicable to leaves anymore m Goal: Prove H -termination of all terms in termination graph
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) take n ( from ( S m )) m Ins rule: take n xs if leaf t is instance of t ′ , then add instantiation edge from t to t ′ introduces indeterminism
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) m take n ( from ( S m )) from ( S m ) take n xs Ins rule: if leaf t is instance of t ′ , then add instantiation edge from t to t ′ since instantiation is [ xs / from ( S m )] , add child node from ( S m )
From HASKELL to Termination Graphs from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) m take n ( from ( S m )) from ( S m ) take n xs Ins rule: if leaf t is instance of t ′ , then add instantiation edge from t to t ′ proving H -termination of all terms in termination graph fails!
From HASKELL to Termination Graphs take Z xs = Nil take n Nil = Nil take ( S n ) ( Cons x xs ) = Cons x ( take n xs ) Expansion Rules VarExp take Case Eval VarExp take n ParSplit Ins take n xs VarExp VarExp rule: if function is applied to too few arguments, then add fresh variable as additional argument
From Termination Graphs to TRSs Termination graphs can be obtained for any start term Goal: Prove H -termination of all terms in termination graph First Approach: VarExp take Transform termination graph into TRS ⇒ disadvantageous VarExp take n Better Approach: take n xs Transform termination graph into DP problems Dependency Pairs powerful & popular termination technique for TRSs DP framework allows integration & combination of any TRS-termination technique
Dependency Pair Framework Apply the general idea of problem solving for termination analysis transform problems into simpler sub-problems repeatedly until all problems are solved What objects do we work on, i.e., what are the “ problems ”? DP problems ( P , R ) dependency pairs P DP problems ( P , R ) R rules What techniques do we use for transformation? DP processors: Proc ( ( P , R ) ) = { ( P 1 , R 1 ) , . . . , ( P n , R n ) } When is a problem solved ? ( P , R ) is finite iff there is no infinite ( P , R ) -chain s 1 σ 1 → P t 1 σ 1 → ∗ R s 2 σ 2 → P t 2 σ 2 → ∗ R . . . where s i → t i ∈ P
� Dependency Pair Framework Termination of TRS R Termination of HASKELL generate termination graph for start term construct initial DP problem construct initial DP problems from termination graph ( DP ( R ) , R ) start term is H -terminating if TRS R is terminating iff initial DP problems are finite initial DP problem is finite use DP framework to prove use DP framework to prove that initial DP problems are finite that initial DP problem is finite Start Term � � � � � � � � HASKELL - � Termination � Termination Tool � DP Problems Program Graph ( AProVE )
� Dependency Pair Framework Termination of HASKELL generate termination graph for start term How to construct DP problems construct initial DP problems from termination graph? from termination graph start term is H -terminating if initial DP problems are finite use DP framework to prove that initial DP problems are finite Start Term � � � � � � � � HASKELL - � Termination � Termination Tool � DP Problems Program Graph ( AProVE )
From Termination Graphs to DP Problems higher-order terms can be represented as applicative first-order terms “ x y ” becomes “ ap ( x, y ) ” Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins take n ( from ( S m )) m S m ParSplit n m
From Termination Graphs to DP Problems Goal: Prove H -termination of all terms for each SCC Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins take n ( from ( S m )) m S m ParSplit n if node is not H -terminating, then a child is not H -terminating m not H -terminating node corresponds to SCC
From Termination Graphs to DP Problems every infinite path traverses a DP path infinitely often ⇒ generate a dependency pair for every DP path Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins m take n ( from ( S m )) n S m ParSplit DP path : m path in SCC from node with incoming instantiation edge to node with outgoing instantiation edge
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take n ( from ( S m )) Rules R : termination is easy to prove ∅ Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take n ( from ( S m ))) Ins m take n ( from ( S m )) n S m ParSplit Dependency Pairs : m if there is a DP path from s to t marked with µ , then generate the dependency pair s µ → t
Generating infinite ( P , R ) -chains � Term in graph not terminating s 1 ( τ 1 ↓ H ) not terminating � s 1 ( τ 1 ↓ H ) DP path from s 1 to t 1 marked with µ 1 s 1 ( τ 1 ↓ H ) not terminating Case � take u ( from m ) [ u/ ( S n )] [ u/ Z ] s 1 ( τ 1 ↓ H ) not terminating � Eval takeZ ( from m ) take ( S n ) ( from m ) s 1 µ 1 σ 1 not terminating � Eval take ( S n ) ( Cons m ( from ( S m ))) Nil t 1 µ 1 σ 1 not terminating � ParSplit Cons m ( take n ( from ( S m ))) s 2 ( τ 2 ↓ H ) not terminating � Ins m take n ( from ( S m )) s 1 ( τ 1 ↓ H ) DP path from s 2 to t 2 marked with µ 2 n S m ParSplit s 2 ( τ 2 ↓ H ) not terminating � m s 2 µ 2 σ 2 not terminating � t 2 µ 2 σ 2 not terminating � s 1 µ 1 σ 1 → P t 1 σ 1 s 2 µ 2 σ 2 s 2 µ 2 σ 2 s 2 µ 2 σ 2 → P t 2 σ 2 R : rules for terms in matcher ���� � �� � � �� � R = ∅ if no defined symbol in matcher s 2 τ 2 → ∗ s 2 ( τ 2 ↓ H ) R
From Termination Graphs to DP Problems from x = Cons x ( from ( S x )) take Z xs = Nil take n Nil = Nil p ( S x )= x take ( S n ) ( Cons x xs )= Cons x ( take ( p ( S n )) xs ) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take ( p ( S n )) ( from ( S m ))) Ins m take ( p ( S n )) ( from ( S m )) Eval p ( S n ) S m ParSplit n m
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take ( p ( S n )) ( from ( S m ))) Ins take ( p ( S n )) ( from ( S m )) m Eval p ( S n ) S m ParSplit R : rules for terms in matcher n m
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take ( p ( S n )) ( from ( S m ))) Ins take ( p ( S n )) ( from ( S m )) m Rule path Eval p ( S n ) S m path from term in matcher ParSplit over Eval - and Case nodes to non- Eval and non- Case node n m
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Rule R : p ( S n ) → n termination easy to prove Case take u ( from m ) [ u/ ( S n )] [ u/ Z ] Eval Eval takeZ ( from m ) take ( S n ) ( from m ) Eval take ( S n ) ( Cons m ( from ( S m ))) Nil ParSplit Cons m ( take ( p ( S n )) ( from ( S m ))) Ins take ( p ( S n )) ( from ( S m )) m Rules if there is a rule path from s to t Eval p ( S n ) S m ParSplit marked with µ , n m then generate the rule s µ → t
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Rule R : p ( S n ) → n Improvement: evaluate rhs of DP as much as possible = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) ev ( t ) : term reachable from t by traversing Eval -nodes ev ( t ) : traverses subterms of ParSplit - and Ins -nodes Ins take ( p ( S n )) ( from ( S m )) Eval p ( S n ) S m ParSplit n m
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Rule R : ∅ Improvement: evaluate rhs of DP as much as possible = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) = ev ( take ev ( p ( S n ) ) ( from ev ( S m )) ) ev ( t ) : term reachable from t by traversing Eval -nodes ev ( t ) : traverses subterms of ParSplit - and Ins -nodes Ins take ( p ( S n )) ( from ( S m )) Rules only needed for terms Eval p ( S n ) S m ParSplit where computation of ev stopped n m
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Improvement: evaluate rhs of DP as much as possible = ev ( take ( p ( S n )) ( from ( S m )) ) Ins = ev ( take ( p ( S n )) ( from ( S m )) ) take ( p ( S n )) ( from ( S m )) Case p ( S n ) S m ParSplit [ n/ ( S x )] [ n/ Z ] Eval Eval p ( S Z ) p ( S ( S x )) m p ( S Z ) = Z p ( S x ) = S ( p x ) ParSplit S ( p ( S x )) Z Ins p ( S x ) x
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Ins take ( p ( S n )) ( from ( S m )) Case p ( S n ) S m ParSplit [ n/ ( S x )] [ n/ Z ] Eval Eval p ( S Z ) p ( S ( S x )) m ParSplit S ( p ( S x )) Z Rule path Ins p ( S x ) path from term in matcher over Eval - and Case nodes to non- Eval and non- Case node x
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Rules R : p ( S Z ) → Z Rules R : p ( S ( S x )) → S ( p ( S x )) Ins take ( p ( S n )) ( from ( S m )) Case p ( S n ) S m ParSplit [ n/ ( S x )] [ n/ Z ] Eval Eval p ( S Z ) p ( S ( S x )) m ParSplit S ( p ( S x )) Z Rules if there is a rule path from s to t Ins p ( S x ) marked with µ , x then generate the rule s µ → t
From Termination Graphs to DP Problems Dependency Pair P : take ( S n ) ( from m ) → take ( p ( S n )) ( from ( S m )) Rules R : p ( S Z ) → Z Rules R : p ( S ( S x )) → S ( p ( S x )) Dependency Pair P : p ( S ( S x )) → p ( S x ) Rules R : ∅ Ins take ( p ( S n )) ( from ( S m )) Case p ( S n ) S m ParSplit [ n/ ( S x )] [ n/ Z ] Eval Eval p ( S Z ) p ( S ( S x )) m ParSplit S ( p ( S x )) Z Ins p ( S x ) one DP problem for each SCC termination is easy to prove x
Termination of HASKELL -Programs New approach in order to use TRS-techniques for HASKELL generate termination graph for given start term extract DP problems from termination graph prove finiteness of DP problems by existing TRS-techniques Implemented in AProVE accepts full HASKELL 98 language successfully evaluated with standard HASKELL -libraries FiniteMap List Maybe Monad Prelude Queue Total 256 166 9 69 489 5 994 YES 321 174 9 80 692 5 1281 TOTAL
� Termination of HASKELL -Programs New approach in order to use TRS-techniques for HASKELL Start Term � � � � � � � � HASKELL - � Termination � Termination Tool � DP Problems Program Graph ( AProVE ) Implemented in AProVE accepts full HASKELL 98 language successfully evaluated with standard HASKELL -libraries FiniteMap List Maybe Monad Prelude Queue Total 256 166 9 69 489 5 994 YES 321 174 9 80 692 5 1281 TOTAL
Overview I. Termination of Term Rewriting 1 Termination of Term Rewrite Systems 2 Non-Termination of Term Rewrite Systems 3 Complexity of Term Rewrite Systems 4 Termination of Integer Term Rewrite Systems II. Termination of Programs 1 Termination of Functional Programs (Haskell) 2 Termination of Logic Programs (Prolog) (PPDP ’12) 3 Termination of Imperative Programs (Java)
Termination of Logic Programming Languages well-developed field (De Schreye & Decorte, 94) etc. direct approaches: work directly on the logic program cTI (Mesnard et al) TerminWeb (Codish et al) TermiLog (Lindenstrauss et al) Polytool (Nguyen, De Schreye, Giesl, Schneider-Kamp) TRS-techniques can be adapted to work directly on the LP transformational approaches: transform LP to TRS TALP (Ohlebusch et al) AProVE (Giesl et al) only for definite LP (without cut) not for real prolog
Termination of Logic Programming Languages analyzing prolog is challenging due to cuts etc. New approach Frontend evaluate prolog a few steps ⇒ symbolic evaluation graph graph captures evaluation strategy due to cuts etc. transform symbolic evaluation graph ⇒ TRS Backend prove termination of the resulting TRS (using existing techniques & tools) implemented in AProVE successfully evaluated on prolog -collections with cuts most powerful termination tool for prolog (winner of termination competition for prolog )
� � � Termination of Logic Programming Languages analyzing prolog is challenging due to cuts etc. haskell - Program ❖ ❖ Symbolic prolog - � Termination Tool � TRS Evaluation Program (AProVE) Graph r r r java - Program implemented in AProVE successfully evaluated on prolog -collections with cuts most powerful termination tool for prolog (winner of termination competition for prolog )
� � � � � � Symbolic Evaluation Graphs and Term Rewriting General methodology for analyzing prolog programs Termination Symbolic prolog - Rewrite Tool TRS Evaluation Program (AProVE) Graph Complexity Determinacy Outline linear operational semantics of prolog from prolog to symbolic evaluation graphs from symbolic evaluation graphs to TRSs for termination analysis from symbolic evaluation graphs to TRSs for complexity analysis determinacy analysis
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) app([ ] , YS , YS ) . (4) app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) . (5) eq( X , X ) . (6) ( t 2 ∈ ( t 1 ) ∗ ) star( t 1 , t 2 ) holds iff t 2 results from concatenation of t 1 star([1 , 2] , [ ]) holds star([1 , 2] , [1 , 2]) holds, since app([1 , 2] , [ ] , [1 , 2]) , star([ 1 , 2 ] , [ ]) hold star([1 , 2] , [1 , 2 , 1 , 2]) holds, etc. cut in clause (2) needed for termination . Otherwise: star([ ] , t ) would lead to app([ ] , YS , t ) , star([ ] , YS ) would lead to star([ ] , t )
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) app([ ] , YS , YS ) . (4) app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) . (5) eq( X , X ) . (6) state: ( G 1 | . . . | G n ) with current goal G 1 and next goals G 2 , . . . , G n goal: ( t 1 , . . . , t k ) c query or goal: ( t 1 , . . . , t k ) c query labeled by clause c used for next resolution inference rules: Case star([1 , 2] , [ ]) ⊢ Case Eval star([1 , 2] , [ ]) (1) | star([1 , 2] , [ ]) (2) | star([1 , 2] , [ ]) (3) ⊢ Eval Back ! 1 | star([1 , 2] , [ ]) (2) | star([1 , 2] , [ ]) (3) ⊢ Cut Cut ⊢ Suc � Suc ε
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) app([ ] , YS , YS ) . (4) app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) . (5) eq( X , X ) . (6) state: ( G 1 | . . . | G n ) with current goal G 1 and next goals G 2 , . . . , G n linear semantics, since state contains all backtracking information ⇒ evaluation is a sequence of states, not a search tree suitable for extension to abstract states star([1 , 2] , [ ]) ⊢ Case star([1 , 2] , [ ]) (1) | star([1 , 2] , [ ]) (2) | star([1 , 2] , [ ]) (3) ⊢ Eval ! 1 | star([1 , 2] , [ ]) (2) | star([1 , 2] , [ ]) (3) ⊢ Cut ⊢ Suc � ε
� � � � � � Symbolic Evaluation Graphs and Term Rewriting General methodology for analyzing prolog programs Termination Symbolic prolog - Rewrite Tool TRS Evaluation Program (AProVE) Graph Complexity Determinacy Outline linear operational semantics of prolog from prolog to symbolic evaluation graphs from symbolic evaluation graphs to TRSs for termination analysis from symbolic evaluation graphs to TRSs for complexity analysis determinacy analysis
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) a star( T 1 , T 2 ) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) Case star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval star( T 1 , T 2 ) ≁ star( XS , [ ]) Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d symbolic evaluation graph: all evaluations for a class of queries class of queries Q p m described by predicate p and moding m Example: Q star = { star( t 1 , t 2 ) | t 1 , t 2 are ground } . m abstract state: stands for set of concrete states state with abstract variables T 1 , T 2 , . . . representing arbitrary terms constraints on the terms represented by T 1 , T 2 , . . . groundness constraints: T 1 , T 2 unification constraints: star( T 1 , T 2 ) ≁ star( XS , [ ])
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) a star( T 1 , T 2 ) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) Case star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval star( T 1 , T 2 ) ≁ star( XS , [ ]) Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval star( T 1 , T 2 ) ≁ star([ ] , ZS ) T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Case . . . abstract state: stands for set of concrete states state with abstract variables T 1 , T 2 , . . . representing arbitrary terms constraints on the terms represented by T 1 , T 2 , . . . groundness constraints: T 1 , T 2 unification constraints: star( T 1 , T 2 ) ≁ star( XS , [ ])
star( XS , [ ]) : - ! . (1) star([ ] , ZS ) : - ! , eq( ZS , [ ]) . (2) T 2 / T 4 a star( T 1 , T 2 ) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . (3) Inst Case star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval star( T 1 , T 2 ) ≁ star( XS , [ ]) Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval star( T 1 , T 2 ) ≁ star([ ] , ZS ) T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . g h app( T 1 , T 3 , T 2 ) star( T 1 , T 4 ) Inst : connection to previous state if current state is an instance Split : split away first atom from a query fresh variables in Split ’s second successor approximate first atom’s answer substitution by groundness analysis
� � � � � � Symbolic Evaluation Graphs and Term Rewriting General methodology for analyzing prolog programs Termination Symbolic prolog - Rewrite Tool TRS Evaluation Program (AProVE) Graph Complexity Determinacy Outline linear operational semantics of prolog from prolog to symbolic evaluation graphs from symbolic evaluation graphs to TRSs for termination analysis from symbolic evaluation graphs to TRSs for complexity analysis determinacy analysis
a star( T 1 , T 2 ) Case Inst star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) Aim: show termination of concrete states represented by graph Solution: synthesize TRS from the graph TRS captures all evaluations that are crucial for termination behavior existing rewrite tools can show termination of TRS ⇒ prove termination of original prolog program
Encoding of f : f in f ( T 1 , T 2 ), f out ( T 3 ) a star( T 1 , T 2 ) f Encoding of a : f in a ( T 1 , T 2 ), f out Case Inst a Encoding of h : f in a ( T 1 , T 4 ), f out star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) encode state s to terms f in s ( . . . ), f out ( . . . ) s • arguments of f in s : abstract ground variables of s ( T 1 , T 2 , . . . ) • arguments of f out : remaining abstract variables of s s which are made ground by every answer substitution of s ( groundness analysis ) for state s with Inst edge to s ′ : use f in s ′ , f out instead of f in s , f out s ′ s
Encoding of f : f in f ( T 1 , T 2 ), f out ( T 3 ) a star( T 1 , T 2 ) f Encoding of a : f in a ( T 1 , T 2 ), f out Case Inst a Encoding of h : f in a ( T 1 , T 4 ), f out star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) encode connection paths to rewrite rules connection path : start state = root, successor of Inst , or successor of Split start state = but no Inst or Split node itself end state = Inst , Split , Suc node, or successor of Inst node connection path may not traverse end nodes except Suc nodes
Encoding of f : f in f ( T 1 , T 2 ), f out ( T 3 ) a star( T 1 , T 2 ) f Encoding of a : f in a ( T 1 , T 2 ), f out Case Inst a Encoding of h : f in a ( T 1 , T 4 ), f out star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) encode connection paths to rewrite rules connection path : cover all ways through graph except Inst edges (are covered by the encoding of terms) Split edges (will be covered by extra Split rules later) parts without cycles or Suc nodes (irrelevant for termination behavior)
f in u a , f ( f in a ( T 1 , T 2 ) → f ( T 1 , T 2 )) a star( T 1 , T 2 ) u a , f ( f out f out ( T 3 )) → Case Inst f a star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε f eq( T 2 , [ ]) app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) connection path from s to s ′ with substitution σ : f in s ( . . . ) σ evaluates to f out f in a ( T 1 , T 2 ) evaluates to f out ( . . . ) σ if if s a f in evaluates to f out f in f ( T 1 , T 2 ) evaluates to f out s ′ ( . . . ) ( . . . ) ( T 3 ) s ′ f rewrite rules: f in → u s , s ′ ( f in f in → u a , f ( f in s ( . . . ) σ s ′ ( . . . ) ) a ( T 1 , T 2 ) f ( T 1 , T 2 ) ) u s , s ′ ( f out f out u a , f ( f out f out s ′ ( . . . ) ) → ( . . . ) σ ( T 3 ) ) → s f a
f in u a , f ( f in a ( T 1 , T 2 ) → f ( T 1 , T 2 )) a star( T 1 , T 2 ) u a , f ( f out f out ( T 3 )) → Case Inst f a f in f out a ( T 1 , [ ]) → star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a Eval Eval T 2 / [ ] ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε f eq( T 2 , [ ]) app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . . . . h star( T 1 , T 4 ) connection path from s ending in Suc node: f in s ( . . . ) σ evaluates to f out f in a ( T 1 , [ ]) evaluates to f out ( . . . ) σ s a intuition: f in a ( T 1 , T 2 ) evaluates to f out if T 2 ∈ ( T 1 ) ∗ a f in f ( T 1 , T 2 ) evaluates to f out if T 1 � =[ ] , T 2 � =[ ], T 3 is T 2 without prefix T 1 , T 3 ∈ ( T 1 ) ∗ ( T 3 ) f
f in u a , f ( f in a ( T 1 , T 2 ) → f ( T 1 , T 2 )) a star( T 1 , T 2 ) u a , f ( f out f out ( T 3 )) → Case Inst f a f in f out a ( T 1 , [ ]) → star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a f in u f,g ( f in f ( T 1 , T 2 ) → g ( T 1 , T 2 )) Eval Eval T 2 / [ ] u f,g ( f out u g,h ( f in ( T 4 )) → a ( T 1 , T 4 ) , T 4 ) ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c g d u g,h ( f out f out , T 4 ) → ( T 4 ) Eval a Cut f Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . g app( T 1 , T 3 , T 2 ) h star( T 1 , T 4 ) Case . . . Split node s with successors s 1 and s 1 : f in s ( . . . ) σ evaluates to f out f in f ( T 1 , T 2 ) evaluates to f out ( . . . ) σ if ( T 4 ) if s f f in s 1 ( . . . ) σ evaluates to f out f in g ( T 1 , T 2 ) evaluates to f out s 1 ( . . . ) σ and ( T 4 ) and g f in evaluates to f out f in a ( T 1 , T 4 ) evaluates to f out s 2 ( . . . ) s 2 ( . . . ) a
f in u a , f ( f in a ( T 1 , T 2 ) → f ( T 1 , T 2 )) a star( T 1 , T 2 ) u a , f ( f out f out ( T 3 )) → Case Inst f a f in f out a ( T 1 , [ ]) → star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b a f in u f,g ( f in f ( T 1 , T 2 ) → g ( T 1 , T 2 )) Eval Eval T 2 / [ ] u f,g ( f out u g,h ( f in ( T 4 )) → a ( T 1 , T 4 ) , T 4 ) ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c g d u g,h ( f out f out , T 4 ) → ( T 4 ) Eval a Cut f Eval T 1 / [ ] e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split T 3 / T 4 Case Split . . . g app( T 1 , T 3 , T 2 ) h star( T 1 , T 4 ) Case . . . intuition: if T 1 � =[ ], T 2 � =[ ], T 4 is T 2 without prefix T 1 , T 4 ∈ ( T 1 ) ∗ f in f ( T 1 , T 2 ) evaluates to f out ( T 4 ) f f in g ( T 1 , T 2 ) evaluates to f out ( T 4 ) if T 1 � =[ ], T 2 � =[ ], T 4 is T 2 without prefix T 1 g f in a ( T 1 , T 4 ) evaluates to f out if T 4 ∈ ( T 1 ) ∗ a
star( XS , [ ]) : - ! . star([ ] , ZS ) : - ! , eq( ZS , [ ]) . star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . app([ ] , YS , YS ) . app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) . eq( X , X ) . f in a ( T 1 , T 2 ) → u a , f ( f in f ( T 1 , T 2 )) u a , f ( f out ( T 3 )) → f out f a f in a ( T 1 , [ ]) → f out a existing TRS tools f in f ( T 1 , T 2 ) → u f,g ( f in g ( T 1 , T 2 )) prove termination u f,g ( f out ( T 4 )) → u g,h ( f in a ( T 1 , T 4 ) , T 4 ) g automatically u g,h ( f out , T 4 ) → f out ( T 4 ) a f f in g ([ T 5 | T 6 ] , [ T 5 | T 7 ]) → u g,i ( f in i ( T 6 , T 7 )) original prolog u g,i ( f out ( T 3 )) → f out ( T 3 ) program terminates i g f in i ([ T 8 | T 9 ] , [ T 8 | T 10 ]) → u i,k ( f in i ( T 9 , T 10 )) u i,k ( f out ( T 3 )) → f out ( T 3 ) i i f in i ([ ] , T 3 ) → f out ( T 3 ) i
� � � Symbolic Evaluation Graphs and Term Rewriting Termination Symbolic prolog - Rewrite Tool � TRS Evaluation Program (AProVE) Graph implemented in tool AProVE most powerful tool for termination of definite logic programs only tool for termination of non-definite prolog programs winner of termination competition for prolog (proves 342 of 477 examples, average runtime 6.5 s per example)
� � � � � � Symbolic Evaluation Graphs and Term Rewriting General methodology for analyzing prolog programs Termination Symbolic prolog - Rewrite Tool TRS Evaluation Program (AProVE) Graph Complexity Outline Determinacy linear operational semantics of prolog from prolog to symbolic evaluation graphs from symbolic evaluation graphs to TRSs for termination analysis from symbolic evaluation graphs to TRSs for complexity analysis determinacy analysis
Complexity for Logic Programs Program P , Class of queries Q p m m maps n ∈ N to longest evaluation starting with Q ∈ Q p prc P , Q p m , prc P , Q p m where | Q | m ≤ n | Q | m : number of variables and function symbols on input positions corresponds to number of unification attempts complexity for class Q p R has linear m if prc P , Q p m ( n ) ∈ O ( n ) R has quadratic complexity for class Q p m ( n ) ∈ O ( n 2 ) etc. m if prc P , Q p Example (star-program): has linear complexity Goal: Re-use existing methodology for termination analysis Goal: to analyze complexity as well
P : star( XS , [ ]) : - ! . star([ ] , ZS ) : - ! , eq( ZS , [ ]) . a star( T 1 , T 2 ) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . Case Inst star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval Eval ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split Case Split . . . g h app( T 1 , T 3 , T 2 ) star( T 1 , T 4 ) f in a ( T 1 , T 2 ) → u a , f ( f in f ( T 1 , T 2 )) Case u a , f ( f out ( T 3 )) → f out generate symbolic evaluation graph f a . . . f in a ( T 1 , [ ]) → f out a generate TRS from graph f in f ( T 1 , T 2 ) → u f,g ( f in g ( T 1 , T 2 )) determine complexity of TRS by existing tool u f,g ( f out ( T 4 )) → u g,h ( f in a ( T 1 , T 4 ) , T 4 ) g u g,h ( f out , T 4 ) → f out ( T 4 ) a f
linear P : star( XS , [ ]) : - ! . star([ ] , ZS ) : - ! , eq( ZS , [ ]) . a star( T 1 , T 2 ) star( XS , ZS ) : - app( XS , YS , ZS ) , star( XS , YS ) . Case Inst star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Correct! Eval Eval depends on Split ’s successor g ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d in P : repeat evaluation of h for Eval Cut Eval every answer of g ( backtracking ) e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) in TRS: evaluate h once (choose Suc g ’s answer non-deterministically ) Cut Eval Eval ε Here: g is deterministic ε eq( T 2 , [ ]) f app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) (has only one answer) Split Case Split . . . g h app( T 1 , T 3 , T 2 ) star( T 1 , T 4 ) f in a ( T 1 , T 2 ) → u a , f ( f in linear f ( T 1 , T 2 )) Case u a , f ( f out ( T 3 )) → f out generate symbolic evaluation graph f a . . . f in a ( T 1 , [ ]) → f out a generate TRS from graph f in f ( T 1 , T 2 ) → u f,g ( f in g ( T 1 , T 2 )) determine complexity of TRS by existing tool u f,g ( f out ( T 4 )) → u g,h ( f in a ( T 1 , T 4 ) , T 4 ) g u g,h ( f out , T 4 ) → f out ( T 4 ) infer that P has the same complexity a f
P : sublist( X , Y ) : - app( P , U , Y ) , app( V , X , P ) . (1) app([ ] , YS , YS ) . (2) app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) (3) Evaluation of sublist Q sublist = { sublist( t 1 , t 2 ) | t 2 ground } m computes all sublists of Y (by backtracking ) P : linear many possibilities to split Y into P and U for each possible P , linear evaluation of app( V , X , P )
quadratic P : sublist( X , Y ) : - app( P , U , Y ) , app( V , X , P ) . (1) a sublist( T 1 , T 2 ) app([ ] , YS , YS ) . (2) Case app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) (3) sublist( T 1 , T 2 ) (1) Eval Eval b app( T 3 , T 4 , T 2 ) , app( T 5 , T 1 , T 3 ) ε T 3 / T 6 Split Split c d Inst app( T 3 , T 4 , T 2 ) app( T 5 , T 1 , T 6 ) Inst Case T 5 / T 3 , T 1 / T 4 , T 6 / T 2 app( T 5 , T 1 , T 6 ) (2) | app( T 5 , T 1 , T 6 ) (3) T 5 / [ ] , T 1 / T 6 Eval Eval � | app( T 5 , T 1 , T 6 ) (3) app( T 5 , T 1 , T 6 ) (3) e f Inst Suc Eval ε app( T 5 , T 1 , T 6 ) (3) g Eval h app( T 8 , T 1 , T 9 ) T 5 / [ T 7 | T 8 ] , T 6 / [ T 7 | T 9 ] generate symbolic evaluation graph and TRS linear f in b ( T 2 ) → u b,c ( f in d ( T 2 )) u b,c ( f out ( . . . )) → u c,d ( f in determine complexity of TRS by existing tool d ( . . . )) d u c,d ( f out ( . . . )) → f out ( . . . ) infer that P has the same complexity d b
P : sublist( X , Y ) : - app( P , U , Y ) , app( V , X , P ) . (1) a sublist( T 1 , T 2 ) app([ ] , YS , YS ) . (2) Case app([ X | XS ] , YS , [ X | ZS ]) : - app( XS , YS , ZS ) (3) sublist( T 1 , T 2 ) (1) Eval Eval b app( T 3 , T 4 , T 2 ) , app( T 5 , T 1 , T 3 ) ε T 3 / T 6 Split Split c d Inst app( T 3 , T 4 , T 2 ) app( T 5 , T 1 , T 6 ) Inst Case Correctness of Complexity Analysis T 5 / T 3 , T 1 / T 4 , T 6 / T 2 app( T 5 , T 1 , T 6 ) (2) | app( T 5 , T 1 , T 6 ) (3) depends on Split ’s successor c in P : repeat evaluation of d for T 5 / [ ] , T 1 / T 6 Eval Eval every answer of c ( backtracking ) � | app( T 5 , T 1 , T 6 ) (3) app( T 5 , T 1 , T 6 ) (3) e f in TRS: evaluate d once (choose Inst Suc Eval c ’s answer non-deterministically ) ε app( T 5 , T 1 , T 6 ) (3) g Eval Here: c is not deterministic h app( T 8 , T 1 , T 9 ) ⇒ Split node b is multiplicative T 5 / [ T 7 | T 8 ] , T 6 / [ T 7 | T 9 ] generate symbolic evaluation graph and TRS f in b ( T 2 ) → u b,c ( f in d ( T 2 )) u b,c ( f out ( . . . )) → u c,d ( f in determine complexity of TRS by existing tool d ( . . . )) d u c,d ( f out ( . . . )) → f out ( . . . ) infer that P has the same complexity d b
Decompose Graph by Multiplicative Split Nodes Graph 1 generate symbolic evaluation graph MULTIPLICATIVE SPLIT generate separate TRSs R 1 , . . . , R 5 for parts up to multiplicative Split nodes (no multiplicative Split node may reach itself) Graph 2 Graph 3 determine irc R 1 , R , . . . , irc R 5 , R separately maps n ∈ N to maximal number of R i -steps in MULTIPLICATIVE SPLIT evaluation starting with basic term t , where | t | ≤ n upper bound for runtime and for number of answers Graph 4 Graph 5 combine complexities multiply complexities for children of multiplicative Split s add complexities of parents of multiplicative Split s irc R 1 , R + irc R 2 , R · ( irc R 3 , R + irc R 4 , R · irc R 5 , R )
a sublist( T 1 , T 2 ) irc R 1 , R : constant Case irc R 2 , R : linear sublist( T 1 , T 2 ) (1) irc R 3 , R : linear Eval Eval complexity of P : quadratic irc R 1 , R + irc R 2 , R · irc R 3 , R b app( T 3 , T 4 , T 2 ) , app( T 5 , T 1 , T 3 ) ε T 3 / T 6 Split Split app( T 3 , T 4 , T 2 ) c d app( T 5 , T 1 , T 6 ) Inst Inst Case T 5 / T 3 , T 1 / T 4 , T 6 / T 2 f in a ( T 2 ) → u a,b ( f in b ( T 2 )) app( T 5 , T 1 , T 6 ) (2) | app( T 5 , T 1 , T 6 ) (3) u a,b ( f out ( . . . )) → f out ( T 1 ) b a f in b ( T 2 ) → u b,c ( f in d ( T 2 )) T 5 / [ ] , T 1 / T 6 Eval Eval u b,c ( f out ( . . . )) → u c,d ( f in d ( . . . )) � | app( T 5 , T 1 , T 6 ) (3) app( T 5 , T 1 , T 6 ) (3) e f d u c,d ( f out ( . . . )) → f out ( . . . ) d b Suc Inst f in d ( T 6 ) → f out Eval ([ ] , T 6 ) ε d f in d ( T 6 ) → u d,g ( f in g ( T 6 )) app( T 5 , T 1 , T 6 ) (3) g Eval u d,g ( f out ( . . . )) → f out ( T 5 , T 1 ) h app( T 8 , T 1 , T 9 ) T 5 / [ T 7 | T 8 ] , T 6 / [ T 7 | T 9 ] g d f in d ( T 6 ) → u d,f ( f in g ( T 6 )) generate graph and TRSs R 1 , R 2 , R 3 u d,f ( . . . ) → f out ( T 5 , T 1 ) d determine irc R 1 , R , irc R 2 , R , irc R 3 , R f in g ([ T 7 | T 9 ]) → u g,h ( . . . ) u g,h ( . . . ) → f out ([ T 7 | T 8 ]) g infer complexity of P
� � � Symbolic Evaluation Graphs and Term Rewriting Symbolic prolog - Rewrite Tool � TRS Evaluation Program (AProVE) Graph Complexity implemented in tool AProVE only tool for complexity of non-well-moded or non-definite programs experiments on all 477 programs of TPDB O ( n 2 ) O ( n · 2 n ) O (1) O ( n ) bounds time CASLOG 1 21 4 3 29 14.8 CiaoPP 3 19 4 3 29 11.7 AProVE 54 117 37 0 208 10.6
� � � � � � Symbolic Evaluation Graphs and Term Rewriting General methodology for analyzing prolog programs Termination Symbolic prolog - Rewrite Tool TRS Evaluation Program (AProVE) Graph Complexity Determinacy Outline linear operational semantics of prolog from prolog to symbolic evaluation graphs from symbolic evaluation graphs to TRSs for termination analysis from symbolic evaluation graphs to TRSs for complexity analysis determinacy analysis
a sublist( T 1 , T 2 ) Criterion for determinacy of s Case If s reaches Suc node s ′ , sublist( T 1 , T 2 ) (1) then there is no path Eval Eval from s ′ to a Suc node. b app( T 3 , T 4 , T 2 ) , app( T 5 , T 1 , T 3 ) ε T 3 / T 6 Split Split c d Inst app( T 3 , T 4 , T 2 ) app( T 5 , T 1 , T 6 ) query deterministic iff Inst Case T 5 / T 3 , T 1 / T 4 , T 6 / T 2 it generates at most one app( T 5 , T 1 , T 6 ) (2) | app( T 5 , T 1 , T 6 ) (3) answer substitution at most once T 5 / [ ] , T 1 / T 6 Eval Eval for program analysis � | app( T 5 , T 1 , T 6 ) (3) app( T 5 , T 1 , T 6 ) (3) e f for complexity analysis Inst Suc Eval ε (non-multiplicative Split s) app( T 5 , T 1 , T 6 ) (3) g Eval h app( T 8 , T 1 , T 9 ) T 5 / [ T 7 | T 8 ] , T 6 / [ T 7 | T 9 ] successful evaluation ⇒ c not deterministic path to Suc node in ⇒ Split node b multiplicative symbolic evaluation graph a not deterministic
Criterion for determinacy of s a star( T 1 , T 2 ) If s reaches Suc node s ′ , Case Inst then there is no path from s ′ to a Suc node. star( T 1 , T 2 ) (1) | star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) b Eval Eval ! | star( T 1 , [ ]) (2) | star( T 1 , [ ]) (3) star( T 1 , T 2 ) (2) | star( T 1 , T 2 ) (3) c d Eval Cut Eval e � ! , eq( T 2 , [ ]) | star([ ] , T 2 ) (3) star( T 1 , T 2 ) (3) Suc Cut Eval Eval ε ε f eq( T 2 , [ ]) app( T 1 , T 3 , T 2 ) , star( T 1 , T 3 ) Split Case Split . . . g app( T 1 , T 3 , T 2 ) h star( T 1 , T 4 ) Case . . . g is deterministic ⇒ Split node f not multiplicative a is deterministic
� Symbolic Evaluation Graphs and Term Rewriting Symbolic prolog - Evaluation Program Graph implemented in tool AProVE experiments on 300 definite programs: � Determinacy CiaoPP: 132, AProVE: 69 experiments on 177 non-definite programs: CiaoPP: 61, AProVE: 92 only first step, but substantial addition to existing determinacy analyses (AProVE succeeds on 78 examples where CiaoPP fails) strong enough for complexity analysis
Overview I. Termination of Term Rewriting 1 Termination of Term Rewrite Systems 2 Non-Termination of Term Rewrite Systems 3 Complexity of Term Rewrite Systems 4 Termination of Integer Term Rewrite Systems II. Termination of Programs 1 Termination of Functional Programs (Haskell) 2 Termination of Logic Programs (Prolog) 3 Termination of Imperative Programs (Java) (RTA ’10 & ’11, CAV ’12)
Termination of Imperative Programs Direct Approaches Synthesis of Linear Ranking Functions (Colon & Sipma, 01), (Podelski & Rybalchenko, 04), . . . Terminator: Termination Analysis by Abstraction & Model Checking (Cook, Podelski, Rybalchenko et al., since 05) Julia & COSTA: Termination Analysis of java bytecode (Spoto, Mesnard, Payet, 10), (Albert, Arenas, Codish, Genaim, Puebla, Zanardini, 08) . . . used at Microsoft for verifying Windows device drivers no use of TRS-techniques (stand-alone methods)
Termination of Imperative Programs Rewrite-Based Approach analyze java bytecode ( jbc ) instead of java using TRS-techniques for jbc is challenging sharing and aliasing side effects cyclic data objects object-orientation recursion . . .
Termination of Imperative Programs New approach Frontend evaluate jbc a few steps ⇒ termination graph termination graph captures side effects, sharing, cyclic data objects etc. transform termination graph ⇒ TRS Backend prove termination of the resulting TRS (using existing techniques & tools) implemented in AProVE successfully evaluated on jbc -collection competitive termination tool for jbc
� � Termination of Imperative Programs prolog - Program ▼ ▼ ▼ ▼ ▼ haskell - � Termination � Termination Tool � TRS Program Graph (AProVE) q q q q q jbc - Program implemented in AProVE successfully evaluated on jbc -collection competitive termination tool for jbc
Termination of Imperative Programs other techniques: public class IntList { abstract objects to numbers int value; IntList next; IntList -object representing [0 , 1 , 2] } is abstracted to length 3 our technique: abstract objects to terms introduce function symbol for every class IntList -object representing [0 , 1 , 2] is abstracted to term: IntList(0 , IntList(1 , IntList(2 , null) ) ) TRS-techniques generate suitable orders to compare arbitrary terms particularly powerful on user-defined data types powerful on pre-defined data types by using Integer TRSs
� � From jbc to Termination Graphs prolog - Program ● ● ● ● haskell - � Termination � Termination Tool � TRS Program (AProVE) Graph ✈ ✈ ✈ ✈ jbc - Program
Example public class Int { 00: aload 0 // load num to opstack 01: ifnull 8 // jump to line 8 if top // only wrap a primitive int // of opstack is null private int val; 04: aload 1 // load limit 05: ifnonnull 9 // jump if not null // count up to the value 08: return // in "limit" 09: aload 0 // load num public static void count( Int num, Int limit) { 10: astore 2 // store into copy 11: aload 0 // load num 12: getfield val // load field val if (num == null 15: aload 1 // load limit || limit == null) { 16: getfield val // load field val return; 19: if icmpge 35 // jump if } // num.val >= limit.val 22: aload 2 // load copy // introduce sharing 23: aload 2 // load copy Int copy = num; 24: getfield val // load field val 27: iconst 1 // load constant 1 while (num.val < limit.val) { 28: iadd // add copy.val and 1 copy.val++; 29: putfield val // store into copy.val } } 32: goto 11 35: return }
Abstract States of the jvm ifnull 8 | n : o 1 , l : o 2 | o 1 00: aload 0 // load num to opstack 01: ifnull 8 // jump to line 8 if top o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) // of opstack is null o 2 = Int (?) 04: aload 1 // load limit 4 components 05: ifnonnull 9 // jump if not null 08: return 1 next program instruction 09: aload 0 // load num 10: astore 2 // store into copy 11: aload 0 // load num 2 values of local variables 12: getfield val // load field val (value of num is reference o 1 ) 15: aload 1 // load limit 16: getfield val // load field val 3 values on the operand stack 19: if icmpge 35 // jump if // num.val >= limit.val 4 information about the heap 22: aload 2 // load copy 23: aload 2 // load copy object at address o 2 is 24: getfield val // load field val 27: iconst 1 // load constant 1 null or of type Int 28: iadd // add copy.val and 1 object at o 1 has type Int , 29: putfield val // store into copy.val val -field has value i 1 32: goto 11 35: return i 1 is an arbitrary integer no sharing
From jbc to Termination Graphs A aload 0 | n : o 1 , l : o 2 | ε return | n : null , l : o 2 | ε 00: aload 0 o 1 = Int (?) o 2 = Int (?) o 2 = Int (?) 01: ifnull 8 04: aload 1 ifnull 8 | n : o 1 , l : o 2 | o 1 ifnull 8 | n : null , l : o 2 | null . o 1 = Int (?) o 2 = Int (?) o 2 = Int (?) . . 19: if icmpge 35 ifnull 8 | n : o 1 , l : o 2 | o 1 aload 1 | n : o 1 , l : o 2 | ε . o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) . . o 2 = Int (?) o 2 = Int (?) 27: iconst 1 28: iadd T:if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 29: putfield val o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) 32: goto 11 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) 35: return i 1 ≥ i 2 return | n : o 1 , l : o 2 , c : o 1 | ε o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) F:if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 3 , i 2 i 1 < i 2 o 1 = Int ( val = i 3 ) i 3 = ( −∞ , ∞ ) State A : iadd | n : o 1 , l : o 2 , c : o 1 | o 1 , i 1 , iconst 1 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) do all calls of count terminate? putfield val | n : o 1 , l : o 2 , c : o 1 | o 1 , i 3 iconst 1 = [1 , 1] o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) i 3 = i 1 + iconst 1 num and limit are arbitrary, but distinct Int -objects i 3 = ( −∞ , ∞ )
From jbc to Termination Graphs A aload 0 | n : o 1 , l : o 2 | ε return | n : null , l : o 2 | ε 00: aload 0 o 1 = Int (?) o 2 = Int (?) o 2 = Int (?) 01: ifnull 8 04: aload 1 B ifnull 8 | n : o 1 , l : o 2 | o 1 ifnull 8 | n : null , l : o 2 | null . o 1 = Int (?) o 2 = Int (?) o 2 = Int (?) . . 19: if icmpge 35 ifnull 8 | n : o 1 , l : o 2 | o 1 aload 1 | n : o 1 , l : o 2 | ε . o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) . . o 2 = Int (?) o 2 = Int (?) 27: iconst 1 28: iadd T:if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 29: putfield val o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) 32: goto 11 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) 35: return i 1 ≥ i 2 return | n : o 1 , l : o 2 , c : o 1 | ε o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) F:if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 1 , i 2 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) if icmpge 35 | n : o 1 , l : o 2 , c : o 1 | i 3 , i 2 i 1 < i 2 o 1 = Int ( val = i 3 ) i 3 = ( −∞ , ∞ ) State B : iadd | n : o 1 , l : o 2 , c : o 1 | o 1 , i 1 , iconst 1 o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) “ aload 0 ” loads value of num on operand stack putfield val | n : o 1 , l : o 2 , c : o 1 | o 1 , i 3 iconst 1 = [1 , 1] o 1 = Int ( val = i 1 ) i 1 = ( −∞ , ∞ ) o 2 = Int ( val = i 2 ) i 2 = ( −∞ , ∞ ) i 3 = i 1 + iconst 1 A connected to B by evaluation edge i 3 = ( −∞ , ∞ )
Recommend
More recommend