Visualising Program Behaviour
2 Program visualisation tools in ECLiPSe Debugger Profiler Coverage Display matrix Visualisation Debugger Profiler Coverage Display matrix Visualisation
3 Profiler - sample based code profiling Any goal can be profiled Does not require special compilation 0.01s sample interval Not available on MS Window (currently) Any goal can be profiled Does not require special compilation 0.01s sample interval Not available on MS Window (currently) queen(Data, Out) :- qperm(Data, Out), safe(Out). qperm([], []). qperm([X|Y], [U|V]) :- qdelete(U, X, Y, Z), qperm(Z, V). qdelete(A, A, L, L). qdelete(X, A, [H|T], [A|R]) :- qdelete(X, H, T, R). safe([]). safe([N|L]) :- nodiag(L, N, 1), safe(L). nodiag([], _, _). nodiag([N|L], B, D) :- D =\= N - B, D =\= B - N, D1 is D + 1, nodiag(L, B, D1). queen(Data, Out) :- qperm(Data, Out), safe(Out). qperm([], []). qperm([X|Y], [U|V]) :- qdelete(U, X, Y, Z), qperm(Z, V). qdelete(A, A, L, L). qdelete(X, A, [H|T], [A|R]) :- qdelete(X, H, T, R). safe([]). safe([N|L]) :- nodiag(L, N, 1), safe(L). nodiag([], _, _). nodiag([N|L], B, D) :- D =\= N - B, D =\= B - N, D1 is D + 1, nodiag(L, B, D1).
4 Profiler - the profile predicate profile(+Goal) :- profile(queen([1,2,3,4,5,6,7,8,9],Out)). profile(+Goal, +OptionList) :- profile( queen([1,2,3,4,5,6,7,8,9],Out), [simple, keep_file] ). When the goal runs quickly, use an auxiliary queen_100 :- for(_X,1,100) do queen([1,2,3,4,5,6,7,8,9],_Out). :- profile(queen_100). profile(+Goal) :- profile(queen([1,2,3,4,5,6,7,8,9],Out)). profile(+Goal, +OptionList) :- profile( queen([1,2,3,4,5,6,7,8,9],Out), [simple, keep_file] ). When the goal runs quickly, use an auxiliary queen_100 :- for(_X,1,100) do queen([1,2,3,4,5,6,7,8,9],_Out). :- profile(queen_100).
5 Profiler - sample based code profiling goal succeeded PROFILING STATISTICS Goal: queen_100 Total user time: 3.19s Predicate Module %Time Time %Cum nodiag /3 eclipse 52.2% 1.67s 52.2% qdelete /4 eclipse 27.4% 0.87s 79.6% qperm /2 eclipse 17.0% 0.54s 96.5% safe /1 eclipse 2.8% 0.09s 99.4% queen /2 eclipse 0.6% 0.02s 100.0% Yes (3.33s cpu) goal succeeded PROFILING STATISTICS Goal: queen_100 Total user time: 3.19s Predicate Module %Time Time %Cum nodiag /3 eclipse 52.2% 1.67s 52.2% qdelete /4 eclipse 27.4% 0.87s 79.6% qperm /2 eclipse 17.0% 0.54s 96.5% safe /1 eclipse 2.8% 0.09s 99.4% queen /2 eclipse 0.6% 0.02s 100.0% Yes (3.33s cpu)
6 Coverage - source line coverage library queen(Data, Out) :- 1 qperm(Data, Out), 7686 safe(Out) 1. qperm([], []) qperm([X|Y], [U|V]) : qdelete(U, X, Y, Z), qperm(Z, V) qdelete(A, A, L, L) qdelete(X, A, [H|T], [A|R]) : qdelete(X, H, T, R) safe([]) 1. safe([N|L]) : nodiag(L, N, 1), 1338 safe(L) 9. nodiag([], _5917, _5918) nodiag([N|L], B, D) : D =\= N - B, D =\= B - N, D1 is D + 1, nodiag(L, B, D1) Requires special compilation Inserts coverage counters into the code Entry to code blocks Between predicate calls within a block At the end of code blocks Pretty prints source annotated with counter values
7 Coverage - source line coverage library The ccompile predicate compiles and loads a file adding coverage counters as it does so ccompile(+File) :- ccompile(’foo.ecl’). ccompile(+File, +OptionList) :- ccompile(’foo.ecl’, [exit_counters:off, macro_expansion:off]). The ccompile predicate compiles and loads a file adding coverage counters as it does so ccompile(+File) :- ccompile(’foo.ecl’). ccompile(+File, +OptionList) :- ccompile(’foo.ecl’, [exit_counters:off, macro_expansion:off]).
8 Coverage - source line coverage library All coverage counters are reset by calling reset_counters/0 The result predicate outputs source code annotated with coverage counter values result/0 result(+File) :- result(‘foo.ecl’). result(+File, +OptionList) :- result(‘foo.ecl’, [outdir:coverage, format:html]). All coverage counters are reset by calling reset_counters/0 The result predicate outputs source code annotated with coverage counter values result/0 result(+File) :- result(‘foo.ecl’). result(+File, +OptionList) :- result(‘foo.ecl’, [outdir:coverage, format:html]).
9 Coverage - source line coverage library queen(Data, Out) :- 1 qperm(Data, Out), 7686 safe(Out) 1. qperm([], []) qperm([X|Y], [U|V]) : qdelete(U, X, Y, Z), qperm(Z, V) qdelete(A, A, L, L) qdelete(X, A, [H|T], [A|R]) : qdelete(X, H, T, R) safe([]) 1. safe([N|L]) : nodiag(L, N, 1), 1338 safe(L) 9. nodiag([], _5917, _5918) nodiag([N|L], B, D) : D =\= N - B, D =\= B - N, D1 is D + 1, nodiag(L, B, D1) :-lib(coverage). :-ccompile(“foo.ecl”). :-queen( [1,2,3,4,5,6,7,8,9], Out ). :-result(“foo.ecl”).
10 Visualisation - control flow Visualisation Client Debugger Annotated source code
11 More Details... See ECLiPSe User Manual Profiling Prolog Execution chapter See ECLiPSe Library Manual Coverage library See ECLiPSe Visualisation Tutorial See ECLiPSe User Manual Profiling Prolog Execution chapter See ECLiPSe Library Manual Coverage library See ECLiPSe Visualisation Tutorial
12 SEND + MORE = MONEY :-lib(ic). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], Carries = [C1,C2,C3,C4], Carries :: [0..1], alldifferent(Digits), S #\= 0, M #\= 0, C1 #= M, C2 + S + M #= O + 10*C1, C3 + E + O #= N + 10*C2, C4 + N + R #= E + 10*C3, D + E #= Y + 10*C4, lab(Carries), lab(Digits). :-lib(ic). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], Carries = [C1,C2,C3,C4], Carries :: [0..1], alldifferent(Digits), S #\= 0, M #\= 0, C1 #= M, C2 + S + M #= O + 10*C1, C3 + E + O #= N + 10*C2, C4 + N + R #= E + 10*C3, D + E #= Y + 10*C4, lab(Carries), lab(Digits).
13 SEND + MORE = MONEY (annotated) :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore1(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, Digits), Carries = [C1,C2,C3,C4], Carries :: [0..1], alldifferent(Digits), S #\= 0, M #\= 0, C1 #= M, C2 + S + M #= O + 10*C1, C3 + E + O #= N + 10*C2, C4 + N + R #= E + 10*C3, D + E #= Y + 10*C4, lab(Carries), lab(Digits). :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore1(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, Digits), Carries = [C1,C2,C3,C4], Carries :: [0..1], alldifferent(Digits), S #\= 0, M #\= 0, C1 #= M, C2 + S + M #= O + 10*C1, C3 + E + O #= N + 10*C2, C4 + N + R #= E + 10*C3, D + E #= Y + 10*C4, lab(Carries), lab(Digits).
14 SEND + MORE = MONEY (annotated II) :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore2(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, Digits, array([flexible],numeric_bounds)), Carries = [C1,C2,C3,C4],... lab(Digits), viewable_expand(equation, 1, C1), viewable_expand(equation, 1, C2), viewable_expand(equation, 1, C3), viewable_expand(equation, 1, C4). :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore2(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, Digits, array([flexible],numeric_bounds)), Carries = [C1,C2,C3,C4],... lab(Digits), viewable_expand(equation, 1, C1), viewable_expand(equation, 1, C2), viewable_expand(equation, 1, C3), viewable_expand(equation, 1, C4).
15 SEND + MORE = MONEY (annotated III) :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore3(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, []([](0, S, E, N, D), [](0, M, O, R, E), [](M, O, N, E, Y)), array([flexible,fixed], numeric_bounds)), Carries = [C1,C2,C3,C4],... lab(Carries), lab(Digits), viewable_expand(equation, 1, [C1, C2, C3, C4, 0]). :-lib(ic). :-lib(viewable). lab([]). lab([X|Xs]):- indomain(X), lab(Xs). sendmore3(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, []([](0, S, E, N, D), [](0, M, O, R, E), [](M, O, N, E, Y)), array([flexible,fixed], numeric_bounds)), Carries = [C1,C2,C3,C4],... lab(Carries), lab(Digits), viewable_expand(equation, 1, [C1, C2, C3, C4, 0]).
16 SEND + MORE = MONEY (annotated IV) :-lib(ic). :-lib(viewable).... sendmore4(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, []([](0, S, E, N, D), [](0, M, O, R, E), [](M, O, N, E, Y)), array([flexible,fixed], numeric_bounds), [["send", "more", "money"], ["ten thousands", "thousands", "hundreds","tens", "units"]]), Carries = [C1,C2,C3,C4],... lab(Carries), lab(Digits), viewable_expand(equation, 1, [C1, C2, C3, C4, 0], "carries"). :-lib(ic). :-lib(viewable).... sendmore4(Digits) :- Digits = [S,E,N,D,M,O,R,Y], Digits :: [0..9], viewable_create(equation, []([](0, S, E, N, D), [](0, M, O, R, E), [](M, O, N, E, Y)), array([flexible,fixed], numeric_bounds), [["send", "more", "money"], ["ten thousands", "thousands", "hundreds","tens", "units"]]), Carries = [C1,C2,C3,C4],... lab(Carries), lab(Digits), viewable_expand(equation, 1, [C1, C2, C3, C4, 0], "carries").