Slides

A specification that says how the program must behave is written
Verification
A system checks whether the code fullfills the specification
Source code + specification + verificator
Test cases that check whether the program behaves as expected are written
Testing
By running the test cases, a bug symptom can be detected
Source code + test cases + running environment
The programmer inspects the execution looking for bugs
Debugging
A debugger helps the programmer to find bugs
Source code + debugger + intuition
1. We do not need to follow a path
2. There can be several errors
3. The boss can also put the foot in
TWO PHASES:
• Generate the execution tree
• Traverse the execution tree, asking the user questions until a bug is found
If a symptom of an error is detected
then AD will eventually find a bug [Sha82]
main = 4
What is an Execution Tree?
listSum [1,2] = 4
Example:
main = listSum [1,2]
listSum [] = 1
listSum (x:xs) = x + (listSum xs)
1+3 = 4
listSum [2] = 3
2+1 = 3
listSum [] = 1
(1) do
(2)
node = selectNode(T)
(3)
answer = askNode(node)
(4)
if (answer = NO)
(5)
then M(node) = Wrong
(6)
buggyNode = node
(7)
N = {n ∈ N | (node  n) ∈ E*}
(8)
else N = N \ {n ∈ N | (node  n) ∈ E*}
(9) while (∃n ∈ N, M(n) = Undefined)
(10) return buggyNode
Debugging session
main = sqrTest [1,2]
square3 x = listSum (partialSums x)
sqrTest x = test (squares (listSum x))
partialSums x = [(sum1 x),(sum2 x)]
test (x,y,z) = (x==y) && (y==z)
sum1 x = div (x * (incr x)) 2
sum2 x = div (x + (decr x)) 2
listSum [] = 0
listSum (x:xs) = x + (listSum xs)
squares x = ((square1 x),(square2 x),(square3 x))
square1 x = square x
square x = x*x
square2 x = listSum (list x x)
list x y | y==0 = []
| otherwise = x:list x (y-1)
incr x = x + 1
decr x = x - 1
Debugging session using Top-Down – Heaviest First.
main = False
Starting the debugging session…
1)
main = False? NO
2)
sqrTest [1,2] = False? NO
3)
squares 3 = [9,9,8]? NO
4)
square2 3 = 9? YES
5)
square3 3 = 8? NO
6)
partialSums 3 = [6,2]? NO
7)
sum1 3 = 6? YES
8)
sum2 3 = 2? NO
9)
decr 3 = 2? YES
sqrTest [1,2] = False
test (9,9,8) = False
squares1 3 = 9
square 3 = 9
squares 3 = (9,9,8)
squares2 3 = 9
squares3 3 = 8
listSum [2] = 2
listSum [3,3,3] = 9
list 3 3 = [3,3,3]
listSum [6,2] = 8
listSum [3,3] = 6
list 3 2 = [3,3]
listSum [2] = 2
sum1 3 = 6
sum2 3 = 2
listSum [3] = 3
list 3 1 = [3]
listSum [] = 0
incr 3 = 4
decr 3 = 2
listSum [] = 0
list 3 0 = []
Bug found in rule:
sum2 x = div (x + (decr x)) 2
listSum [1,2] = 3
partialSums 3 = [6,2]
listSum [] = 0
Debugging session using Divide & Query (by Hirunkitti).
main = False
Starting the debugging session…
1)
square2 3 = 9? YES
2)
square3 3 = 8? NO
3)
partialSums 3 = [6,2]? NO
4)
sum1 3 = 6? YES
5)
sum2 3 = 2? NO
6)
decr 3 = 2? YES
sqrTest [1,2] = False
test (9,9,8) = False
squares1 3 = 9
square 3 = 9
squares 3 = (9,9,8)
squares2 3 = 9
listSum [1,2] = 3
squares3 3 = 8
listSum [2] = 2
listSum [3,3,3] = 9
list 3 3 = [3,3,3]
listSum [6,2] = 8
partialSums 3 = [6,2]
listSum [3,3] = 6
list 3 2 = [3,3]
listSum [2] = 2
sum1 3 = 6
sum2 3 = 2
listSum [3] = 3
list 3 1 = [3]
listSum [] = 0
incr 3 = 4
decr 3 = 2
listSum [] = 0
list 3 0 = []
Bug found in rule:
sum2 x = div (x + (decr x)) 2
listSum [] = 0
Which one is better?
Top-Down
Divide & Query
None of them, they are just different
o Questions are semantically
related to the previous ones
o The bug found will probably
be the one you are looking for
o Too many questions
o Very few questions
o Questions are hardly related
to the previous ones
o The bug found may not be
the one you are looking for
16
8
8
1
5
1
4
1
1
1
1
2
4
2
6
1
1
1
1
1
1
1
1
1
1 8
1 1
1 5
1 1
1 4
1 1
1 1
1 1
3
2
3
3
3
3
2
2
2
1
1
1
3
2
2
2
2
1
1
9
2
8
3
2
5
5
3
4
2
2
4
3
1
2
1
3
2
1
3
1
2
3
16
3
16
3
6
6
6,5
6,5
3
2
3
2
3,5
2
3,5
2
2
1
2
1
2,5
1
2,5
1
1
1
1
1
• Divide & Query by Hirunkitti is not optimal
• We provide a new strategy which is optimal
Up(n’) = Down(n’)
|un’ – dn’| < |un’’ - dn’’|
8
6
4
x/2 * x/2
1
2
1
0*x
2
0
d
1
u
x/2
d u >d u
n1
1
Equation 1:
wn = Up(n’) + Down(n’) + win’
Equation 2:
wn’ = Down(n’) + win’
n1
n2
n2
x
d u >d u
d (w - d - wi ) > d (w - d - wi )
d w - d - d wi > d w - d - d wi
d w - d w > d - d + d wi - d wi
(d - d )w > d - d + d wi - d wi
-d
d
>
+ d wi - d wi
w
d -d d -d d -d
-d
d
>
+
+
+
w d d wi wi d d
d d
-d
d
d
>
+
+
+
- d
(
)
w d d wi wi
d d
d d d d
w > d + d + wi d- + wi (1- d- )
d d
d d
w > d + d + wi d + wi (1- d )
>
+
+
+
w
w > dd + dd + wi
wi d wi wi d
w > w + w - 2wi + wi
w > w + w - wi
n1
n1
n1
n2
n
n2
n1
n
n2
n
n2
2
2
n1
n
n1
n1
n
n2
2
n1
n
n2
n1
n2
n
n
n1
n2
2
n1
n2
2
n1
n2
n1
n2
n1
n1
n2
n
n2
n2
n
n
n2
n
2
2
2
n
n
n1
n1
n1
n
n
n2
n2
n
n
n
n2
n1
n2
n1
n
n2
n
n1
n2
n1
n1
n
n1
n2
n
n2
n1
n2
n1
n2
n1
n2
n1
n
n1
n2
n1
n
n1
n1
n
n
n1
n2
n
n1
n2
n
n
n
n
n1
n1
n2
n2
n
n
n
n
n1
n2
n
n1
n2
n
n
n
n1
n
n2
n2
8
6
4
2
1
2
1
1
1
w > w + w - wi
n
n1
n2
n
7
7
7
5
2
5
2
5
2
5
2
4
1
4
1
4
1
4
1
3
1
7
3
1
1
3
1
1
3
1
w > w + w - wi
n
n1
n2
1
n
1
(1)
Candidate = root
(2)
(3)
(4)
(5)
(6)
do
(7)
Best = Candidate
Children = {m | (Best → m) ∈ E}
if (Children = ∅) then return Best
Candidate = n‘ | ∀n’’ with n’, n’’ ∈ Children, wn’ ≥ wn’’
while (wCandidate > wroot/2)
(8) if (M(Best) = Wrong) then return Candidate
(9) if (wroot ≥ wBest + wCandidate – wiroot) then return Best
(10)
else return Candidate
(1)
Candidate = root
(2)
(3)
(4)
(5)
(6)
(7)
do
(8)
(9)
(10)
if (M(Best) = Wrong) then return Candidate
if (wroot ≥ wBest + wCandidate – wiroot) then return Best
else return Candidate
20
Best = Candidate
Children = {m | (Best → m) ∈ E}
if (Children = ∅) then return Best
Candidate = n‘ | ∀n’’ with n’, n’’ ∈ Children, wn’ ≥ wn’’
while (wCandidate > wroot/2)
12
8
3
2
5
1
4
1
1
1
1
2
1
1
5
2
4
1
1
(1)
Candidate = root
(2)
(3)
(4)
(5)
(6)
(7)
(8)
do
Best = Candidate
Children = {m | (Best → m) ∈ E}
if (Children = ∅) then return Best
Candidate = n′ |∀n′′ with n′ , n′′ ∈ Children, wn’ ≥ wn′′
while (wCandidate − wiCandidate/2 > wroot/2)
Candidate = n‘ ∈ Children | ∀n’’ ∈ Children, wn′ − win′/2 ≥ wn′′ − win′′/2
(9) if (M(Best) = Wrong) then return Candidate
(10) if (wroot ≥ wBest + wCandidate – wiBest/2 – wiCandidate/2) then return Best
(11)
else return Candidate
Benchmark
NumReader
Ordering
Factoricer
Sedgewich
Clasifier
LegendGame
Cues
Romanic
FibRecursive
Risk
FacTrans
RndQuicksort
BinaryArrays
FibFactAna
NewtonPol
RegresionTest
BoubleFib
ComplexNums
Integral
TestMath
TestMath2
Figures
FastCalc
SpaceLimits
Argparser
Cglib
Kxml
Javassist
Average
Nodes
12
46
62
12
23
71
18
123
4.619
33
198
72
128
351
7
18
171
60
5
48
228
113
59
127
129
1.216
1.172
1.357
374,21
D&QO
28,99 %
12,04 %
9,83 %
30,77 %
19,79 %
8,87 %
31,58 %
6,40 %
0,27 %
16,78 %
3,89 %
8,73 %
5,52 %
2,44 %
39,06 %
23,27 %
4,40 %
10,02 %
44,44 %
11,91 %
3,51 %
6,72 %
10,11 %
12,95 %
12,10 %
1,93 %
2,86 %
4,34 %
13,34 %
D&QH
28.99 %
12,09 %
9,83 %
30,77 %
20,31 %
8,87 %
32,41 %
10,84 %
0,27 %
16,78 %
3,89 %
8,73 %
5,52 %
2,44 %
39,06 %
23,27 %
4,41 %
10,02 %
44,44 %
11,91 %
3,51 %
6,75 %
10,14 %
16,07 %
12,10 %
1,93 %
2,86 %
4,34 %
13,66 %
D&QS
31,36 %
12,63 %
9,93 %
33,14 %
22,40 %
8,95 %
32,41 %
11,23 %
0,28 %
18,08 %
3,93 %
8,73 %
5,71 %
2,45 %
43,75 %
25,21 %
4,57 %
10,32 %
47,22 %
12,16 %
3,51 %
6,79 %
10,42 %
19,15 %
13,08 %
2,33 %
3,01 %
5,44 %
14,58 %
DR&Q
29,59 %
14,40 %
20,03 %
30,77 %
21,88 %
16,72 %
32,41 %
13,56 %
1,20 %
19,38 %
6,22 %
11,41 %
7,13 %
5,38 %
39,06 %
25,21 %
11,40 %
11,31 %
44,44 %
12,99 %
9,73 %
8,09 %
11,53 %
21,74 %
20,48 %
2,12 %
3,56 %
4,49 %
16,29 %
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
Average
41,80 %
19,88 %
16,94 %
38,46 %
28,47 %
16,01 %
37,60 %
15,00 %
5,59 %
24,76 %
10,06 %
15,19 %
11,21 %
9,68 %
44,03 %
30,45 %
13,75 %
16,53 %
48,74 %
20,46 %
14,57 %
12,36 %
18,28 %
22,31 %
18,04 %
8,12 %
9,00 %
9,59 %
20,60 %
16
8
8
1
5
1
4
1
1
1
1
2
4
2
6
1
1
1
1
1
1
1
1
1
9
9
2
4
4
3
3
1
3
2
1
1
3
4
5
4
4
5
2
3
1
3
31
4
3
3
1
3
1
4
3
30
4
1
2
1
3
4
15
8
4
2
1
1
1
4
5
4
3
1
1
1
4
4
15
7
6
1
66
4
4
8
4
2
4
6 6
5
2
4
1
4
1
1
4
1
1
4
1
4
6 7
4
2
4
2
4
4
1
1
5
2
1
1
3
4
1
6
5
64
• None strategy of the Divide & Query family
can ever be an optimal strategy
• We provide a way of optaining an optimal strategy
n1
[n2,n7,n10]
46 10 4
n2
[n3,n4,n5,n6]
19 5 5
6 6
n3
1
n4
1
3
1
2
3
1
1
n5
3
4
1
4
1
1
n7
[n8,n9]
8 3 53 5
n6
4
5
1
5
1
1
n8
5
6
1
6
1
1
n9
2
4
4
1
1
n10
1
1
4
1
4
3
5
5
[n2,n7,n10] = (19 + 1 * 5) + (8 + 2 * 3) + (1 + 3 * 1) + (4) = (24) + (14) + (4) + (4) = 46
[n7,n2,n10] = (8 + 1 * 3) + (19 + 2 * 5) + (1 + 3 * 1) + (4) = (11) + (29) + (4) + (4) = 48
[n10,n2,n7] = (1 + 1 * 1) + (19 + 2 * 5) + (8 + 3 * 3) + (4) = (2) + (29) + (17) + (4) = 52
(1)
(2)
(3)
(4)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
SPn = calculateSP(T, n)
spOptimal = spn ∈ SPn | ∀sp’n ∈ SPn, calculateQ(T, n, spn) ≤ calculateQ(T, n, sp’n)
QOptimal = calculateQ(T, n, spOptimal)
return (spOptimal, QOptimal)
questAccumulated = 1
while ({n’ | (n → n’) ∈ E*} ≠ {n})
node = spn[nodeIndex]
nodeIndex = nodeIndex + 1
questions = questions + (Qnodo + questAccumulated * wnode)
questAccumulated = questAccumulated + 1
T = adjustMiddleNodes(T, n, node)
end while
questions = questions + (questAccumulated)
return questions
O = {n’’ ∈ N | (n’ → n’’) ∈ E*}
N=N\O
n’ = n’’ | (n’’ → n’) ∈ E
while (n’ ≠ n)
(_, Qn’) = calculateSpOptimal(T, n’)
wn’ = wn’ - |O|
n’ = n’’ | (n’’ → n’) ∈ E
end while
return T
n1
n2
n3
n4
1
7
n6
4
n7
3
n5
1
2
1
(1)
(2)
(3)
(4)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
SPn = calculateSP(T, n)
spOptimal = spn ∈ SPn | ∀sp’n ∈ SPn, calculateQ(T, n, spn) ≤ calculateQ(T, n, sp’n)
QOptimal = calculateQ(T, n, spOptimal)
return (spOptimal, QOptimal)
timeAccumulated = tin
while ({n’ | (n → n’) ∈ E*} ≠ {n})
node = spn[nodeIndex]
nodeIndex = nodeIndex + 1
time = time + (Qnode + timeAccumulated * wnode)
timeAcumulated = timeAccumulated + tinode
T = adjustMiddleNodes(T, n, node)
end while
time = time + (timeAccumulated * win)
return time
O = {n’’ ∈ N | (n’ → n’’) ∈ E*}
N=N\O
n’ = n’’ | (n’’ → n’) ∈ E
while (n’ ≠ n)
(_, Qn’) = calculateSpOptimal(T, n’)
wn’ = wn’ - |O|
n’ = n’’ | (n’’ → n’) ∈ E
end while
return T
n1
n4
1
9
n2
6|2
n6
n3
n7
3
n5
1
2
1
1
L
1
2
3
2
1
3
2
3
…
2
3
2
1
L
3
2
L
2
1
2
6
4
6
L
3
2
…
2
3
3
4
…
3
4
5
6
1 - Memory problem
The size of the ET can be huge
It does not usually fit in main memory
2 - Graphic problem
The whole ET cannot be shown at the same time
3 - Time problem
• Generating the ET is costly
• The problem is even worse with databases
In some languages the problem is inherent
to the current technology
Java: The Java Platform Debugger Architecture
JVM
Source
Code
JPDA
Execution Tree
3 - Time problem
• Generating the ET is costly
• The problem is even worse with databases
In some languages the problem is inherent
to the current technology
Java: The Java Platform Debugger Architecture
Benchmark
ET time
argparser
22 s.
cglib
230 s.
kxml2
1318 s.
javassist
556 s.
jtstcase
1913 s.
HTMLcleaner
4828 s.
Key ideas:
Memory problem 
Store the ET in a database
Graphic problem 
Use a clustering mechanism based on a cache memory system
Time problem
JPDA

Allow the user to debug before the ET has been generated
-> Use a virtual ET (and reimplement the strategies for VETs)
Interface communication
- Communicates with the user
- Controls what nodes are shown
in the GUI
Selecting questions
- Selects the nodes of the VET to
be asked about
- Implements the search
strategies
Construction of the VET
- The only interface with JPDA
- Wakes up thread 2 when the
VET is too big.
- It sleeps when the persistence
bound is reached
Storage of the VET
- It controls what nodes are
stored in the database
- Removes half of the nodes,
sleeps and weaks up thread 1
The cache system:
n
…
m
n
m
…
Persistence cache
m
…
Logic cache
Presentation cache
Redefining search strategies:
…
…
…
Top-Down

Heaviest First
Heaviest First
Divide & Query
Divide & Query




…

…
It cannot
even
startthose
because
thethat
root
node
is the last
thathave
will abe completed
only asks
about
nodes
are
completed
andnode
do not
completed ancestor
The heaviest node could not be completed yet
It would ask first about the heaviest node of the previous ones
The node that divides the tree in half may not be completed yet
It would ask about the completed node that better divides the VET in two
subtrees with the same number of nodes
…
1
L
1
2
3
2
1
3
2
3
…
2
3
2
1
L
3
2
L
2
1
2
6
4
6
L
3
2
…
2
3
3
4
…
3
4
5
6
An execution tree is balanced (binomial) when:
having the evidence that a bug can be found in the tree,
a node that divides the tree in half can be found after every question
16
4
8
2
2
4
4
1
4
4
2
1
4
4
4
4
4
1
4
1
1
1
1
1
2
4
4
4
4
4
4
4
public class Chess {
public static void main(String[] args) {
Chess c = new Chess();
Position rook = new Position();
Position king = new Position();
king.locate(5, 1);
rook.locate(8, 1);
c.castling(rook, king);
}
void castling(Position r, Position k) {
if (r.x != 8) {
for (int i=1; i<=2; i++) { r.left(); }
for (int i=1; i<=2; i++) { k.right(); }
} else {
for (int i=1; i<=3; i++) { r.right(); }
for (int i=1; i<=2; i++) { k.left(); }
}
}
}
class Position {
int x, y;
void locate (int a, int b) { x = a; y = b; }
void up() { y = y + 1; }
void down() { y = y - 1; }
void right() { x = x + 1; }
void left() { x = x - 1; }
}
king.x=5
king.y=1
rook.x=8
rook.y=1
r.x=8
r.x=9
r.right()
r.y=1
r.y=1
r.x=9
r.x=10
r.right()
r.y=1
r.y=1
c.castling(rook,king)
r.x=10
r.x=11
r.right()
r.y=1
r.y=1
king.x=3
king.y=1
rook.x=11
rook.y=1
k.x=5
k.x=4
k.left()
k.y=1
k.y=1
k.x=4
k.x=3
k.left()
k.y=1
k.y=1
king.x=5
king.y=1
rook.x=8
rook.y=1
r.right()
r.x=8
r.x=11
r.right()
r.y=1
r.y=1
r.right()
r.x=8
r.x=9
r.right()
r.y=1
r.y=1
r.x=9
r.x=10
r.right()
r.y=1
r.y=1
c.castling(rook,king)
r.x=10
r.x=11
r.right()
r.y=1
r.y=1
king.x=3
king.y=1
rook.x=11
rook.y=1
k.x=5 k.left() k.x=3
k.y=1 k.left() k.y=1
k.x=5
k.x=4
k.left()
k.y=1
k.y=1
k.x=4
k.x=3
k.left()
k.y=1
k.y=1
king.x=5
king.y=1
rook.x=8
rook.y=1
c.castling(rook,king)
k.x=5 k.left() k.x=3
k.y=1 k.left() k.y=1
r.right()
r.x=8
r.x=11
r.right()
r.y=1
r.y=1
r.right()
r.x=8
r.x=9
r.y=1 r.right() r.y=1
r.x=9
r.x=10
r.y=1 r.right() r.y=1
king.x=3
king.y=1
rook.x=11
rook.y=1
r.x=10
r.x=11
r.y=1 r.right() r.y=1
k.x=5
k.x=4
k.y=1 k.left() k.y=1
k.x=4
k.x=3
k.y=1 k.left() k.y=1
Search strategy
Left to Right
Heaviest First
D&Q Shapiro
D&Q Hirunkitti
NB
8.021
7.875
7.229
6.792
B
6.957
6.804
5.978
5.717
Reduction (%)
13.27 %
13.60 %
17.31 %
15.82 %
1
L
1
2
3
2
1
3
2
3
…
2
3
2
1
L
3
2
L
2
1
2
6
4
6
L
3
2
…
2
3
3
4
…
3
4
5
6
public void sqrt(double x) {
if (x < 0)
return Double.NaN;
double b = x;
while (Math.abs(b * b - x) > 1e-12)
b = approx(x, b);
return b;
}
public void approx(double x, double b) {
return ((x / b) + b) / 2;
}
1
2
2
2
2
2
2
…
public void sqrt(double x) {
if (x < 0)
return Double.NaN;
double b = x;
{
if (Math.abs(b * b - x) > 1e-12) {
Object[] result = this.sqrt_loop(x, b);
x = (Double) result[0];
b = (Double) result[1];
}
}
return b;
}
private Object[] sqrt_loop(double x, double b) {
b = approx(x, b);
if (Math.abs(b * b - x) > 1e-12)
return this.sqrt_loop(x, b);
return new Object[] { x, b };
}
1
L
2
L
2
L
L
2
…
…
1
L
1
2
3
2
3
2
3
…
2
3
L
2
public void sqrt(double x) {
if (x < 0)
return Double.NaN;
double b = x;
while (Math.abs(b * b - x) > 1e-12)
b = approx(x, b);
return b;
}
3
2
L
L
3
…
…
1
L
1
2
3
2
1
3
2
3
…
2
3
2
1
L
3
2
L
2
1
2
6
4
6
L
3
2
…
2
3
3
4
…
3
4
5
6
1
1
2
1
2
3
2
2
3
6
4
3
4
4
6
5
6
32 / 9 = 3.55
1 2
1
1 4
2
2
2
2
3
4
2
3
2
5
4
2
5
26 / 8 = 3.25
27 / 7 = 3.86
1 4
1 6
2
1
2
2
2
3
2
4
2
5
2
1 4
2
6
2
2
2
3
2
4
2
2
3
2
4
0
2
1
5
3
4
6
7
Q1 = (Q2 + W2) + (Q3 + 2W3) + (Q4 + 3W4) + 4WI1
Q0 = (Q1 + W1) + (Q5 + 2W5) + (Q6 + 3W6) + (Q7 + 4W7) + 5WI0
Q0 = (Q2 + Q3 + Q4) + Q5 + Q6 + Q7 +
W1 + (W2 + 2W3 + 3W4 + 4WI1) + 2W5 + 3W6 + 4W7 + 5WI0
0
2
3
4
5
6
7
Q0 = (Q2 + Q3 + Q4) + Q5 + Q6 + Q7 +
W1 + (W2 + 2W3 + 3W4 + 4WI1) + 2W5 + 3W6 + 4W7 + 5WI0
Q’0 = (Q2 + W2) + (Q3 + 2W3) + (Q4 + 3W4) +
(Q5 + 4W5) + (Q6 + 5W6) + (Q7 + 6W7) + 5WI0
Q’0 = Q2 + Q3 + Q4 + Q5 + Q6 + Q7 +
W2 + 2W3 + 3W4 + 4W5 + 5W6 + 6W7 + 7WI0
0
1
2
3
5
6
4
0
7
2
3
4
6
5
7
Q0 = (Q2 + Q3 + Q4) + Q5 + Q6 + Q7 +
W1 + (W2 + 2W3 + 3W4 + 4WI1) + 2W5 + 3W6 + 4W7 + 5WI0
Q’0 = Q2 + Q3 + Q4 + Q5 + Q6 + Q7 +
Cost(nodes)
W6node
| node
∈ nodes} + |nodes| + 1
W2 =+ Σ{Pos(node,
2W3 + 3W4 +nodes)
4W5 + *5W
+ 6W
7 + 7WI0
Q0 = Cost(nodes0) + Cost(nodes1)
Q’0 = Cost(nodes’0)
Coste(nodes0) + Coste(nodes1)
AVG0 =
W0
Coste(nodes’0)
AVG’0 =
W’0
>-
recs = {n | n,n’ ∈ N ∧ (n → n’) ∈ E } ∧ l(n) = l(n’)}
(1) while (recs ≠ ∅)
(2)
take n ∈ recs such that ∃/ n’ ∈ recs with (n → n’) ∈ E+
(3)
recs = recs \ {n}
(4)
parent = n
(5)
do
(6)
maxImpr = 0
(7)
children = {c | (n → c) ∈ E ∧ l(n) = l(c)}
(8)
for each child ∈ children
(9)
pchildren = Sort(Children(parent))
(10)
cchildren = Sort(Children(child))
(11)
comb = Sort((pchildren ∪ cchildren) \ {child})
(12)
impr =
Coste(pchildren) + Coste(cchildren)
Wparent
-
(13)
if (impr > maxImpr)
(14)
maxImpr = impr
(15)
bestNode = child
(16)
end for each
(17)
if (maxImpr ≠ 0)
(18)
T’ = Compress(T’, parent, bestNode)
(19)
while (maxImpr ≠ 0)
(20) end while
Coste(comb)
Wparent - 1
1
1
2
1
2
3
Cost(nodes) = Σ{Pos(node, nodes) * Wnode | node ∈ nodes} + |nodes| + 1
2
2
3
6
4
3
4
4
6
5
6
Benchmark
Factoricer
Classifier
LegendGame
Romanic
FibRecursive
FactTrans
BinaryArrays
FibFactAna
RegresionTest
BoubleFibArrays
StatsMeanFib
Integral
TestMath
TestMath2
Figures
FactCalc
SpaceLimits
Average
ET
55
25
87
121
5378
197
141
178
13
16
19
5
3
92
2
128
95
385.59
Nodes
LE
TCori
331
51
57
22
243
87
171
112
6192
98
212
24
203
100
261
244
121
15
164
10
50
23
8
8
5
3
2493
13
10
10
179
75
133
98
637.24 46.65
TCopt
51
24
87
113
101
26
100
3 49
15
10
23
8
3
13
10
75
100
47.53
LE
5
3
10
3
12
3
5
27
5
10
6
3
3
3
24
3
15
7.06
Time
LE
TC
151
105
184
4
259
31
191
12
1L 251
953
181
26
172
79
3 202L 2 33
237
4
213
27
195
21
152
L2
195
2
211
607
597
13
206
46
786
10
257.80 116.18
ET
11.62
8.64
12.81
16.24
15.64
10.75
12.17
3 7.90
4.77
9.31
7.79
6.80
7.67
14.70
9.00
8.45
36.26
11.80
Questions
%
LE
TCori TCopt LETC
TC
8.50
7.35
7.35
63.25
100.0
6.19
6.46
6.29
72.80
97.36
8.28
11.84 11.84
92.43
100.0
7.74
10.75
9.42
58.00
87.62
12.91
9.21
8.00
51.15
86.86
7.88
6.42
5.08
47.26
79.13
7.76
7.89
7.89
64.83
100.0
8.29
8.50
6.06
76.71
71.29
7.17
4.20
4.20
88.05
100.0
8.79
4.90
4.90
52.63
100.0
8.12
6.78
6.48
83.18
95.58
5.75
7.88
5.88
86.47
74.62
6.00
9.00
7.67
100.0
85.22
11.54
15.77 12.77
86.87
80.98
7.20
6.60
6.60
73.33
100.0
7.60
7.96
7.96
94.20
100.0
12.29
18.46 14.04
38.72
76.06
8.35
8.82
7.79
72.35 90.28
 2 search strategies


A new version of Divide & Query that is better in practice → Hirunkitti’s D&Q is not optimal
An optimal search strategy with respect to the number of questions
 4 techniques

Virtual Execution Trees allows for starting the debugging session almost instantly

Tree Balancing reduces the amount of questions the user is asked

Loop Expansion increases the granularity level of the bugs found

Tree Compression better balances the ET
 2 debuggers

DDJ Desktop version

HDJ Eclipse plugin: DDJ & Trace Debugger & Omniscient Debugger
 1 generalized model for algorithmic debugging
 1 Java library: loops2Recursion
 Tree Balancing
 A suitable balancing process for Divide & Query strategies is needed
 Tree Compression
 A local minimum detection process has been defined, but a global minimum one
would generate less questions
 Divide by Queries
 An implementation is needed that finds (or at least approximate) the optimal node
in a reasonable time
 Hybrid Debugger for Java (HDJ)
 The Declarative Debugger and Trace Debugger implement their currect state of the art
 The Omniscient Debugger is implemented from scratch and only the most important
features are present
 Nationals
David Insa, Josep Silva, Cesar Tomas Mejora del rendimiento de la depuración declarativa mediante expansión y compresión de bucles
XII Jornadas de PROgramación y LEnguajes (PROLE 2012) - Almería (Spain)
David Insa, Josep Silva An Improved Version of Divide and Query
XI Jornadas de PROgramación y LEnguajes (PROLE 2011) - A Coruña (Spain)
David Insa, Josep Silva Hacia una estrategia óptima para la depuración algorítmica
XI Jornadas de PROgramación y LEnguajes (PROLE 2011) - A Coruña (Spain)
David Insa, Josep Silva, Adrian Riesco Balancing Execution Trees
X Jornadas de PROgramación y LEnguajes (PROLE 2010) - Valencia (Spain)
 Journals
David Insa, Josep Silva Automatic Transformation of Iterative Loops into Recursive Methods
Information and Software Technology (Information 2015)
David Insa, Josep Silva Implementation of an Optimal Strategy for Algorithmic Debugging
Electronic Notes in Theoretical Computer Science (ENTCS 2012)
 Internationals
David Insa, Josep Silva An Optimal Strategy for Algorithmic Debugging
26th IEEE/ACM International Conference On Automated Software Engineering (ASE 2011) - Kansas (USA)
David Insa, Josep Silva An Algorithmic Debugger for Java
26th IEEE International Conference on Software Maintenance (ICSM 2010) - Timisoara (Romania)
David Insa, Josep Silva A Generalization and Paradigm-Independent Reformulation of Algorithmic Debugging
24th International Symposium on LOgic-Based Program Synthesis and TRansformation (LOPSTR 2015) - Siena (Italy)
David Insa, Josep Silva, Juan González A New Hybrid Debugging Architecture for Eclipse
23rd International Symposium on LOgic-Based Program Synthesis and TRansformation (LOPSTR 2013) - Madrid (Spain)
David Insa, Josep Silva, Adrian Riesco Speeding Up Algorithmic Debugging Using Balanced Execution Trees
7th International Conference on Tests & Proofs (TAP 2013) - Budapest (Hungary)
David Insa, Josep Silva Enhancing Declarative Debugging with Loop Expansion and Tree Compression
22nd International Symposium on LOgic-Based Program Synthesis and TRansformation (LOPSTR 2012) - Leuven (Belgium)
David Insa, Josep Silva Optimal Divide & Query
15th Portuguese Conference on Artificial Intelligence (EPIA 2011) - Lisboa (Portugal)
David Insa, Josep Silva Scaling Up Algorithmic Debugging with Virtual Execution Trees
20th International Symposium on LOgic-Based Program Synthesis and TRansformation (LOPSTR 2010) - Hagenberg (Austria)