Determinacy Inference for Logic Programs
Lunjin Lu @ Oakland UniversityIn collaboration with Andy King @ Kent University, UK
Context
Project - “An Integrated Framework for Semantic Based Analysis of Logic Programs” Backward analyses Parametric analyses Context sensitive analyses
Project – “US-UK Collaborative Research on Backward analyses for Logic Programs”
Determinacy
sort(Xs,Ys) :- perm(Xs,Ys), ordered(Ys).
perm(Xs,[Z|Zs]) :- select(Z,Xs,Ys),perm(Ys,Zs).perm([],[]).
ordered([]).ordered([X]) :- number(X).ordered([X,Y|Ys]) :-
X =< Y, ordered([Y|Ys]).
select(X,[X|Xs],Xs).select(X,[Y|Ys],[Y|Zs]) :-
select(X,Ys,Zs).
A call is determinate if it has at most one computed answer and that answer is generated once.
?- sort([2,2],L).
L=[2,2] ;
L=[2,2] ;
No.
Goal
Infer sufficient conditions under which a call is determinate Generalizing determinacy checking
Motivation
Useful in language implementations Program development
Tune performance Execute a determinate call under once;
Detect possible bugs; Useful in program specialization
Unfold when certain determinacy condition is satisfied.
Determinacy is important in concurrent programming
Reversing a list
(1) append(Xs, Ys, Zs) :- Xs = [], Ys = Zs.(2) append(Xs, Ys, Zs) :-
Xs = [X|Xs1], Zs = [X|Zs1], append(Xs1, Ys, Zs1).
(3) rev(Xs,Ys) :- Xs = [], Ys = []. (4) rev(Xs,Ys) :- Xs = [X|Xs1], Ys2 = [X],
rev(Xs1, Ys1), append(Ys1, Ys2, Ys).
Overall structure of analysis
Success Patterns wrt
Mux Conditions wrt rigid’
DeterminacyConditions wrt rigid’
Success pattern wrt rigid’
Determinacy condition wrt rigid’
Computing success patterns wrt term abstraction
Success Patterns wrt
Mux Conditions wrt rigid’
DeterminacyConditions wrt rigid’
Success pattern wrt rigid’
Determinacy condition wrt rigid’
Abstracting terms
A concrete term is mapped into an abstract term via a map .
Example one: dk
d0(t) = _
dk(X) = X
dk(f(t1,…,tn)) = f(dk-1(t1),…,dk-1(tn)) Example two: list length norm
otherwisei
tif
Vartift
tn
i tttt
1
212
1
]|[1
Abstracting primitive constraints
Term abstraction induces an abstraction map, also denoted , that takes concrete constraints into abstract constraints.
Examples (K=[X|L]) is (K=1+L) when = || || (L=[X,Y,Z,W]) is (L=[X,Y|_]) when = d2.
Operations on abstract constraints \/ /\ x
Abstracting program wrt a term abstraction
(1) append(Xs, Ys, Zs) :- Xs = [], Ys = Zs. append(Xs, Ys, Zs) :-
Xs≥0, Ys≥0 , Zs≥0, Xs = 0, Ys = Zs.
(2) append(Xs, Ys, Zs) :- Xs = [X|Xs1], Zs = [X|Zs1], append(Xs1, Ys, Zs1).
append(Xs, Ys, Zs) :- Xs≥0, Ys≥0 , Zs≥0, Xs1≥0, Zs1≥0 , Xs = 1+Xs1, Zs = 1+Zs1,
append(Xs1, Ys, Zs1).
Abstract program
(1) append(Xs, Ys, Zs) :- Xs≥0, Ys≥0 , Zs≥0, Xs = 0, Ys = Zs.
(2) append(Xs, Ys, Zs) :- Xs≥0, Ys≥0 , Zs≥0, Xs1≥0, Zs1≥0 , Xs = 1+Xs1, Zs = 1+Zs1,
append(Xs1, Ys, Zs1).
(3) rev(Xs,Ys) :- Xs≥0, Ys≥0, Xs = 0, Ys = 0.
(4) rev(Xs,Ys) :- Xs≥0, Ys≥0, Xs1≥0, Ys1≥0,Ys2≥0, Xs = 1+Xs1, Ys2 = 1, rev(Xs1, Ys1), append(Ys1, Ys2, Ys).
Computing success set of abstract program
1) append(Xs,Ys,Zs) :-Ys≥0,Zs≥0,Xs=0,Ys=Zs.
2) append(Xs, Ys, Zs) :-
1≥Xs,Xs≥0,Ys≥0,1≥Zs,Zs≥0,Zs=Xs+Ys3) append(Xs,Ys,Zs) :- Xs≥0,Ys≥0,Zs=Xs+Ys
4) rev(Xs,Ys) :- Xs = 0, Ys = 0. 5) rev(Xs,Ys) :-
1≥Xs, Xs≥0, 1≥Ys, Ys≥0, Xs=Ys.6) rev(Xs,Ys) :- Xs≥0, Xs=Ys.
Predicate level success patterns
append(x1,x2,x3) :- (x1≥0) (x2≥0) (x1+x2=x3)
rev(x1,x2) :- (x1≥0) (x1=x2)
Clause level success patterns
(1) append(x1,x2,x3) :-
(x1=0) (x2≥0) (x2=x3).
(2) append(x1,x2,x3) :-
(x1≥1) (x2≥0) (x1+x2=x3).
(3) rev(x1,x2) :- (x1=0) (x2=0).
(4) rev(x1,x2) :- (x1≥1) (x1=x2)
Synthesizing mutual exclusion conditions
Success Patterns wrt
Mux Conditions wrt rigid’
DeterminacyConditions wrt rigid’
Success pattern wrt rigid’
Determinacy condition wrt rigid’
Tracking rigidity
Induced rigidity: term abstraction induces a rigidity predicate:
rigid(t) (t)=((t)) for any e.g. rigid([1,X]) = truee.g. rigid(X) = false
Tracked rigidity: it may be simpler to track a rigidity predicate which implies the induced one.
rigid’(t) rigid(t) Domain of rigidity: Pos
Rigidity dependence is expressed as positive Boolean functions such as (x1x2).
Galois connection
rigid’(f) = {Sub|
Sub.assign()|=f}
rigid’() = {fPos| rigid
(f)}
assign()= {xrigid’((x))|
xdom()}
Mutual exclusion conditions
A mutual exclusion condition for a predicate is a rigidity constraint under which at most one clause of the predicate may commence a successful derivation.
Mutual exclusion of two clauses
Let C1 and C2 have success patterns
p(x) :- c1
p(x) :- c2.
If Y and XP(Y,p(x),C1,C2) then
C1 and C2 are mutually exclusive
where XP(Y,p(x),C1,C2) = (-Y(c1)-Y(c2))
Mutual exclusion of two clauses
(1) append(x1,x2,x3) :- (x1=0) (x2≥0) (x2=x3). c1(2) append(x1,x2,x3) :- (x1≥1) (x2≥0) (x1+x2=x3). c2
-{x1}(c1) = (x1=0) -{x1}(c2) = (x1≥1)XP({x1},p(x),C1,C2) = true
-{x2,x3}(c1) = (x2≥0) (x2=x3) -{x2,x3}(c2) = (x2≥0) (x2<x3)
XP({x2,x3},p(x),C1,C2) = true
Synthesizing mutual exclusions
XP(p(x)) = {Y|C1,C2S. (C1C2XP(Y,p(x),C1,C2))}
with S = the set of clauses defining p.
XP(append(x1,x2,x3)) = x1 (x2x3)
XP(rev(x1,x2)) = x1 x2
Synthesizing Determinacy Conditions
Success Patterns wrt
Mux Conditions wrt rigid’
DeterminacyConditions wrt rigid’
Success pattern wrt rigid’
Determinacy condition wrt rigid’
Synthesizing determinacy conditions
Determinacy inference takes two steps: The first is a lfp that computes rigidity
success patterns The second is a gfp that calculates
rigidity call patterns that ensures determinacy. (objective)
Both lfp and gfp works on rigidity abstraction of the original program.
Abstracting program wrt rigidity
(1) append(Xs, Ys, Zs) :- Xs = [], Ys = Zs.
append(Xs, Ys, Zs) :- Xs (Ys Zs).
(2) append(Xs, Ys, Zs) :- Xs=[X|Xs1], Zs=[X|Zs1], append(Xs1,Ys,Zs1).
append(Xs, Ys, Zs) :- (XsXs1)(ZsZs1),
append(Xs1,Ys,Zs1).
Rigidity program
(1) append(Xs,Ys,Zs) :- Xs (Ys Zs).
(2) append(Xs,Ys,Zs) :- (Xs Xs1) (Zs Zs1), append(Xs1,Ys,Zs1).
(3) rev(Xs,Ys) :- Xs Ys. (4) rev(Xs,Ys) :- (Xs Xs1) Ys2,
rev(Xs1,Ys1), append(Ys1,Ys2,Ys).
Computing rigidity success patterns
Rigidity success patterns of the original program is obtained by calculating success set of the rigidity program.
append(x1,x2,x3) = x1 (x2 x3)rev(x1,x2) = x1 x2
Synthesizing determinacy conditions via backward analysis
Success Patterns wrt
Mux Conditions wrt rigid’
DeterminacyConditions wrt rigid’
Success pattern wrt rigid’
Determinacy condition wrt rigid’
Determinacy Conditions
Determinacy conditions describes those queries that are determinate.
There is one determinacy condition for each predicate.
p(x) :- g states that (p(x)) has at most one computed answer whenever rigid’
(g).
Lower approximation of determinacy conditions
If p(x) :- g is a determinacy condition and g’ |= g then p(x):-g’ is a determinacy condition.
Determinacy conditions can thus be approximated from below without compromising correctness (but not necessarily from above)
Greatest fixpoint computation
Iteration commences with I0={ p(x):-true | p }.
Ik+1 is computed from Ik by considering each clause in turn and calculating a (more) correct determinacy condition. Intially Ik+1 = Ik Strengthen Ik+1
Propagating determinacy conditions backwards p(x) f0, p1(x1),…,pn(xn).
A correct condition g’ is obtained by Propagating the condition on each
call
ei = -x((f0j<ifj ) gi))
where pi(xi):-gi Ik+1 and fj is the rigidity success pattern for pj(xj).
Conjoining e1, e2, …, en and mutual exclusion condition for p(x).
Updating Ik+1
Ik+1 contains a determinacy condition p(x) :- g” and this is updated to p(x) :- g”/\g’ if g” | g’.
Determinacy conditions becomes progressively stronger on each iteration.
This process will converge onto the gfp.
Gfp computation for reverse
I0:append(x1,x2,x3) :- truerev(x1,x2) :- true
I1:
append(x1,x2,x3) = x1 (x2 x3)rev(x1,x2) = x1 x2
I3=I2:
append(x1,x2,x3) = x1 (x2 x3)rev(x1,x2) = x1
Small Benchmarks
Performance
Other work on backward analysis for logic programs
Termination Inference (Codish & Genaim 2005)
Backward analysis via program transformation (Gallagher 2003)
Suspension (Genaim and King 2003) Groundness (King & Lu 2002) Type (Lu & King 2002) Pair sharing (Lu & King 2004) Set sharing (Li & Lu 2005) Equivalence of Forward and backward
analysis (King & Lu 2003)
Conclusion
Backwards analysis can infer sufficient conditions that ensures some properties are satisfied.
Determinacy inference analysis is composed of off-the-self success pattern analysis, mutual exclusion synthesis and a backwards analysis.
Initial experiments shows that it is practical and infers useful results.
Future work
Independence of computation rule For improved precision
Mutual exclusion condition More term abstractions