| 1 | % (c) 2014-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 | :- module(ltl_safety,[is_safety_property/2,ltl_mc_safety_property/3, | |
| 6 | is_ltl2ba_tool_installed/0, | |
| 7 | aut_transition/3, aut_finite_state/1, aut_initial_state/1, | |
| 8 | tps_occurring/0]). | |
| 9 | ||
| 10 | /* SICSTUS Libraries */ | |
| 11 | :- use_module(library(lists)). | |
| 12 | :- use_module(library(codesio)). | |
| 13 | :- use_module(library(terms)). | |
| 14 | :- use_module(library(file_systems)). | |
| 15 | ||
| 16 | /* ProB Libraries */ | |
| 17 | :- use_module(probsrc(tools),[ajoin/2,host_platform/1]). | |
| 18 | :- use_module(probsrc(error_manager)). | |
| 19 | %% :- use_module(probsrc(debug)). | |
| 20 | :- use_module(probsrc(self_check)). | |
| 21 | :- use_module(probsrc(preferences),[preference/2,set_preference/2,get_preference/2]). | |
| 22 | %:- use_module(probsrc(system_call),[system_call/5]). | |
| 23 | :- use_module(probsrc(debug),[debug_println/2,debug_mode/1]). | |
| 24 | :- use_module(probsrc(bsyntaxtree),[create_negation/2]). | |
| 25 | ||
| 26 | :- use_module(extension('ltl2ba/ltl2ba')). | |
| 27 | ||
| 28 | /* ProB LTL Model Checker Modules */ | |
| 29 | :- use_module(probltlsrc(safety_mc),[start_mc_safety_property/3]). | |
| 30 | :- use_module(probltlsrc(ltl_translate),[pp_ap/2,pp_tp/2]). | |
| 31 | ||
| 32 | :- use_module(probsrc(module_information),[module_info/2]). | |
| 33 | :- module_info(group,ltl). | |
| 34 | :- module_info(description,'This module provides predicates for checking whether an LTL formula is a safety property.'). | |
| 35 | ||
| 36 | :- dynamic ap_representation/2, tp_representation/2, tps_occurring/0. | |
| 37 | ||
| 38 | :- dynamic aut_transition/3, aut_finite_state/1, aut_initial_state/1. | |
| 39 | ||
| 40 | clear_automaton_facts :- | |
| 41 | retractall(aut_transition(_,_,_)), | |
| 42 | retractall(aut_initial_state(_)), | |
| 43 | retractall(aut_finite_state(_)). | |
| 44 | ||
| 45 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 46 | %%%%%%%%%%% Checking whether an LTL property represents a safety property %%%%%%%%%% | |
| 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 48 | % The predicates check whether the parsed LTL property represents a safety property | |
| 49 | % by checking the syntactical structure of the formula. | |
| 50 | % The idea is borrowed from the following theorem from the paper | |
| 51 | % "Safety, Liveness and Fairness in Temporal Logic" of A. Sistla: | |
| 52 | %% THEOREM: Every propositional formula is a safety formula and if f,g are safety formulae, | |
| 53 | %% then so are f & g, f or g, X f, f W g, and G f, where 'W' is the weak-until operator. | |
| 54 | % | |
| 55 | % Note that the checked formula should be a positive formula. An LTL formula is said to | |
| 56 | % be a positive if none of the temporal operators appears in the scope of 'not'. | |
| 57 | ||
| 58 | % Testing various properties for being safety or liveness. Some of | |
| 59 | % the unit tests here represent examples from the paper mentioned above. | |
| 60 | % Note that the first argument of is_safety_property/2 should be negated, as | |
| 61 | % this is done after negating the original property that should be model checked (see select_ltl_mode/4 in ltl.pl) | |
| 62 | :- assert_must_succeed((F = ap(p), | |
| 63 | is_safety_property_test(not(F),_NF))). | |
| 64 | :- assert_must_succeed((F = globally(deadlock), | |
| 65 | is_safety_property_test(not(F),_NF))). | |
| 66 | :- assert_must_succeed((F = weakuntil(not(ap(alloc)),ap(request)), | |
| 67 | is_safety_property_test(not(F),_NF))). | |
| 68 | :- assert_must_succeed((F = and(weakuntil(not(ap(alloc)),ap(request)), | |
| 69 | globally(implies(ap(alloc),next(weakuntil(not(ap(alloc)),ap(request)))))), | |
| 70 | is_safety_property_test(not(F),_NF))). | |
| 71 | :- assert_must_succeed((F = globally(implies(not(ap(request)),or(ap(alloc),or(next(ap(alloc)),next(next(ap(alloc))))))), | |
| 72 | is_safety_property_test(not(F),_NF))). | |
| 73 | :- assert_must_succeed((F = globally(or(not(ap(p)),globally(not(ap(p))))), | |
| 74 | is_safety_property_test(not(F),_NF))). | |
| 75 | :- assert_must_succeed((F = not(until(ap(p1),until(ap(p2),ap(p3)))), | |
| 76 | is_safety_property_test(not(F),_NF))). | |
| 77 | :- assert_must_succeed((F = not(until(ap(p1),until(ap(p2),until(ap(p3),ap(p4))))), | |
| 78 | is_safety_property_test(not(F),_NF))). | |
| 79 | :- assert_must_succeed((F = not(until(ap(p1),until(ap(p2),until(ap(p3),until(ap(p4),until(ap(p5),until(ap(p6),ap(p7)))))))), | |
| 80 | is_safety_property_test(not(F),_NF))). | |
| 81 | :- assert_must_succeed((F = not(not(globally(deadlock))), | |
| 82 | is_safety_property_test(not(F),_NF))). | |
| 83 | :- assert_must_succeed((F = globally(or(ap(p),and(next(ap(q)),not(next(ap(q)))))), | |
| 84 | is_safety_property_test(not(F),_NF))). | |
| 85 | :- assert_must_succeed((F = and(globally(or(ap(p),next(globally(ap(q))))),globally(or(ap(p),next(globally(not(ap(q))))))), | |
| 86 | is_safety_property_test(not(F),_NF))). | |
| 87 | :- assert_must_fail((F = globally(implies(ap(request),finally(ap(alloc)))), | |
| 88 | is_safety_property_test(not(F),_NF))). | |
| 89 | :- assert_must_fail((F = globally(finally(ap(alloc))), | |
| 90 | is_safety_property_test(not(F),_NF))). | |
| 91 | :- assert_must_fail((F = globally(until(ap(request),finally(ap(alloc)))), | |
| 92 | is_safety_property_test(not(F),_NF))). | |
| 93 | :- assert_must_fail((F = implies(globally(finally(ap(send))),globally(finally(receive))), | |
| 94 | is_safety_property_test(not(F),_NF))). | |
| 95 | :- assert_must_fail((F = not(until(ap(p1),not(until(ap(p2),until(ap(p3),ap(p4)))))), | |
| 96 | is_safety_property_test(not(F),_NF))). | |
| 97 | ||
| 98 | is_safety_property_test(F,NF) :- | |
| 99 | get_preference(use_safety_ltl_model_checker,Val), | |
| 100 | set_preference(use_safety_ltl_model_checker,true), | |
| 101 | is_safety_property(F,NF), | |
| 102 | set_preference(use_safety_ltl_model_checker,Val). | |
| 103 | ||
| 104 | is_safety_property(not(F),NF) :- | |
| 105 | preference(use_safety_ltl_model_checker,true), | |
| 106 | normalize_to_release_pnf(F,NF), | |
| 107 | is_syntactically_safe(NF). | |
| 108 | ||
| 109 | is_syntactically_safe(deadlock) :- !. | |
| 110 | is_syntactically_safe(false) :- !. | |
| 111 | is_syntactically_safe(true) :- !. | |
| 112 | is_syntactically_safe(ap(_)) :- !. | |
| 113 | is_syntactically_safe(action(_)) :- !. | |
| 114 | is_syntactically_safe(and(F,G)) :- !, | |
| 115 | is_syntactically_safe(F), | |
| 116 | is_syntactically_safe(G). | |
| 117 | is_syntactically_safe(or(F,G)) :- !, | |
| 118 | is_syntactically_safe(F), | |
| 119 | is_syntactically_safe(G). | |
| 120 | is_syntactically_safe(next(F)) :- !, | |
| 121 | is_syntactically_safe(F). | |
| 122 | is_syntactically_safe(weakuntil(F,G)) :- !, | |
| 123 | is_syntactically_safe(F), | |
| 124 | is_syntactically_safe(G). | |
| 125 | is_syntactically_safe(release(F,G)) :- !, | |
| 126 | is_syntactically_safe(F), | |
| 127 | is_syntactically_safe(G). | |
| 128 | is_syntactically_safe(not(F)) :- !, | |
| 129 | is_atomic_proposition(F). | |
| 130 | ||
| 131 | is_atomic_proposition(F) :- | |
| 132 | F =.. [Functor|_Args], | |
| 133 | memberchk(Functor,[true,false,ap,action]). | |
| 134 | ||
| 135 | % Release PNF (the Release PNF does not imply exponential blow-up of the origin LTL formula) | |
| 136 | % f = true | false | a | not a | f1 & f2 | f1 or f2 | X f | f1 U f2 | f1 R f2 | |
| 137 | normalize_to_release_pnf(deadlock,deadlock) :- !. | |
| 138 | normalize_to_release_pnf(false,false) :- !. | |
| 139 | normalize_to_release_pnf(true,true) :- !. | |
| 140 | normalize_to_release_pnf(ap(P),ap(P)) :- !. | |
| 141 | normalize_to_release_pnf(action(P),action(P)) :- !. | |
| 142 | normalize_to_release_pnf(and(F,G),and(NF,NG)) :- !, | |
| 143 | normalize_to_release_pnf(F,NF), | |
| 144 | normalize_to_release_pnf(G,NG). | |
| 145 | normalize_to_release_pnf(or(F,G),or(NF,NG)) :- !, | |
| 146 | normalize_to_release_pnf(F,NF), | |
| 147 | normalize_to_release_pnf(G,NG). | |
| 148 | normalize_to_release_pnf(implies(F,G),NImplies) :- !, | |
| 149 | normalize_to_release_pnf(or(not(F),G),NImplies). | |
| 150 | normalize_to_release_pnf(next(F),next(NF)) :- !, | |
| 151 | normalize_to_release_pnf(F,NF). | |
| 152 | normalize_to_release_pnf(globally(F),release(false,NF)) :- !, | |
| 153 | normalize_to_release_pnf(F,NF). | |
| 154 | normalize_to_release_pnf(finally(F),until(true,NF)) :- !, | |
| 155 | normalize_to_release_pnf(F,NF). | |
| 156 | normalize_to_release_pnf(weakuntil(F,G),weakuntil(NF,NG)) :- !, | |
| 157 | normalize_to_release_pnf(F,NF), | |
| 158 | normalize_to_release_pnf(G,NG). | |
| 159 | normalize_to_release_pnf(release(F,G),release(NF,NG)) :- !, | |
| 160 | normalize_to_release_pnf(F,NF), | |
| 161 | normalize_to_release_pnf(G,NG). | |
| 162 | normalize_to_release_pnf(until(F,G),until(NF,NG)) :- !, | |
| 163 | normalize_to_release_pnf(F,NF), | |
| 164 | normalize_to_release_pnf(G,NG). | |
| 165 | % not rules | |
| 166 | normalize_to_release_pnf(not(true),false) :- !. | |
| 167 | normalize_to_release_pnf(not(false),true) :- !. | |
| 168 | normalize_to_release_pnf(not(and(F,G)),NOr) :- !, | |
| 169 | normalize_to_release_pnf(or(not(F),not(G)),NOr). | |
| 170 | normalize_to_release_pnf(not(or(F,G)),NAnd) :- !, | |
| 171 | normalize_to_release_pnf(and(not(F),not(G)),NAnd). | |
| 172 | normalize_to_release_pnf(not(next(F)),NNext) :- !, | |
| 173 | normalize_to_release_pnf(next(not(F)),NNext). | |
| 174 | normalize_to_release_pnf(not(finally(F)),NGlobally) :- !, | |
| 175 | normalize_to_release_pnf(release(false,not(F)),NGlobally). | |
| 176 | normalize_to_release_pnf(not(globally(F)),NUntil) :- !, | |
| 177 | normalize_to_release_pnf(until(true,not(F)),NUntil). | |
| 178 | normalize_to_release_pnf(not(until(F,G)),NRelease) :- !, | |
| 179 | normalize_to_release_pnf(release(not(F),not(G)),NRelease). | |
| 180 | normalize_to_release_pnf(not(F),NF) :- !, | |
| 181 | (F = not(F1) -> | |
| 182 | normalize_to_release_pnf(F1,NF) | |
| 183 | ; normalize_to_release_pnf(F,NF1), | |
| 184 | NF=not(NF1)). | |
| 185 | ||
| 186 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 187 | %%%%%%%%%%%%%%%%% Predicates for using the LTL2BA Tool %%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 188 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 189 | ||
| 190 | ltl_mc_safety_property(Ltl,StartNodes,Result) :- | |
| 191 | translate_to_ltl2ba_syntax(Ltl,Ltl1), | |
| 192 | ltl2ba_init, | |
| 193 | clear_automaton_facts, | |
| 194 | (debug_mode(on) -> Verbose = true; Verbose = false), | |
| 195 | c_call_ltl2ba(Ltl1,ltl_safety:assert_aut_initial_state,ltl_safety:assert_aut_finite_state,ltl_safety:assert_aut_transition,Verbose,ExitResult), | |
| 196 | debug_print_ba_automaton, | |
| 197 | (ExitResult = ok -> | |
| 198 | load_and_check_safety_property(StartNodes,Result) | |
| 199 | ; ExitResult = error -> | |
| 200 | add_error_fail(translating_ltl2ba,'An error appeared while translating LTL to BA for the following formula: ',Ltl1) | |
| 201 | ; otherwise -> | |
| 202 | add_error_fail(translating_ltl2ba,'Unexpected error occurred while translating LTL to BA for the following formula: ',Ltl1) | |
| 203 | ). | |
| 204 | ltl_mc_safety_property(_Ltl,_StarNodes,_Result) :- | |
| 205 | add_error_fail(translating_ltl2ba,'Please ensure that ltl2ba is installed (see Help menu for ProB Tcl/Tk)',''). | |
| 206 | ||
| 207 | load_and_check_safety_property(StartNodes,Result) :- | |
| 208 | %% start_mc_safety_property(random,StartNodes,Result). | |
| 209 | start_mc_safety_property(breadth_first,StartNodes,Result). | |
| 210 | ||
| 211 | is_ltl2ba_tool_installed :- is_ltl2ba_tool_installed(message). | |
| 212 | is_ltl2ba_tool_installed(GenerateMsg) :- | |
| 213 | host_platform(Platform), | |
| 214 | get_platform_specifix_ltl2ba_library(Platform,File), | |
| 215 | absolute_file_name(prob_lib(File),LTL2BALibrary), | |
| 216 | (file_exists(LTL2BALibrary) -> | |
| 217 | debug_println(9,'LTL2BA is installed.') | |
| 218 | ; GenerateMsg==message -> | |
| 219 | add_message(translating_ltl2ba, | |
| 220 | 'ltl2ba-library archive could not be found in lib/ directory, install ltl2ba for faster model checking'), | |
| 221 | fail | |
| 222 | ). | |
| 223 | ||
| 224 | get_platform_specifix_ltl2ba_library(darwin,'ltl2ba.bundle'):- !. | |
| 225 | get_platform_specifix_ltl2ba_library(linux,'ltl2ba.so') :- !. | |
| 226 | get_platform_specifix_ltl2ba_library(windows,'ltl2ba.dll') :- !. | |
| 227 | get_platform_specifix_ltl2ba_library(Unknown,_) :- | |
| 228 | add_error_fail(translating_ltl2ba,'Unknown platform: ', Unknown). | |
| 229 | ||
| 230 | :- public assert_aut_initial_state/1. % callback given to C | |
| 231 | assert_aut_initial_state(StateDescription) :- | |
| 232 | debug_println(9,asserting_initialstate(StateDescription)), | |
| 233 | assert(aut_initial_state(StateDescription)). | |
| 234 | :- public assert_aut_finite_state/1. % callback given to C | |
| 235 | assert_aut_finite_state(StateDescription) :- | |
| 236 | debug_println(9,asserting_finitestate(StateDescription)), | |
| 237 | assert(aut_finite_state(StateDescription)). | |
| 238 | :- public assert_aut_transition/3. % callback given to C | |
| 239 | assert_aut_transition(Src,Atom,Dst) :- | |
| 240 | atom_codes(Atom,Codes), | |
| 241 | read_term_from_codes_exception(Codes,PrepRep,[]), | |
| 242 | redefine_transition_label(PrepRep,Label), | |
| 243 | debug_println(9,asserting_transition(aut_transition(Src,Label,Dst))), | |
| 244 | assert(aut_transition(Src,Label,Dst)). | |
| 245 | ||
| 246 | read_term_from_codes_exception(Codes,PrepRep,Options) :- | |
| 247 | (read_term_from_codes(Codes,PrepRep,Options) | |
| 248 | -> true | |
| 249 | ; atom_codes(Atom,Codes), | |
| 250 | add_error(translating_ltl3ba_callback, 'Unexpected atom representation (does atom ends with fullstop?): ', Atom) | |
| 251 | ). | |
| 252 | ||
| 253 | %redefine_automaton_facts :- | |
| 254 | % aut_transition(Src,P,Dst), | |
| 255 | % redefine_transition(Src,P,Dst), | |
| 256 | % fail. | |
| 257 | %redefine_automaton_facts. | |
| 258 | %redefine_transition(Src,Predicate,Dst) :- | |
| 259 | % retract(aut_transition(Src,Predicate,Dst)), | |
| 260 | % redefine_transition_label(Predicate,Preposition), | |
| 261 | % assert(aut_transition(Src,Preposition,Dst)). | |
| 262 | ||
| 263 | redefine_transition_label(true,Res) :- !, | |
| 264 | Res = true. | |
| 265 | redefine_transition_label(false,Res) :- !, | |
| 266 | Res = false. | |
| 267 | redefine_transition_label(not(AP),Res) :- | |
| 268 | ap_representation(AP,bpred(Pred)),!, | |
| 269 | create_negation(Pred,NegPred), | |
| 270 | create_atomic_b_predicate(NegPred,Res). | |
| 271 | redefine_transition_label(AP,Res) :- | |
| 272 | ap_representation(AP,Rep),!, | |
| 273 | Res = ap(Rep). | |
| 274 | redefine_transition_label(TP,Res) :- | |
| 275 | tp_representation(TP,Rep),!, | |
| 276 | Res = tp(Rep). | |
| 277 | redefine_transition_label(F,Res) :- | |
| 278 | F =.. [Functor|Args], | |
| 279 | maplist(redefine_transition_label,Args,NewArgs), | |
| 280 | Res =.. [Functor|NewArgs]. | |
| 281 | ||
| 282 | create_atomic_b_predicate(BPred,Res) :- | |
| 283 | Res = ap(bpred(BPred)). | |
| 284 | ||
| 285 | debug_print_ba_automaton :- | |
| 286 | (debug_mode(on) | |
| 287 | -> print_transitions_fail_loop | |
| 288 | ; true). | |
| 289 | ||
| 290 | print_transitions_fail_loop :- | |
| 291 | aut_transition(Src,Label,Dst), | |
| 292 | print('Transition: '),print(Src), | |
| 293 | translate_and_print_label(Label), | |
| 294 | print(Dst),nl,fail. | |
| 295 | print_transitions_fail_loop. | |
| 296 | ||
| 297 | translate_and_print_label(Label) :- | |
| 298 | pp_ba_label(Label,Atom,[]), | |
| 299 | ajoin(Atom,Text), | |
| 300 | print_label(Text). | |
| 301 | ||
| 302 | %% pretty-printing predicate in Spin syntax (created just to test if ltl2ba produces the correct automaton) | |
| 303 | pp_ba_label(true,['true'|S],S) :- !. | |
| 304 | pp_ba_label(false,['false'|S],S) :- !. | |
| 305 | pp_ba_label(ap(AP),[Atom|S],S) :- !, | |
| 306 | pp_ap(AP,Atom). | |
| 307 | pp_ba_label(tp(TP),[Atom|S],S) :- !, | |
| 308 | pp_tp(TP,Atom). | |
| 309 | pp_ba_label(not(Pred),['! ('|S],T) :- !, | |
| 310 | pp_ba_label(Pred,S,[')'|T]). | |
| 311 | pp_ba_label(and(Pred1,Pred2),['('|S],T) :- !, | |
| 312 | pp_ba_label(Pred1,S,[' && '| S1]), | |
| 313 | pp_ba_label(Pred2,S1,[')'|T]). | |
| 314 | pp_ba_label(or(Pred1,Pred2),['('|S],T) :- !, | |
| 315 | pp_ba_label(Pred1,S,[' || '| S1]), | |
| 316 | pp_ba_label(Pred2,S1,[')'|T]). | |
| 317 | pp_ba_label(Otherwise,['???'|S],S) :- | |
| 318 | add_error(printing_ba_label_for_ltl2ba,'Non-expected label: ',Otherwise). | |
| 319 | ||
| 320 | print_label(Label) :- | |
| 321 | print(' --('),print(Label),print(')--> '). | |
| 322 | ||
| 323 | translate_to_ltl2ba_syntax(Formula,Text) :- | |
| 324 | retractall(ap_representation(_,_)), | |
| 325 | retractall(tp_representation(_,_)), | |
| 326 | retractall(tps_occurring), | |
| 327 | pp_formula_to_ltl2ba_syntax(Formula,Text). | |
| 328 | ||
| 329 | pp_formula_to_ltl2ba_syntax(Formula,Res) :- | |
| 330 | pp_to_ltl2ba_syntax(Formula,Atoms,[]), | |
| 331 | ajoin(Atoms,Res). | |
| 332 | ||
| 333 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 334 | %%%%%%%%%%%%%%%%% Unit Tests %%%%%%%%%%%%%%%%%%%%%% | |
| 335 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| 336 | ||
| 337 | :- assert_must_succeed((F = and(or(true,false),true), | |
| 338 | pp_formula_to_ltl2ba_syntax(F,Text), | |
| 339 | Text = '((true || false) && true)')). | |
| 340 | :- assert_must_succeed((F = implies(deadlock,not(true)), | |
| 341 | pp_formula_to_ltl2ba_syntax(F,Text), | |
| 342 | Text = '(deadlock -> ! true)')). | |
| 343 | :- assert_must_succeed((F = not(until(true,next(implies(deadlock,not(true))))), | |
| 344 | pp_formula_to_ltl2ba_syntax(F,Text), | |
| 345 | Text = '! (true U X ((deadlock -> ! true)))')). | |
| 346 | :- assert_must_succeed((F = weakuntil(true,false), | |
| 347 | pp_formula_to_ltl2ba_syntax(F,Text), | |
| 348 | Text = '((! true || false) V (true || false))')). | |
| 349 | :- assert_must_succeed((F = globally(finally(true)), | |
| 350 | pp_formula_to_ltl2ba_syntax(F,Text), | |
| 351 | Text = '[] (<> (true))')). | |
| 352 | ||
| 353 | ||
| 354 | pp_to_ltl2ba_syntax(true,['true'|S],S) :- !. | |
| 355 | pp_to_ltl2ba_syntax(false,['false'|S],S) :- !. | |
| 356 | pp_to_ltl2ba_syntax(deadlock,['deadlock'|S],S) :- !. | |
| 357 | pp_to_ltl2ba_syntax(ap(X),[AP|S],S) :- !, | |
| 358 | term_hash(X,Hash), | |
| 359 | ajoin(['ap',Hash],AP), | |
| 360 | (\+ap_representation(AP,_) -> assert(ap_representation(AP,X)); true). | |
| 361 | pp_to_ltl2ba_syntax(action(X),[TP|S],S) :- !, | |
| 362 | assert(tps_occurring), | |
| 363 | term_hash(X,Hash), | |
| 364 | ajoin(['tp',Hash],TP), | |
| 365 | (\+tp_representation(TP,_) -> assert(tp_representation(TP,X)); true). | |
| 366 | pp_to_ltl2ba_syntax(not(X),['! '|S],T) :- !, | |
| 367 | pp_to_ltl2ba_syntax(X,S,T). | |
| 368 | pp_to_ltl2ba_syntax(and(X,Y),['('|S],T) :- !, | |
| 369 | pp_to_ltl2ba_syntax(X,S,[' && '|S1]), | |
| 370 | pp_to_ltl2ba_syntax(Y,S1,[')'|T]). | |
| 371 | pp_to_ltl2ba_syntax(or(X,Y),['('|S],T) :- !, | |
| 372 | pp_to_ltl2ba_syntax(X,S,[' || '|S1]), | |
| 373 | pp_to_ltl2ba_syntax(Y,S1,[')'|T]). | |
| 374 | pp_to_ltl2ba_syntax(implies(X,Y),['('|S],T) :- !, | |
| 375 | pp_to_ltl2ba_syntax(X,S,[' -> '|S1]), | |
| 376 | pp_to_ltl2ba_syntax(Y,S1,[')'|T]). | |
| 377 | pp_to_ltl2ba_syntax(next(X),['X ('|S],T) :- !, | |
| 378 | pp_to_ltl2ba_syntax(X,S,[')'|T]). | |
| 379 | pp_to_ltl2ba_syntax(globally(X),['[] ('|S],T) :- !, | |
| 380 | pp_to_ltl2ba_syntax(X,S,[')'|T]). | |
| 381 | pp_to_ltl2ba_syntax(finally(X),['<> ('|S],T) :- !, | |
| 382 | pp_to_ltl2ba_syntax(X,S,[')'|T]). | |
| 383 | pp_to_ltl2ba_syntax(until(X,Y),['('|S],T) :- !, | |
| 384 | pp_to_ltl2ba_syntax(X,S,[' U '|S1]), | |
| 385 | pp_to_ltl2ba_syntax(Y,S1,[')'|T]). | |
| 386 | pp_to_ltl2ba_syntax(release(X,Y),['('|S],T) :- !, | |
| 387 | pp_to_ltl2ba_syntax(X,S,[' V '|S1]), | |
| 388 | pp_to_ltl2ba_syntax(Y,S1,[')'|T]). | |
| 389 | pp_to_ltl2ba_syntax(weakuntil(X,Y),S,T) :- !, | |
| 390 | pp_to_ltl2ba_syntax(release(or(not(X),Y),or(X,Y)),S,T). | |
| 391 | ||
| 392 | ||
| 393 | %% Obsolete predicates (to be removed later) | |
| 394 | ||
| 395 | ||
| 396 | %create_ba_pl_file(Text,Filename) :- | |
| 397 | % write_string_to_file('prob_buchi_temp.pl',Filename,Text). | |
| 398 | % | |
| 399 | %write_string_to_file(BaseName,Filename,Machine) :- | |
| 400 | % open(temp(BaseName),write,S,[if_exists(generate_unique_name),encoding('UTF-8')]), | |
| 401 | % stream_property(S, file_name(Filename)), | |
| 402 | % print_string(Machine,S), | |
| 403 | % close(S). | |
| 404 | % | |
| 405 | %print_string([],_). | |
| 406 | %print_string([C|Rest],S) :- put_code(S,C),print_string(Rest,S). | |
| 407 | ||
| 408 |