| 1 | % (c) 2025-2025 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 | ||
| 7 | % This is a model-checker verifying Probabilistic Computation | |
| 8 | % Tree Logic (PCTL) formulas over Discrete-Time Markov Chains (DTMC) | |
| 9 | % written by Honore Marmion | |
| 10 | ||
| 11 | % Working on SICStus prolog 4.10 | |
| 12 | ||
| 13 | %############################################### | |
| 14 | ||
| 15 | :- module(dtmc_model_checking,[pctl_model_check/4 | |
| 16 | % sat/1, sat/2, | |
| 17 | % search_prob0/4,prob0/4,prob1/4,table_prob0/3,state/1 | |
| 18 | ]). | |
| 19 | :- use_module(library(clpr),[{}/1]). | |
| 20 | ||
| 21 | ||
| 22 | :- use_module(probsrc(error_manager),[add_error/3, add_internal_error/2, add_warning/3]). | |
| 23 | :- use_module(probltlsrc(ltl_tools),[temporal_parser/3]). | |
| 24 | :- use_module(probsrc(state_space),[find_initialised_states/1, current_state_id/1]). | |
| 25 | :- use_module(probsrc(tools),[start_ms_timer/1, stop_ms_timer_with_msg/2]). | |
| 26 | ||
| 27 | pctl_model_check(Formula,_MaxNodes,Mode,Res) :- | |
| 28 | (temporal_parser(Formula,pctl,PCtlFormula) -> true ; add_error(ctl,'PCTL Parser failed: ',Formula),fail), | |
| 29 | %set_max_nr_of_new_impl_trans_nodes(MaxNodes), | |
| 30 | % TODO: provide better feedback, extract probability for P={p} formulas | |
| 31 | (pre_process_formula(PCtlFormula,ProcessedFormula,Bindings,[]) -> true | |
| 32 | ; add_error(dtmc_model_checking,'Could not pre-process: ',PCtlFormula), | |
| 33 | ProcessedFormula = PCtlFormula | |
| 34 | ), | |
| 35 | (Mode= specific_node(ID) -> Start=ID | |
| 36 | ; Mode = starthere -> current_state_id(Start) | |
| 37 | ; Mode = init -> find_initialised_states(SN), member(Start,SN) % TODO try out all start nodes?? | |
| 38 | ; add_error(dtmc_model_checking,'Illegal starting mode (init, starthere supported):',Mode), | |
| 39 | Start = root | |
| 40 | ), | |
| 41 | format('Checking PCTL formula from state ~w : ~w~n AST: ~w~n Open Probability Variables: ~w~n',[Start,Formula,ProcessedFormula,Bindings]), | |
| 42 | reset_tables, | |
| 43 | start_ms_timer(T1), | |
| 44 | (sat(ProcessedFormula,Start) | |
| 45 | -> (Bindings=[] -> Res=true ; Res = solution(Bindings)) | |
| 46 | ; Res = false), | |
| 47 | stop_ms_timer_with_msg(T1,'PTCTL model checking'). | |
| 48 | ||
| 49 | reset_tables :- retractall(table_prob0(_,_,_)),retractall(node(_)), retractall(prob_current(_,_)). | |
| 50 | ||
| 51 | pre_process_formula(true,true) --> []. | |
| 52 | pre_process_formula(false,false) --> []. | |
| 53 | pre_process_formula(ap(P),ap(P)) --> []. | |
| 54 | pre_process_formula(p(P),p(P)) --> []. | |
| 55 | pre_process_formula(probformula(Operator,RefProbAtom,Ctl_formula), | |
| 56 | probformula(Operator,RefProbNr,Ctl_formula)) --> | |
| 57 | ({ground_number(RefProbAtom,RefProbNr)} -> [] | |
| 58 | ; {Operator=equal} -> [RefProbAtom/RefProbNr] | |
| 59 | ; {add_error(dtmc_model_checking,'Illegal reference probability for operator (only equal is supported for symbolic values):',RefProbAtom/Operator)}, | |
| 60 | [RefProbAtom/RefProbNr] | |
| 61 | ). % TODO: pre_process_path_formula | |
| 62 | pre_process_formula(and(F,G),and(PF,PG)) --> | |
| 63 | pre_process_formula(F,PF), | |
| 64 | pre_process_formula(G,PG). | |
| 65 | pre_process_formula(or(F,G),and(PF,PG)) --> | |
| 66 | pre_process_formula(F,PF), | |
| 67 | pre_process_formula(G,PG). | |
| 68 | pre_process_formula(implies(F,G),and(PF,PG)) --> | |
| 69 | pre_process_formula(F,PF), | |
| 70 | pre_process_formula(G,PG). | |
| 71 | pre_process_formula(not(F),not(PF)) --> | |
| 72 | pre_process_formula(F,PF). | |
| 73 | ||
| 74 | %pre_process_path_formula(u(F,G),u(PF,PG)) --> | |
| 75 | % pre_process_formula(F,PF), | |
| 76 | % pre_process_formula(G,PG). | |
| 77 | ||
| 78 | ||
| 79 | % Interface predicates defining the system to be checked | |
| 80 | ||
| 81 | :- use_module(probsrc(xtl_interface),[xtl_transition/4]). | |
| 82 | :- use_module(probltlsrc(ltl_propositions), [trans/4, check_ap/2]). % check_transition_pred/5 | |
| 83 | :- use_module(probsrc(state_space),[visited_expression/2, visited_expression_id/1]). | |
| 84 | ||
| 85 | % TODO: move to specfile and extend to work with B pragmas,... | |
| 86 | transition_probability(From,To,Prob) :- trans(From,To,_,_), | |
| 87 | visited_expression(From,FS), | |
| 88 | visited_expression(To,TS), | |
| 89 | xtl_transition(FS,_,TS,Infos), | |
| 90 | (member(probability/X,Infos) -> Prob=X ; write(no_probability(From,To,Infos)),nl,fail). | |
| 91 | ||
| 92 | state(X) :- visited_expression_id(X). | |
| 93 | ||
| 94 | % example public_examples/XTL/markov/SimpleMarkov.P | |
| 95 | % ?- use_module(extension('markov/dtmc_model_checking.pl')). | |
| 96 | % ?- sat(prob_formula(eq,P,f(p(xtl_predicate_check(finished))))). | |
| 97 | ||
| 98 | %PCTL Model-checking | |
| 99 | ||
| 100 | % This term allow to handle nested formulas in case of dynamic model-checking | |
| 101 | :- dynamic node/1. | |
| 102 | ||
| 103 | %start(root). | |
| 104 | start(ID) :- find_initialised_states(I), member(ID,I). | |
| 105 | ||
| 106 | sat(Formula) :- start(E), sat(Formula,E). | |
| 107 | ||
| 108 | ||
| 109 | % Classic cases | |
| 110 | ||
| 111 | sat_not(false,_E). | |
| 112 | sat_not(true,_E) :- fail. | |
| 113 | sat_not(p(Property),E) :- \+(check_ap(Property,E)). | |
| 114 | sat_not(ap(Property),E) :- \+(check_ap(Property,E)). | |
| 115 | sat_not(and(F,_G),E) :- sat_not(F,E). | |
| 116 | sat_not(and(_F,G),E) :- sat_not(G,E). | |
| 117 | sat_not(or(F,G),E) :- sat_not(F,E),sat_not(G,E). | |
| 118 | sat_not(implies(F,G),E) :- sat(not(or(not(F),G)),E). | |
| 119 | sat_not(equivalence(F,G),E) :- sat_not(and(implies(F,G),implies(G,F)),E). | |
| 120 | sat_not(not(F),E) :- sat(F,E). | |
| 121 | ||
| 122 | %sat(Formula,State) :- write(sat(Formula,State)),nl,fail. | |
| 123 | sat(true,_E). | |
| 124 | sat(false,_E):-fail. | |
| 125 | sat(ap(Property),E) :- check_ap(Property,E). | |
| 126 | sat(p(Property),E) :- check_ap(Property,E). | |
| 127 | sat(and(F,G),E) :- sat(F,E), sat(G,E). | |
| 128 | sat(or(F,_G),E) :- sat(F,E). | |
| 129 | sat(or(_F,G),E) :- sat(G,E). | |
| 130 | sat(implies(F,G),E) :- sat(or(not(F),G),E). | |
| 131 | sat(equivalence(F,G),E) :- sat(and(implies(F,G),implies(G,F)),E). | |
| 132 | sat(not(F),E) :- probformula(_,_,_)\=F, sat_not(F,E). | |
| 133 | ||
| 134 | % Probabilistic-formula cases. Operator is =, < >,<= or >=. P is a number between 0 and 1 (or a Variable), | |
| 135 | % E is a state. | |
| 136 | % Check if the formula is nested | |
| 137 | ||
| 138 | sat(probformula(Operator,P,Ctl_formula),E) :- | |
| 139 | Ctl_formula = gk(_,_) -> | |
| 140 | sat_gk(probformula(Operator,P,Ctl_formula),E) | |
| 141 | ; Ctl_formula = g(_) -> | |
| 142 | sat_g(probformula(Operator,P,Ctl_formula),E) | |
| 143 | ; (node(Node) -> | |
| 144 | New_Node is Node +1, | |
| 145 | retract(node(Node)), | |
| 146 | assert(node(New_Node)), | |
| 147 | sat_node(probformula(Operator,P,Ctl_formula),E,New_Node) | |
| 148 | ; assert(node(0)), | |
| 149 | sat_node(probformula(Operator,P,Ctl_formula),E,0), | |
| 150 | retractall(node(_)) /*reinitialize nodes*/ | |
| 151 | ). | |
| 152 | ||
| 153 | sat(not(probformula(Operator,P,Ctl_formula)),E) :- | |
| 154 | negate_operator(Operator,NotOp), | |
| 155 | sat(probformula(NotOp,P,Ctl_formula),E). | |
| 156 | ||
| 157 | % Always bounded formula, we use the dual probabilistic event of fk(K,not(F)) | |
| 158 | sat(probformula(Operator,P,gk(K,F)),E) :- | |
| 159 | ground(P) -> | |
| 160 | Q is 1-P, | |
| 161 | (Operator = equal -> | |
| 162 | sat(probformula(Operator,Q,fk(K,not(F))),E) | |
| 163 | ; sat(not(probformula(Operator,Q,fk(K,not(F)))),E)) | |
| 164 | ; ((Operator = equal -> | |
| 165 | sat(probformula(Operator,Q,fk(K,not(F))),E) | |
| 166 | ; sat(not(probformula(Operator,Q,fk(K,not(F)))),E)), | |
| 167 | P is 1-Q) | |
| 168 | . | |
| 169 | ||
| 170 | % Always bounded formula, we use the dual probabilistic event of fk(K,not(F)) | |
| 171 | sat_gk(probformula(Operator,P,gk(K,F)),E) :- | |
| 172 | ground(P) -> | |
| 173 | Q is 1-P, | |
| 174 | (Operator = equal -> | |
| 175 | sat(probformula(Operator,Q,fk(K,not(F))),E) | |
| 176 | ; Operator = greater -> | |
| 177 | sat(probformula(less,Q,fk(K,not(F))),E) | |
| 178 | ; Operator = less -> | |
| 179 | sat(probformula(greater,Q,fk(K,not(F))),E) | |
| 180 | ; Operator = strictlygreater -> | |
| 181 | sat(probformula(strictlyless,Q,fk(K,not(F))),E) | |
| 182 | ; Operator = strictlyless -> | |
| 183 | sat(probformula(strictlygreater,Q,fk(K,not(F))),E)) | |
| 184 | ; ((Operator = equal -> | |
| 185 | sat(probformula(Operator,Q,fk(K,not(F))),E) | |
| 186 | ; Operator = greater -> | |
| 187 | sat(probformula(less,Q,fk(K,not(F))),E) | |
| 188 | ; Operator = less -> | |
| 189 | sat(probformula(greater,Q,fk(K,not(F))),E) | |
| 190 | ; Operator = strictlygreater -> | |
| 191 | sat(probformula(strictlyless,Q,fk(K,not(F))),E) | |
| 192 | ; Operator = strictlyless -> | |
| 193 | sat(probformula(strictlygreater,Q,fk(K,not(F))),E)), | |
| 194 | P is 1-Q) | |
| 195 | . | |
| 196 | ||
| 197 | % Always formula | |
| 198 | sat_g(probformula(Operator,P,g(F)),E) :- | |
| 199 | ground(P) -> | |
| 200 | Q is 1-P, | |
| 201 | (Operator = equal -> | |
| 202 | sat(probformula(Operator,Q,f(not(F))),E) | |
| 203 | ; Operator = greater -> | |
| 204 | sat(probformula(less,Q,f(not(F))),E) | |
| 205 | ; Operator = less -> | |
| 206 | sat(probformula(greater,Q,f(not(F))),E) | |
| 207 | ; Operator = strictlygreater -> | |
| 208 | sat(probformula(strictlyless,Q,f(not(F))),E) | |
| 209 | ; Operator = strictlyless -> | |
| 210 | sat(probformula(strictlygreater,Q,f(not(F))),E)) | |
| 211 | ; ((Operator = equal -> | |
| 212 | sat(probformula(Operator,Q,f(not(F))),E) | |
| 213 | ; Operator = greater -> | |
| 214 | sat(probformula(less,Q,f(not(F))),E) | |
| 215 | ; Operator = less -> | |
| 216 | sat(probformula(greater,Q,f(not(F))),E) | |
| 217 | ; Operator = strictlygreater -> | |
| 218 | sat(probformula(strictlyless,Q,f(not(F))),E) | |
| 219 | ; Operator = strictlyless -> | |
| 220 | sat(probformula(strictlygreater,Q,f(not(F))),E)), | |
| 221 | P is 1-Q) | |
| 222 | . | |
| 223 | ||
| 224 | % Check the type of the formula | |
| 225 | sat_node(probformula(Operator,P,Ctl_formula),E,Node) :- | |
| 226 | Ctl_formula = u(F,G) -> | |
| 227 | prob_calc(u(F,G),E,P_phi,Node), | |
| 228 | against(P_phi,P,Operator) | |
| 229 | ; Ctl_formula = f(G) -> | |
| 230 | prob_calc(u(true,G),E,P_phi,Node), | |
| 231 | against(P_phi,P,Operator) | |
| 232 | ; Ctl_formula = fk(K,G) -> | |
| 233 | sat_dynamic(probformula(Operator,P,uk(true,K,G)),E,Node) | |
| 234 | ; sat_dynamic(probformula(Operator,P,Ctl_formula),E,Node). | |
| 235 | ||
| 236 | % Use a different technic depending on the operator | |
| 237 | % This allow notably the calculation of a probability for the equal operator | |
| 238 | sat_dynamic(probformula(Operator,P,Ctl_formula),E,Node) :- | |
| 239 | ((Operator = greater ; Operator= strictlygreater) -> | |
| 240 | ground(P), | |
| 241 | prob_calc(Ctl_formula,E,P,Operator,Node) | |
| 242 | ||
| 243 | ; Operator = equal -> | |
| 244 | retractall(prob_current(Node,_)), | |
| 245 | (ground(P) -> | |
| 246 | prob_calc(Ctl_formula,E,P,equal,Node) | |
| 247 | ||
| 248 | ; (prob_calc(Ctl_formula,E,1.0,equal,Node) -> | |
| 249 | P=1.0 | |
| 250 | ; prob_current(Node,P))) | |
| 251 | ||
| 252 | ; Operator = less -> | |
| 253 | ground(P), | |
| 254 | \+(prob_calc(Ctl_formula,E,P,strictlygreater,Node)) | |
| 255 | ||
| 256 | ; Operator = strictlyless -> | |
| 257 | ground(P), | |
| 258 | \+(prob_calc(Ctl_formula,E,P,greater,Node)) | |
| 259 | ). | |
| 260 | ||
| 261 | % Compare different formulas using a specific operator | |
| 262 | ||
| 263 | % For the equal comparison, we compare the results using epsilon precision in case | |
| 264 | % of a given probability | |
| 265 | against(P_phi,ReferenceP,equal) :- !, | |
| 266 | (ground_number(ReferenceP,P) -> | |
| 267 | P_phi =< P + 0.00000000000000023, | |
| 268 | P =< P_phi + 0.00000000000000023 | |
| 269 | ; ReferenceP = P_phi % ReferenceP is an open variable | |
| 270 | ). | |
| 271 | against(P_phi,ReferenceP,less) :- | |
| 272 | ground_number(ReferenceP,P), !, | |
| 273 | P_phi =< P + 0.00000000000000023. % less | |
| 274 | against(P_phi,ReferenceP,greater) :- | |
| 275 | ground_number(ReferenceP,P), !, | |
| 276 | P_phi >= P - 0.00000000000000023. % greater | |
| 277 | against(P_phi,ReferenceP,strictlyless) :- | |
| 278 | ground_number(ReferenceP,P), !, | |
| 279 | P_phi + 0.00000000000000023 < P . % strictly less | |
| 280 | against(P_phi,ReferenceP,strictlygreater) :- | |
| 281 | ground_number(ReferenceP,P), !, | |
| 282 | P_phi - 0.00000000000000023 > P . % strictlygreater | |
| 283 | against(P_phi,ReferenceP,not(equal)) :- !, | |
| 284 | (ground_number(ReferenceP,P) -> | |
| 285 | (P_phi > P + 0.00000000000000023 ; | |
| 286 | P =< P_phi + 0.00000000000000023 | |
| 287 | ) | |
| 288 | ; % ReferenceP is an open variable | |
| 289 | add_warning(dtmc_model_checking,'Using symbolic variable for inequality: ',P_phi), | |
| 290 | (P_phi < 1-0.00000000000000023 | |
| 291 | -> ReferenceP = P_phi + 0.00000000000000023 | |
| 292 | ; ReferenceP = P_phi - 0.00000000000000023 | |
| 293 | ) | |
| 294 | ). | |
| 295 | against(P_phi,P,not(less)) :- !, against(P_phi,P,strictlygreater). | |
| 296 | against(P_phi,P,not(greater)) :- !, against(P_phi,P,strictlyless). | |
| 297 | against(P_phi,P,not(strictlyless)) :- !, against(P_phi,P,greater). | |
| 298 | against(P_phi,P,not(strictlygreater)) :- !, against(P_phi,P,less). | |
| 299 | against(P1,P2,Op) :- add_internal_error('Illegal comparison operator: ',against(P1,P2,Op)),fail. | |
| 300 | ||
| 301 | negate_operator(not(Op),R) :- !, R=Op. | |
| 302 | negate_operator(Op,not(Op)). | |
| 303 | ||
| 304 | :- use_module(probsrc(tools),[safe_number_codes/2]). | |
| 305 | % TODO: in future fully pre-process AST of formula once before launching model checker | |
| 306 | ground_number(P,Res) :- number(P),!,Res=P. | |
| 307 | ground_number(P,Res) :- atom(P), atom_codes(P,Codes), % convert atom from parser into number | |
| 308 | safe_number_codes(Nr,Codes),!,Res=Nr. | |
| 309 | ||
| 310 | ||
| 311 | % Next formula | |
| 312 | :- dynamic prob_current/2. | |
| 313 | ||
| 314 | prob_calc(x(F),E,P_phi,Operator,Node) :- | |
| 315 | retractall(prob_current(Node,_)), | |
| 316 | assert(prob_current(Node,0.0)), | |
| 317 | (prob_calc_sub(x(F),E,P_phi,Operator,Node) -> | |
| 318 | true | |
| 319 | ; against(0.0,P_phi,Operator)),!. | |
| 320 | ||
| 321 | % Until Bounded formula | |
| 322 | prob_calc(uk(F,K,G),E,P_phi,Operator,Node) :- | |
| 323 | retractall(prob_current(Node,_)), | |
| 324 | assert(prob_current(Node,0.0)), | |
| 325 | (sat(G,E) -> | |
| 326 | retractall(prob_current(Node,_)), | |
| 327 | assert(prob_current(Node,1.0)), | |
| 328 | against(1.0,P_phi,Operator) | |
| 329 | ; sat(F,E) -> | |
| 330 | (prob_calc_sub(uk(F,K,G),E,P_phi,1.0,Operator,Node) -> | |
| 331 | true | |
| 332 | ; against(0.0,P_phi,Operator)) | |
| 333 | ; against(0.0,P_phi,Operator)),!. | |
| 334 | ||
| 335 | % Until formula | |
| 336 | % For this formula we have to calculate the probability for | |
| 337 | % all states | |
| 338 | prob_calc(u(F,G),E,P_phi,Node) :- | |
| 339 | retractall(table_prob0(_,_,Node)), | |
| 340 | retractall(table_prob1(_,_,Node)), | |
| 341 | prob_calc_u1(F,G,List_S,P_vect,Node), | |
| 342 | state(E), | |
| 343 | (find_prob_u(List_S,P_vect,E,P) -> P_phi=P | |
| 344 | ; P_phi=0.0 | |
| 345 | ). | |
| 346 | ||
| 347 | ||
| 348 | %******************************************************* | |
| 349 | ||
| 350 | % recursion for the next formula | |
| 351 | prob_calc_sub(x(F),E,P_phi,Operator,Node) :- | |
| 352 | transition_probability(E,S,P), | |
| 353 | sat(F,S), | |
| 354 | prob_current(Node,Previous_P), | |
| 355 | Current_prob is Previous_P +P, | |
| 356 | retract(prob_current(Node,Previous_P)), | |
| 357 | assert(prob_current(Node,Current_prob)), | |
| 358 | against(Current_prob,P_phi,Operator). | |
| 359 | ||
| 360 | % recursion for the bounded until formula | |
| 361 | prob_calc_sub(uk(F,K_new,G),E,P_phi,P_trace,Operator,Node) :- | |
| 362 | (sat(G,E) -> | |
| 363 | prob_current(Node,P), | |
| 364 | P_new is P+P_trace, | |
| 365 | retract(prob_current(Node,P)), | |
| 366 | assert(prob_current(Node,P_new)), | |
| 367 | against(P_new,P_phi,Operator) | |
| 368 | ; K_new > 0, | |
| 369 | transition_probability(E,S,P_trans), | |
| 370 | sat(F,S), | |
| 371 | K is K_new -1, | |
| 372 | P_trace_new is P_trace*P_trans, | |
| 373 | prob_calc_sub(uk(F,K,G),S,P_phi,P_trace_new,Operator,Node) | |
| 374 | ). | |
| 375 | ||
| 376 | % 1rst precomputation for the until formula | |
| 377 | ||
| 378 | :- dynamic table_prob0/3. | |
| 379 | ||
| 380 | prob0(_F,_G,E,Node) :- | |
| 381 | table_prob0(E,true,Node),!. | |
| 382 | ||
| 383 | prob0(_F,G,E,Node) :- | |
| 384 | sat(G,E), | |
| 385 | !, | |
| 386 | asserta(table_prob0(E,true,Node)). | |
| 387 | ||
| 388 | prob0(F,G,E1,Node) :- | |
| 389 | sat(F,E1), | |
| 390 | assertz(table_prob0(E1,computing,Node)), | |
| 391 | trans(E1,E2,_P,_TransId), | |
| 392 | \+ table_prob0(E2,computing,Node), | |
| 393 | (prob0(F,G,E2,Node) -> | |
| 394 | asserta(table_prob0(E1,true,Node)), | |
| 395 | retract(table_prob0(E1,computing,Node)) | |
| 396 | ),!. | |
| 397 | ||
| 398 | search_prob0(F,G,E,Node):- | |
| 399 | retractall(table_prob0(_,computing,Node)), | |
| 400 | prob0(F,G,E,Node). | |
| 401 | ||
| 402 | % 2nd precomputation for the until formula | |
| 403 | :- dynamic table_prob1/3. | |
| 404 | ||
| 405 | prob1(_F,_G,E,Node) :- | |
| 406 | table_prob1(E,true,Node),!. | |
| 407 | ||
| 408 | prob1(_F,_G,E,Node) :- | |
| 409 | \+(table_prob0(E,true,Node)), | |
| 410 | !, | |
| 411 | asserta(table_prob1(E,true,Node)). | |
| 412 | ||
| 413 | prob1(F,G,E1,Node) :- | |
| 414 | sat(F,E1), | |
| 415 | \+(sat(G,E1)), | |
| 416 | assert(table_prob1(E1,computing,Node)), | |
| 417 | trans(E1,E2,_P,_), | |
| 418 | \+ table_prob1(E2,computing,Node), | |
| 419 | (prob1(F,G,E2,Node) -> | |
| 420 | asserta(table_prob1(E1,true,Node)), | |
| 421 | retract(table_prob1(E1,computing,Node)) | |
| 422 | ),!. | |
| 423 | ||
| 424 | search_prob1(F,G,E,Node):- | |
| 425 | retractall(table_prob1(_,computing,Node)), | |
| 426 | prob1(F,G,E,Node). | |
| 427 | ||
| 428 | % P_vect is the vector of non-null probabilities | |
| 429 | % for the until formula | |
| 430 | prob_calc_u1(F,G,List_S,P_vect,Node) :- | |
| 431 | findall(S,(state(S),search_prob0(F,G,S,Node)),List_S), | |
| 432 | findall(E,(state(E),search_prob1(F,G,E,Node)),_List), | |
| 433 | prob_calc_u2(F,G,List_S,List_S,P_vect,P_vect,Node). | |
| 434 | ||
| 435 | prob_calc_u2(_F,_G,[],_List_S,[],_P_vect,_Node). | |
| 436 | prob_calc_u2(F,G,[S|List_S_explored],List_S,[P_phi|P_vect_explored],P_vect,Node) :- | |
| 437 | (table_prob1(S,true,Node) -> prob_calc_u3(S,List_S,P_phi,P_vect) | |
| 438 | ; P_phi=1.0 | |
| 439 | ), | |
| 440 | prob_calc_u2(F,G,List_S_explored,List_S,P_vect_explored,P_vect,Node). | |
| 441 | ||
| 442 | prob_calc_u3(_S,[],0.0,[]). | |
| 443 | prob_calc_u3(S,[E|List_S],P_phi_new,[P|P_vect]) :- | |
| 444 | prob_calc_u3(S,List_S,P_phi,P_vect), | |
| 445 | (transition_probability(S,E,P_trans) -> {P_phi_new = P*P_trans + P_phi} | |
| 446 | ; P_phi_new=P_phi | |
| 447 | ). | |
| 448 | ||
| 449 | find_prob_u([E],[P],E,P). | |
| 450 | find_prob_u([S1,S2|List_S],[Prob1,Prob2|P_vect],E,P) :- | |
| 451 | (E=S1,P=Prob1) | |
| 452 | ; find_prob_u([S2|List_S],[Prob2|P_vect],E,P). |