1 % (c) 2009-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5
6 /* visualize_graph.pl */
7 :- module(visualize_graph,[tcltk_print_states_for_dot/1, tcltk_print_states_for_dot/2,
8 tcltk_print_states_for_dot_sfdp/1, tcltk_print_states_for_dot_sfdp/2,
9 tcltk_print_neighbourhood_states_for_dot/2,
10 tcltk_print_current_state_for_dot/1,
11 tcltk_print_shortest_trace_to_current_state_for_dot/1,
12 %tcltk_print_trace_to_current_state_for_dot/1, % removed
13 tcltk_print_current_state_as_graph_for_dot/1, tcltk_print_state_as_graph_for_dot/2,
14 tcltk_print_history_to_current_state_for_dot/1,
15 tcltk_print_history_to_current_state_with_neighbors_for_dot/1,
16 % tcltk_print_transition_diagram_for_variable_or_expr/2, % moved to state_space_reduction
17 tcltk_print_definitions_as_graph_for_dot/1,
18 tcltk_print_predicate_dependency_as_graph_for_dot/2,
19 tcltk_print_csp_process_states_for_dot/2,
20 print_graph_header/1,
21 print_graph_footer/0,
22
23 convert_state_to_string/2]).
24
25
26 :- use_module(module_information).
27 :- module_info(group,dot).
28 :- module_info(description,'This module generates various dot graphs (state space, single state, transition diagram,...).').
29
30 :- use_module(library(lists)).
31 :- use_module(preferences).
32
33 :- use_module(debug).
34 :- use_module(self_check).
35 :- use_module(translate).
36 :- use_module(bmachine,[b_is_constant/1]).
37
38 :- use_module(state_space).
39 :- use_module(dot_graph_generator,[translate_bvalue_to_colour/2, translate_int_col/2]).
40 :- use_module(state_space_exploration_modes,[compute_heuristic_function_for_state_id/2]).
41
42 /* --------------------------------------------------- */
43 /* MAIN ENTRY POINTS FOR TCL */
44 /* --------------------------------------------------- */
45
46
47 % print full state space for dot:
48
49 % a version for large graphs; where we automatically turn off some details
50 tcltk_print_states_for_dot_sfdp(F) :-
51 tcltk_print_states_for_dot_sfdp(F,colour_transitions).
52 tcltk_print_states_for_dot_sfdp(F,ColourTransitions) :-
53 temporary_set_preference(dot_print_node_info,false,CHNG1),
54 temporary_set_preference(dot_print_node_properties,false,CHNG2),
55 temporary_set_preference(dot_print_self_loops,false,CHNG3),
56 temporary_set_preference(dot_fill_normal_nodes,true,CHNG4),
57 call_cleanup(tcltk_print_states_for_dot(F,ColourTransitions),
58 (preferences:reset_temporary_preference(dot_print_node_info,CHNG1),
59 preferences:reset_temporary_preference(dot_print_node_properties,CHNG2),
60 preferences:reset_temporary_preference(dot_print_self_loops,CHNG3),
61 preferences:reset_temporary_preference(dot_fill_normal_nodes,CHNG4))).
62
63 tcltk_print_states_for_dot(F) :- tcltk_print_states_for_dot(F,no_colour_for_transitions).
64 tcltk_print_states_for_dot(F,ColourTransitions) :-
65 format('Writing states to dot file ~w~n',[F]),
66 tell(F),(tcltk_print_states_for_dot_aux(ColourTransitions) -> true ; true),told.
67
68 tcltk_print_states_for_dot_aux(ColourTransitions) :-
69 reset_label_nr(ColourTransitions),
70 print_graph_header(visited_states),
71 visited_expression_id(NodeID),
72 tcltk_print_node_for_dot(NodeID),
73 tcltk_print_transitions_for_dot(NodeID,_),
74 fail.
75 tcltk_print_states_for_dot_aux(_ColourTransitions) :-
76 print_graph_footer.
77
78
79 tcltk_print_neighbourhood_states_for_dot(Dist,F) :-
80 retractall(unfiltered_state(_,_)),
81 current_state_id(CurID),
82 (dfs(CurID,Dist) -> true ; true), % mark neighbours until distance Dist
83 tell(F),(tcltk_print_unfiltered_states_for_dot -> true ; true),told.
84
85 :- dynamic unfiltered_state/2.
86 dfs(ID,Dist) :- unfiltered_state(ID,D1), (D1>=Dist -> ! ; retract(unfiltered_state(ID,D1))),fail.
87 dfs(ID,Dist) :- assert(unfiltered_state(ID,Dist)), D1 is Dist-1,
88 D1>0,
89 any_transition(ID,_,NodeID),
90 dfs(NodeID,D1).
91
92 tcltk_print_unfiltered_states_for_dot :- reset_label_nr,
93 print_graph_header_with_layout(neighbourhood,sfdp),
94 unfiltered_state(NodeID,Dist),
95 tcltk_print_node_for_dot(NodeID,[pendwidth/Dist]),
96 tcltk_print_transitions_for_dot(NodeID,_),
97 fail.
98 tcltk_print_unfiltered_states_for_dot :-
99 print_graph_footer.
100
101 % --------------------------
102 tcltk_print_csp_process_states_for_dot(F,ProcID) :-
103 tell(F),(tcltk_print_csp_process_states_for_dot_root(ProcID) -> true ; true),told.
104
105 tcltk_print_csp_process_states_for_dot_root(ProcID) :-
106 reset_label_nr,
107 print_graph_header(csp_process),
108 tcltk_print_node_for_dot(root),
109 tcltk_print_transitions_for_dot(root,ProcID),
110 tcltk_print_csp_process_states_for_dot.
111
112 tcltk_print_csp_process_states_for_dot :-
113 refinement_checker: dvisited(NodeID),
114 tcltk_print_node_for_dot(NodeID),
115 tcltk_print_transitions_for_dot(NodeID,_),
116 fail.
117 tcltk_print_csp_process_states_for_dot :-
118 print_graph_footer.
119
120 % --------------------------
121
122 tcltk_print_current_state_for_dot(F) :-
123 tell(F), (tcltk_print_current_state_for_dot -> true ; true),told.
124 tcltk_print_current_state_for_dot :-
125 reset_label_nr,
126 print_graph_header(current_state),
127 current_state_id(CurID),
128 ( (NodeID=CurID) ;
129 any_transition(CurID,_,NodeID)),
130 tcltk_print_node_for_dot(NodeID),
131 fail.
132 tcltk_print_current_state_for_dot :-
133 current_state_id(CurID),
134 tcltk_print_transitions_for_dot(CurID,_),
135 fail.
136 tcltk_print_current_state_for_dot :-
137 print_graph_footer.
138
139
140 tcltk_print_shortest_trace_to_current_state_for_dot(F) :-
141 tell(F), (tcltk_print_shortest_trace_to_current_state_for_dot -> true ; true),told.
142 tcltk_print_shortest_trace_to_current_state_for_dot :-
143 reset_label_nr,
144 print_graph_header(shortest_trace_to_current_state),
145 current_state_id(CurID),
146 user:find_shortest_trace_to_node(root,CurID,_,StateIDList),
147 print_trace_to_current_state(StateIDList),
148 print_graph_footer.
149
150
151 tcltk_print_history_to_current_state_for_dot(F) :-
152 tell(F), (tcltk_print_history_to_current_state_for_dot -> true ; true),told.
153 tcltk_print_history_to_current_state_for_dot :-
154 reset_label_nr,
155 print_graph_header(history),
156 current_state_id(CurID),
157 history(H),
158 reverse([CurID|H],IDList),
159 print_trace_to_current_state(IDList),
160 print_graph_footer.
161
162 % called for fairness formulas (currently only in CSP refinement checking mode)
163 tcltk_print_history_to_current_state_with_neighbors_for_dot(F) :-
164 tell(F), (tcltk_print_history_to_current_state_with_neighbors_for_dot -> true ; true),told.
165 tcltk_print_history_to_current_state_with_neighbors_for_dot :-
166 reset_label_nr,
167 print_graph_header(history),
168 current_state_id(CurID),
169 history(H),
170 reverse([CurID|H],IDList),
171 print_trace_with_neighbors_to_current_state(IDList),
172 print_graph_footer.
173
174 /* ---------------------------------------------------------------------- */
175
176
177 :-use_module(dot_graph_generator,[gen_dot_graph/6]).
178
179 % this predicate is currently not used anywhere, graph_canon:print_cstate_graph is used instead
180 tcltk_print_current_state_as_graph_for_dot(File) :-
181 current_expression(_CurID,State),
182 tcltk_print_state_as_graph_for_dot(State,File).
183 tcltk_print_state_as_graph_for_dot(State,File) :-
184 print(gen_graph(State)),nl,
185 gen_dot_graph(File,visualize_graph,dot_state_node,dot_state_trans(State),dot_same_rank,dot_subgraph).
186
187 :- public dot_state_node/6.
188 :- use_module(b_global_sets,[b_global_set/1,is_b_global_constant/3,all_elements_of_type/2]).
189 dot_state_node(ID,SET,Desc,box,none,Color) :-
190 b_global_set(SET), Desc = ID,
191 if(is_b_global_constant(SET,_Nr,Cst),
192 (Color=red,ID = Cst),
193 (Color=blue,
194 all_elements_of_type(SET,AllVals),
195 member(X,AllVals),
196 translate_bvalue(X,ID)
197 )
198 ).
199 dot_state_node(root,none,'','Mdiamond',none,green).
200
201 :- public dot_subgraph/3.
202 dot_subgraph(SubGraph,filled,lightgray) :-
203 b_global_set(SubGraph).
204
205 :- public dot_same_rank/1.
206 dot_same_rank(_TVals) :- fail.
207 % old version: b_global_set(SET),all_elements_of_type(SET,AllVals),translate_values(AllVals,TVals).
208
209 :- public dot_state_trans/6.
210 :- use_module(store,[get_id_value/3]).
211 dot_state_trans(State,NodeID,Label,SuccNodeID,Color,Style) :- Style=solid,
212 get_id_value(VarOrConstant,State,VarValue),
213 dot_state_trans_var(VarValue,NodeID,SuccNodeID,VarOrConstant,Label),
214 (b_is_constant(VarOrConstant) -> Color=blue ; Color=black).
215
216 :- use_module(gensym).
217
218 dot_state_trans_var(VarValue,NodeID,SuccNodeID,Var,Var) :-
219 dot_state_basic_pair(VarValue,X1,X2), /* we have a relation or a pair */
220 dot_state_basic_type(X1), El1=X1,
221 dot_state_basic_type(X2), El2=X2, /* in case it is a function: we can also accept El2 to be dot_state_basic_type_or_element */
222 translate_bvalue(El1,NodeID),
223 translate_bvalue(El2,SuccNodeID).
224 dot_state_trans_var(VarValue,NodeID,SuccNodeID,Var,Var) :-
225 dot_state_basic_type_or_element(VarValue,V),
226 NodeID = root,
227 translate_bvalue(V,SuccNodeID).
228 dot_state_trans_var(VarValue,NodeID,SuccNodeID,Var,Label) :-
229 ( (member(X,VarValue),Kind=el)
230 ; (VarValue=(X,_),Kind=prj1)
231 ; (VarValue=(_,X),Kind=prj2)
232 ),
233 \+ directly_representable_element(X),
234 gensym(Var,IntNode),
235 ((NodeID = root, SuccNodeID = IntNode, Label=Var)
236 ;
237 dot_state_trans_internal(IntNode,Kind,X,NodeID,SuccNodeID,Label)
238 ).
239
240
241 directly_representable_element(X) :- dot_state_basic_type(X).
242 directly_representable_element((X1,X2)) :-
243 dot_state_basic_type(X1),
244 dot_state_basic_type(X2).
245
246 dot_state_basic_type(fd(_,_)).
247 dot_state_basic_type(int(_)).
248 dot_state_basic_type(pred_false /* bool_false */).
249 dot_state_basic_type(pred_true /* bool_true */).
250 dot_state_basic_type(string(_)).
251
252 dot_state_basic_type_or_element(X,X) :- dot_state_basic_type(X).
253 dot_state_basic_type_or_element(S,X) :- member(X,S), dot_state_basic_type(X).
254 dot_state_basic_type_or_element([],empty_set).
255
256 :- use_module(library(avl),[avl_member/2]).
257 dot_state_basic_pair((X1,X2),X1,X2).
258 dot_state_basic_pair([H|T],X1,X2) :- member((X1,X2),[H|T]).
259 dot_state_basic_pair(avl_set(A),X1,X2) :- avl_member((X1,X2),A).
260
261 dot_state_trans_internal(IntNode,Kind,VarValue,NodeID,SuccNodeID,Label) :-
262 dot_state_basic_type_or_element(VarValue,V),
263 translate_bvalue(V,SuccNodeID),
264 NodeID = IntNode, Label=Kind.
265 dot_state_trans_internal(IntNode,Kind,VarValue,NodeID,SuccNodeID,Label) :-
266 dot_state_basic_pair(VarValue,X1,X2), /* we have a relation or a pair */
267 dot_state_basic_type_or_element(X1,El1),
268 dot_state_basic_type_or_element(X2,El2),
269 NodeID = IntNode,
270 ( (translate_bvalue(El1,SuccNodeID), Label = prj1(Kind))
271 ;(translate_bvalue(El2,SuccNodeID), Label = prj2(Kind))
272 ).
273 /* MISSING: recursion */
274
275 /* ---------------------------------------------------------------------- */
276
277
278 print_graph_header(Type) :-
279 format('digraph ~w {~n',[Type]),
280 % print('graph [orientation=landscape, page="8.5, 11",ratio=fill,size="7.5,10"];'),nl. % old default layout
281 % print('graph [page="8.5, 11",ratio=fill,size="7.5,10"];'),nl.
282 print('graph [nodesep=1.5, ranksep=1.5];'), nl.
283
284 % Layout = sdfp, fdp, twopi, dot, ...
285 print_graph_header_with_layout(Type,Layout) :-
286 format('digraph ~w {~n',[Type]),
287 format('graph [nodesep=1.5, ranksep=1.5, layout=~w];~n',[Layout]).
288 % other possible options for graph: splines=true overlap=false ?
289
290 print_graph_footer :- print('}'),nl.
291
292
293 /* ---------------------------------------------------------------------- */
294
295 :- use_module(library(lists),[clumps/2]).
296 :- use_module(library(samsort)).
297 :- use_module(tools,[ajoin/2]).
298 print_trace_to_current_state(IDList) :- samsort(IDList,SIDList), % keeps duplicates
299 clumps(SIDList,Clumps),
300 member([NodeID|T],Clumps),
301 (length([NodeID|T],Len),Len>1
302 -> ajoin(['repeated (',Len,')'],Lbl),
303 tcltk_print_node_for_dot(NodeID,[extralabel/Lbl])
304 ; tcltk_print_node_for_dot(NodeID)),
305 fail.
306 print_trace_to_current_state(IDList) :-
307 temporary_set_preference(dot_print_self_loops,true,CHNG3),
308 print_trace_to_current_state2(IDList),
309 preferences:reset_temporary_preference(dot_print_self_loops,CHNG3).
310
311 print_trace_to_current_state2([]).
312 print_trace_to_current_state2([_]).
313 print_trace_to_current_state2([ID1,ID2|Tail]) :-
314 tcltk_print_transitions_for_dot(ID1,ID2),
315 print_trace_to_current_state2([ID2|Tail]).
316
317 print_trace_with_neighbors_to_current_state(IDList) :- sort(IDList,SIDList),
318 member(NodeID,SIDList),
319 tcltk_print_node_for_dot(NodeID),
320 fail.
321 print_trace_with_neighbors_to_current_state(IDList) :-
322 current_state_id(CurID),
323 nth1(N,IDList,CurID,_Rest),!,
324 append_length(PathToLoop,LoopIDs,IDList,N),
325 %format(user_output,'~w pos=~w : ~w , path to loop=~w, loop=~w~n',[CurID,N,IDList,PathToLoop,LoopIDs]),
326 temporary_set_preference(dot_print_self_loops,true,CHNG3),
327 print_trace_to_current_state2(PathToLoop), % print path to loop
328 print_trace_with_neighbors_to_current_state2([CurID|LoopIDs],IDList), % print loop (with neighbors, because of the fairness check),
329 preferences:reset_temporary_preference(dot_print_self_loops,CHNG3).
330
331 print_trace_with_neighbors_to_current_state2([],_).
332 print_trace_with_neighbors_to_current_state2([ID|Tail],IDList) :-
333 findall(ID,(transition(ID,_,_,SuccID),
334 \+ append(_,[ID,SuccID|_],IDList), % check if the edge is not already shown
335 % format(user_output,'Neighb: ~w -> ~w : idlist=~w, tail=~w~n',[ID,SuccID,IDList,Tail]),
336 tcltk_print_transitions_for_dot(ID,SuccID)),_IDList),
337 print_trace_with_neighbors_to_current_state2(Tail,IDList).
338
339 extract_b_store(csp_and_b(_,T),R) :- !, R=T.
340 extract_b_store(R,R).
341
342 extract_full_store(concrete_constants(C),R) :- !,R=C.
343 extract_full_store(const_and_vars(ConstID,Vars),R) :- !,
344 specfile:expand_const_and_vars(ConstID,Vars,R).
345 extract_full_store(R,R).
346
347 :- use_module(tools,[print_escaped/1]).
348 :- use_module(probltlsrc(ltl),[counterexample_node/1]).
349 :- use_module(model_checker,[find_invariant_error/4]).
350 :- use_module(specfile,[animation_mode/1]).
351
352 tcltk_print_node_for_dot(ID) :- tcltk_print_node_for_dot(ID,[]).
353
354 tcltk_print_node_for_dot(NodeID,Options) :-
355 animation_mode(AM),
356 visited_expression(NodeID,CurT),
357 extract_b_store(CurT,CurBT),
358 extract_full_store(CurBT,CurTemp),
359 (NodeID=root -> preference(dot_print_root,true) ; true),
360 (member(shape/Shape,Options) -> true ; dot_node_shape(NodeID,CurTemp,Shape)),
361 % TO DO: penwidth=2.0, fillcolor="#F1F2D8"
362 print(NodeID), print(' [shape='),print(Shape),
363 (find_invariant_error(AM,NodeID,CurTemp,_)
364 -> get_preference(dot_invariant_violated_node_colour,IColor),
365 print(', style=filled, color=\"'),
366 print(IColor)
367
368 ; ltl:counterexample_node(NodeID)
369 -> get_preference(dot_counterexample_node_colour,CENColour),
370 print(', color=\"'),print(CENColour)
371 ; ((preference(dot_colour_goal_nodes,true),
372 user:test_goal_in_node(NodeID)) % TO DO: add something like STATE_COLOUR_EXPRESSION
373 -> get_preference(dot_goal_node_colour,GoalColor),
374 print(', style=\"rounded,filled\", color=\"'),
375 print(GoalColor)
376 ; (preference(dot_fill_normal_nodes,true) -> print(', style=\"rounded,filled\"') ; true),
377 (member(color/Color,Options) -> true ; dot_node_color(NodeID,Color)),
378 print(', color=\"'),print(Color)
379 )
380 ),
381 print('\"'),
382 (member(fontsize/FSize,Options) -> true ; get_preference(dot_node_font_size,FSize)),
383 print(', fontsize='), print(FSize),
384
385 (member(pendwidth/PenWidth,Options) -> true ; get_preference(dot_node_penwidth,PenWidth)),
386 (PenWidth = 1 -> true ; print(', penwidth='), print(PenWidth)),
387 print(', label=\"'),
388 (member(extralabel/ExtraLbl,Options) -> print_escaped(ExtraLbl), print('\\n') ; true),
389 (preference(dot_print_node_ids,true) -> print(NodeID), print(':\\n') ; true),
390 (preference(dot_print_node_info,true)
391 -> convert_state_to_string(CurT,StateAsString),
392 print_escaped(StateAsString) % quoted encode; except for
393 ; true
394 ),
395 (preference(dot_print_node_properties,true)
396 -> print_node_properties(NodeID)
397 ; true
398 ),
399 print('\"];'),nl,
400 fail.
401 tcltk_print_node_for_dot(_NodeID,_) :- nl.
402
403
404 dot_node_shape(_StateId,State,triangle) :-
405 % state with abort values
406 memberchk(bind(_,term(no_value_for(_))),State),!.
407 dot_node_shape(root,_State,Shape) :-
408 % the root state
409 !,get_preference(dot_root_shape,Shape).
410 dot_node_shape(StateId,_State,Shape) :-
411 % the currently displayed state in the animation
412 current_state_id(StateId),!,
413 get_preference(dot_current_node_shape,Shape).
414 dot_node_shape(StateId,_State,diamond) :-
415 % a state which was subject to permutation flooding
416 transition(StateId,'*permute*',_),!.
417 dot_node_shape(_StateId,_State,Shape) :-
418 % a normal state
419 get_preference(dot_normal_node_shape,Shape).
420
421
422 dot_node_color(StateId,Color) :-
423 % an open state where not all transitions are yet calculated
424 not_all_transitions_added(StateId),!,
425 get_preference(dot_open_node_colour,Color).
426 dot_node_color(StateId,Color) :-
427 % a state which is outside the user-defined state space that should be model-checked
428 not_interesting(StateId),!,
429 get_preference(dot_scope_limit_node_colour,Color).
430 dot_node_color(StateId,Color) :-
431 transition(StateId,'*permute*',_),!, Color = lightgray.
432 dot_node_color(StateId,Color) :-
433 %get_preference(dot_normal_node_colour,Color),
434 compute_heuristic_function_for_state_id(StateId,HRes),
435 !,
436 translate_bvalue_to_colour(HRes,Color). %tools:print_message(heur(HRes,Color)).
437 dot_node_color(_StateId,Color) :-
438 get_preference(dot_normal_node_colour,Color).
439
440
441 :- use_module(specfile,[property/2,elementary_prop/2,b_or_z_mode/0]).
442
443 print_node_properties(ID) :-
444 print(' Prop={'),
445 visited_expression(ID,State),
446 get_state_property(State,PropAsString),
447 print_string_for_dot(PropAsString), print('\\'),print('n'),
448 fail.
449 print_node_properties(_) :- print('}').
450
451 get_state_property(State,PropAsString) :-
452 specfile:property(State,Prop),
453 translate:translate_property_with_limit(Prop,320,PropAsString).
454
455 :- use_module(bmachine,[b_get_machine_animation_expression/1]).
456 :- use_module(specfile,[state_corresponds_to_fully_setup_b_machine/2]).
457 get_animation_expression_value(State,PropAsString) :-
458 b_or_z_mode,
459 b_get_machine_animation_expression(AExpr),
460 state_corresponds_to_fully_setup_b_machine(State,BState),
461 b_interpreter:b_compute_expression_nowf(AExpr,[],BState,AValue),
462 translate:translate_bvalue(AValue,PropAsString).
463
464
465 tcltk_print_transitions_for_dot(NodeID,SuccID) :-
466 transition(NodeID,Action,TransID,SuccID),
467 visited_expression(NodeID,State), set_translation_context(State),
468 (NodeID=root -> preference(dot_print_root,true) ; true),
469 (Action = '-->'(_Func,_)
470 -> (NodeID \= SuccID ; preference(dot_print_functions,true))
471 ; true),
472 (NodeID \= SuccID -> true ; preference(dot_print_self_loops,true)),
473 format('~w -> ~w',[NodeID,SuccID]),
474 (preference(dot_print_arc_colors,true) ->
475 (NodeID==root
476 -> print(' [style = dotted, color = black, label=\"')
477 ; (Action = '*permute*'
478 -> ArcCol=gray
479 ; ltl: counterexample_op(TransID)
480 -> get_preference(dot_counterexample_op_colour,ArcCol)
481 ; dot_arc_color(TransID, Action, ArcCol)
482 ),
483 format(' [color = \"~w\", label=\"',[ArcCol])
484 )
485 ; print(' [label=\"')
486 ),
487 dot_print_action(Action),
488 get_preference(dot_edge_font_size,FSize),
489 format('\", fontsize=~w];~n',[FSize]),
490 fail.
491 tcltk_print_transitions_for_dot(_NodeID,_SuccID) :- clear_translation_constants,nl.
492
493
494 %dot_arc_color(TransID, blue) :-
495 % b_abstract_mappings:widened_trans(TransID),!.
496 dot_arc_color(_,Action,ArcCol) :-
497 get_label_nr(Action,Nr), Nr>0,
498 translate_int_col(Nr,ArcCol),
499 !.
500 dot_arc_color(_TransId,_Action, ArcCol) :-
501 (preference(dot_normal_arc_colour,ArcCol) -> true ; ArcCol=blue).
502 % TO DO: enable colouring; particularly in sfdp mode
503
504 :- dynamic label_nr/2, next_label_nr/1.
505 next_label_nr(0).
506 reset_label_nr :- retractall(label_nr(_,_)), retractall(next_label_nr(_)).
507 reset_label_nr(Colour) :- reset_label_nr,
508 (Colour=colour_transitions
509 -> assert(next_label_nr(0)) % asserts next label nr: we will colour transitions
510 ; true).
511
512 get_label_nr(Action,Nr) :- functor(Action,F,_),
513 (label_nr(F,FNr) -> Nr=FNr
514 ; retract(next_label_nr(N)), N1 is N+1, assert(next_label_nr(N1)), assert(label_nr(F,N)), Nr=N).
515
516
517 dot_print_action(_) :- preference(dot_print_edge_labels,false),!.
518 dot_print_action(Action) :- preference(dot_print_action_arguments,true),
519 self_check:mnf(dot_print_action,translate:translate_event(Action,ActionAsString)),
520 print_string_for_dot(ActionAsString),!.
521 dot_print_action('-->'(FAction,_R)) :- nonvar(FAction),
522 functor(FAction,OperationName,_),!,
523 print_string_for_dot(OperationName).
524 dot_print_action(Action) :- nonvar(Action), functor(Action,OperationName,_),!,
525 print_string_for_dot(OperationName).
526 dot_print_action(Action) :- print('err:'),print_string_for_dot(Action).
527
528 :- use_module(tools,[wrap_and_truncate_atom/4,string_escape/2]).
529 print_string_for_dot(String) :- string_escape(String,EString),
530 wrap_and_truncate_atom(EString,50,350,NS), print(NS).
531
532 /* ------------------------------------------------------------ */
533 /* converting a state into a string for the graph visualization */
534 /* ------------------------------------------------------------ */
535
536
537 :- use_module(tools,[string_concatenate/3]).
538 convert_state_to_string(root,'root') :- !.
539 convert_state_to_string(State,String) :-
540 get_animation_expression_value(State,V),!,
541 String=V.
542 convert_state_to_string(StateTempl,StateAsString) :- animation_mode(xtl),!,
543 convert_state_to_string_default(StateTempl,StateAsString).
544 convert_state_to_string(concrete_constants(CurTemp),StateAsString) :- !,
545 findall(FProp,elementary_prop(CurTemp,FProp),State), /* was fd_findall */
546 translate_params_for_dot(State,StateAsString).
547 convert_state_to_string(const_and_vars(ConstID,StateTempl),StateAsString) :- !,
548 set_translation_constants(ConstID),
549 convert_state_to_string(StateTempl,StateAsString),
550 clear_translation_constants.
551 convert_state_to_string(csp_and_b(CSPState,BState),StateAsString) :- !,
552 translate_cspm_state(CSPState,CSPText),
553 convert_state_to_string(BState,BString),
554 string_concatenate(CSPText,'\n',C2),
555 string_concatenate(C2,BString,StateAsString).
556 convert_state_to_string([H|T],StateAsString) :- !,
557 CurTemp=[H|T],
558 findall(FProp,elementary_prop(CurTemp,FProp),State), /* was fd_findall */
559 translate_params_for_dot(State,StateAsString).
560 convert_state_to_string(StateTempl,StateAsString) :-
561 convert_state_to_string_default(StateTempl,StateAsString).
562
563 convert_state_to_string_default(StateTempl,StateAsString) :-
564 findall(FProp,
565 (property(StateTempl,Prop),filter_elementary_prop(Prop,FProp)),
566 State), /* was fd_findall */
567 translate_params_for_dot(State,StateAsString).
568
569 filter_elementary_prop(X,R) :- \+ b_or_z_mode,!,R=X.
570 filter_elementary_prop('='(Cst,_V),_) :- nonvar(Cst),
571 b_is_constant(Cst),!,fail.
572 filter_elementary_prop(Relation,_) :-
573 functor(Relation,Func,_),
574 b_is_constant(Func),!,fail.
575 filter_elementary_prop('='(_X,pred_false /* bool_false */),_) :- !,fail. /* do not show boolean variables that are false */
576 filter_elementary_prop('='( X,pred_true /* bool_true */), X) :- !. /* just show the boolean variable, not that it is = true */
577 filter_elementary_prop(X,X).
578
579
580 /* ---------------------- */
581 /* DEFINITION dependency */
582 /* ---------------------- */
583
584 % show definition call graph
585
586 tcltk_print_definitions_as_graph_for_dot(File) :-
587 SAME_RANK = none,
588 gen_dot_graph(File,visualize_graph,dot_def_node,dot_def_trans,SAME_RANK,dot_def_subgraph).
589
590
591 :- use_module(bmachine,[b_get_definition/5]).
592 :- use_module(library(ordsets),[ord_member/2]).
593
594 :- public dot_def_node/6.
595 dot_def_node(DEFID,SubGraph,Desc,box,none,Color) :-
596 findall(Called, (b_get_definition(_,_,_,_,D), member(Called,D)),CD),
597 CD \= [], !,
598 sort(CD,CalledDefs),
599 b_get_definition(DEFID,DefType,Args,_Body,Deps),
600 length(Args,NrArgs),
601 tools:ajoin([DEFID,'/',NrArgs],Desc), % TO DO: improve
602 (get_preference(dot_definitions_use_sub_graph,true) -> SubGraph = DefType ; SubGraph=none),
603 (get_preference(dot_definitions_show_all,true) -> true
604 ; Deps = [_|_] -> true ; ord_member(DEFID,CalledDefs)), % TO DO add preference to show all DEFINITIONS
605 (DefType = predicate -> Color = green ; Color = blue).
606 dot_def_node(0,none,'No DEFINITIONS visible',box,none,red).
607
608 :- public dot_def_trans/5.
609 dot_def_trans(NodeID,Label,SuccNodeID,Color,Style) :- Style=solid,
610 b_get_definition(NodeID,_DefType,_Args,_Body,Deps),
611 Label = 'call',
612 member(SuccNodeID,Deps),
613 (Deps = [_] -> Color = black ; Color = blue).
614
615 :- public dot_def_subgraph/3.
616 dot_def_subgraph(SubGraph,filled,lightgray) :-
617 get_preference(dot_definitions_use_sub_graph,true),
618 member(SubGraph,[predicate,expression,substitution]),
619 (b_get_definition(_,SubGraph,_,_,_) -> true).
620
621
622 /* Prediate dependency */
623
624 % call -dotexpr predicate_dependency Pred File
625 % separates a predicate into conjuncts and shows edges between predicates with common variables
626
627 :- use_module(tools,[string_escape/2]).
628 :- use_module(bsyntaxtree,[predicate_identifiers/2,conjunction_to_list/2]).
629 %
630 tcltk_print_predicate_dependency_as_graph_for_dot(Pred,File) :-
631 my_parse_predicate(Pred,Typed),
632 print_predicate_dependency_as_graph_for_dot(Typed,File).
633
634 :- use_module(bmachine, [type_with_errors/4]).
635 :- use_module(error_manager, [add_error/3]).
636 my_parse_predicate(RawAST,Typed) :- compound(RawAST),!,
637 type_with_errors(RawAST,[variables],Type,Typed),
638 (Type=pred -> true
639 ; add_error(visualize_graph,'Expected predicate by got:',Type),fail).
640 my_parse_predicate(Pred,Typed) :-
641 atom_codes(Pred,Codes),
642 eval_strings:repl_parse_predicate(Codes,exists,Typed,_).
643
644 print_predicate_dependency_as_graph_for_dot(Typed,File) :-
645 my_conjunction_to_list(Typed,Conj),
646 get_pred_ids(Conj,1,Preds),
647 SAME_RANK = none,
648 gen_dot_graph(File,visualize_graph,dot_pred_node(Preds),dot_pred_trans(Preds),SAME_RANK,none).
649
650 my_conjunction_to_list(b(exists(_,Body),pred,_),L) :- !, my_conjunction_to_list(Body,L).
651 my_conjunction_to_list(B,L) :- conjunction_to_list(B,L).
652
653 get_pred_ids([],_,[]).
654 get_pred_ids([Pred|T],N,[pred(N,Pred,Ids)|PT]) :- predicate_identifiers(Pred,Ids),
655 N1 is N+1, get_pred_ids(T,N1,PT).
656
657 :- public dot_pred_node/7.
658 dot_pred_node(Preds,PID,none,EDesc,box,none,blue) :- member(pred(PID,Pred,_),Preds),
659 translate:translate_bexpression_with_limit(Pred,Desc),
660 string_escape(Desc,EDesc).
661
662 :- use_module(library(ordsets),[ord_intersection/3]).
663 :- public dot_pred_trans/6.
664 dot_pred_trans(Preds,NodeID,Label,SuccNodeID,Color,Style) :- Style=solid, Color=black,
665 member(pred(NodeID,_,Ids1),Preds),
666 member(pred(SuccNodeID,_,Ids2),Preds), SuccNodeID>NodeID,
667 ord_intersection(Ids1,Ids2,Label), Label \= [].