| 1 | % Heinrich Heine Universitaet Duesseldorf | |
| 2 | % (c) 2025-2026 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
| 3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
| 4 | ||
| 5 | % Implementation of a Sequent Prover | |
| 6 | % where we can use the ProB animator to perform proof steps | |
| 7 | % proof rules taken/adapted from https://wiki.event-b.org/index.php/Inference_Rules | |
| 8 | % rewrite rules taken/adapted from https://wiki.event-b.org/index.php/All_Rewrite_Rules | |
| 9 | % the term representation is the one from ProB's well_definedness prover | |
| 10 | ||
| 11 | :- module(sequent_prover,[initialise_for_po_file/1, | |
| 12 | cont_length/2, | |
| 13 | get_continuations/2, | |
| 14 | get_scope/3, | |
| 15 | parse_input/3, | |
| 16 | translate_norm_expr_term/2, | |
| 17 | used_identifiers/2, | |
| 18 | ||
| 19 | po_nr_label/2, normalised_hyps/3, normalised_goal/3 | |
| 20 | ]). | |
| 21 | ||
| 22 | :- use_module(probsrc(module_information),[module_info/2]). | |
| 23 | :- module_info(group,sequent_prover). | |
| 24 | :- module_info(description,'This module provides rewrite and inference rules for the sequent_prover'). | |
| 25 | ||
| 26 | :- use_module(library(lists)). | |
| 27 | :- use_module(probsrc(error_manager),[add_error/3, add_internal_error/2]). | |
| 28 | :- use_module(probsrc(tools),[ajoin/2, flatten/2, list_intersection/3, list_difference/3]). | |
| 29 | :- use_module(probsrc(translate),[transform_raw/2]). | |
| 30 | :- use_module(wdsrc(well_def_hyps),[convert_norm_expr_to_raw/2, | |
| 31 | normalize_expression/2, normalize_predicate/2]). | |
| 32 | :- use_module(seqproversrc(sequent_auto_prover),[bounded_find_proof/5]). | |
| 33 | :- use_module(seqproversrc(simplification_rules),[simplification_rule/6, is_true/1]). | |
| 34 | :- use_module(seqproversrc(prover_utils)). | |
| 35 | ||
| 36 | % ------------------------ | |
| 37 | :- dynamic normalised_hyps/3, normalised_goal/3, po_nr_label/2. % for BPR export | |
| 38 | ||
| 39 | initialise_for_po_file(File) :- | |
| 40 | retractall(normalised_pred(_,_,_)), | |
| 41 | retractall(normalised_pred(_,_,_)), | |
| 42 | retractall(po_nr_label(_,_)), | |
| 43 | bb_put(po_counter,1), | |
| 44 | load_from_po_file(File,Hyps,Goal,PO,PODesc,Info), | |
| 45 | sort(Hyps,SHyps), | |
| 46 | % for ProB XTL Mode: specifying the start states: | |
| 47 | bb_get(po_counter,PONR), | |
| 48 | assertz(po_nr_label(PONR,PO)), | |
| 49 | assertz(xtl_interface:start(state(sequent(SHyps,Goal,success(PONR)),Info),[description(PODesc)])), | |
| 50 | P1 is PONR+1, bb_put(po_counter,P1), | |
| 51 | fail. | |
| 52 | initialise_for_po_file(_) :- | |
| 53 | % assert other xtl_interface predicates: | |
| 54 | assertz((xtl_interface:trans(A,B,C) :- sequent_prover:sequent_prover_trans_start(A,B,C))), | |
| 55 | assertz((xtl_interface:trans(A,B,C,D) :- sequent_prover:sequent_prover_trans_start_desc(A,B,C,D))), | |
| 56 | assertz((xtl_interface:trans_prop(A,B) :- sequent_prover:trans_prop(A,B))), | |
| 57 | assertz((xtl_interface:prop(A,B) :- sequent_prover:prop(A,B))), | |
| 58 | assertz((xtl_interface:symb_trans(A,B,C,D) :- sequent_prover:symb_trans(A,B,C,D))), | |
| 59 | assertz((xtl_interface:symb_trans_enabled(A,B) :- sequent_prover:symb_trans_enabled(A,B))), | |
| 60 | assertz((xtl_interface:animation_function_result(A,B) :- sequent_prover:animation_function_result(A,B))), | |
| 61 | assertz((xtl_interface:animation_image_right_click_transition(A,B,C) :- sequent_prover:animation_image_right_click_transition(A,B,C))), | |
| 62 | assertz((xtl_interface:animation_image_right_click_transition(A,B,C,D) :- sequent_prover:animation_image_right_click_transition(A,B,C,D))), | |
| 63 | assertz(xtl_interface:nr_state_properties(30)). % TODO: a dynamic solution would be nice. | |
| 64 | ||
| 65 | :- use_module(probsrc(preferences),[get_preference/2]). | |
| 66 | rodin_mode :- get_preference(sequent_prover_rodin_mode,true). | |
| 67 | ||
| 68 | % declare these public as we will assert calls to them in the code above for initialise_for_po_file: | |
| 69 | :- public prop/2, sequent_prover_trans/3, sequent_prover_trans_desc/4, symb_trans/4, symb_trans_enabled/2. | |
| 70 | :- public animation_function_result/2, animation_image_right_click_transition/3, animation_image_right_click_transition/4. | |
| 71 | :- public sequent_prover_trans_start/3, sequent_prover_trans_start_desc/4, trans_prop/2. | |
| 72 | ||
| 73 | % ------------------------ | |
| 74 | ||
| 75 | get_normalised_bexpr(Expr,NormExpr) :- | |
| 76 | transform_raw(Expr,TExpr), | |
| 77 | normalize_predicate(TExpr,NormExpr). | |
| 78 | ||
| 79 | :- use_module(probsrc(xtl_interface),[get_disprover_po/6]). | |
| 80 | load_from_po_file(_File,Hyps,Goal,POLabel,FullPOLabel,[rawsets(RawSets),des_hyps(OtherHyps)]) :- | |
| 81 | % we use the disprover_po facts already loaded in xtl_interface, load_po_file(File) not necessary | |
| 82 | get_disprover_po(POLabel,Context,RawGoal,RawAllHyps,RawSelHyps,RodinStatus), | |
| 83 | ajoin([POLabel,' (',RodinStatus,')'],FullPOLabel), | |
| 84 | get_normalised_bexpr(RawGoal,Goal), | |
| 85 | list_difference(RawAllHyps,RawSelHyps,RawNotSelHyps), | |
| 86 | maplist(get_normalised_bexpr,RawSelHyps,Hyps), | |
| 87 | maplist(get_normalised_bexpr,RawNotSelHyps,OtherHyps), | |
| 88 | append(RawSelHyps,RawNotSelHyps,RawPreds), append(Hyps,OtherHyps,NormPreds), | |
| 89 | assertz(normalised_hyps(POLabel,RawPreds,NormPreds)), | |
| 90 | assertz(normalised_goal(POLabel,RawGoal,Goal)), | |
| 91 | bmachine_eventb:extract_ctx_sections(Context,_Name,_Extends,RawSets,_Constants,_AbstractConstants,_Axioms,_Theorems). | |
| 92 | ||
| 93 | ||
| 94 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs) :- | |
| 95 | get_scope(Hyps,Info,Scope), | |
| 96 | get_identifier_types(Scope,IdsTypes), | |
| 97 | new_aux_identifier(IdsTypes,Y), !, | |
| 98 | get_wd_pos2(equal('$'(Y),NormExpr),Scope,POs). | |
| 99 | ||
| 100 | get_wd_pos(NormExpr,Hyps,Info,POs) :- | |
| 101 | get_scope(Hyps,Info,Scope), | |
| 102 | get_wd_pos2(NormExpr,Scope,POs). | |
| 103 | ||
| 104 | get_wd_pos2(NormExpr,Scope,POs) :- | |
| 105 | convert_norm_expr_to_raw(NormExpr,ParsedRaw), | |
| 106 | bmachine:b_type_check_raw_expr(ParsedRaw,Scope,TypedPred,open(_)), | |
| 107 | well_def_hyps:empty_hyps(H), | |
| 108 | well_def_analyser:compute_all_wd_pos(TypedPred,H,[],TPOs), | |
| 109 | maplist(rewrite_type_set,TPOs,TPOsT), | |
| 110 | maplist(normalize_predicate,TPOsT,POs). | |
| 111 | ||
| 112 | get_scope(Hyps,Info,[identifier([])]) :- | |
| 113 | get_meta_info(des_hyps,Info,DHyps), | |
| 114 | append(Hyps,DHyps,[]), !. | |
| 115 | get_scope(Hyps,Info,[identifier(Res)]) :- | |
| 116 | get_meta_info(des_hyps,Info,DHyps), | |
| 117 | append(Hyps,DHyps,AllHyps), | |
| 118 | used_identifiers(AllHyps,Ids), | |
| 119 | sort(Ids,SortedIds), | |
| 120 | maplist(replace_bounded_ids(SortedIds),Hyps,HypsWithFreshBIds),!, | |
| 121 | (HypsWithFreshBIds=[] -> HypsConj=truth | |
| 122 | ; list_to_op(HypsWithFreshBIds,HypsConj,conjunct)), | |
| 123 | get_set_types(Ids,Info,SetIds), | |
| 124 | get_typed_identifiers(HypsConj,[identifier(SetIds)],List), | |
| 125 | append(SetIds,List,AllIds), | |
| 126 | select_types(AllIds,Res). | |
| 127 | ||
| 128 | replace_bounded_ids(_,E,Res) :- atomic(E),!,Res=E. | |
| 129 | replace_bounded_ids(_,'$'(E),Res) :- atomic(E),!,Res='$'(E). | |
| 130 | replace_bounded_ids(Ids,E,F) :- | |
| 131 | with_ids(E,BIds), % expression has bounded ids | |
| 132 | length(BIds,Len), | |
| 133 | possible_identifier(X), | |
| 134 | range_ids(X,Len,NewIds), % generate X_1, X_2, ... as NewIds | |
| 135 | list_intersection(Ids,NewIds,[]), !, % check if these are fresh | |
| 136 | rewrite_pairwise_ids(BIds,NewIds,E,F). | |
| 137 | replace_bounded_ids(Ids,E,F) :- % E is a compound term not introducing bounded ids | |
| 138 | E=..[Op|Args], | |
| 139 | maplist(replace_bounded_ids(Ids),Args,NewArgs), | |
| 140 | F=..[Op|NewArgs]. | |
| 141 | ||
| 142 | rewrite_pairwise_ids([],[],E,E). | |
| 143 | rewrite_pairwise_ids([X|TX],[Y|TY],E,Res) :- | |
| 144 | replace_id(X,Y,E,NewE), | |
| 145 | rewrite_pairwise_ids(TX,TY,NewE,Res). | |
| 146 | ||
| 147 | replace_id('$'(X),'$'(Y),'$'(X),'$'(Y)) :- atomic(X), !. | |
| 148 | replace_id(X,Y,C,NewC) :- C=..[Op|Args], | |
| 149 | maplist(replace_id(X,Y),Args,NewArgs), | |
| 150 | NewC=..[Op|NewArgs]. | |
| 151 | ||
| 152 | filter_hyps([],[]). | |
| 153 | filter_hyps([Expr|Hyps],Res) :- with_ids(Expr,_), !, filter_hyps(Hyps,Res). | |
| 154 | filter_hyps([Expr|Hyps],[Expr|Res]) :- filter_hyps(Hyps,Res). | |
| 155 | ||
| 156 | get_set_types([],_,[]). | |
| 157 | get_set_types(['$'(SetId)|T],Info,[b(identifier(SetId),set(global(SetId)),[])|R]) :- | |
| 158 | is_deferred_or_enumerated_set('$'(SetId),Info),!, | |
| 159 | get_set_types(T,Info,R). | |
| 160 | get_set_types([_|T],Info,R) :- get_set_types(T,Info,R). | |
| 161 | ||
| 162 | rewrite_type_set(X,Res) :- \+ compound(X),!, Res=X. | |
| 163 | rewrite_type_set(b(typeset,set(global(SET)),I),b(identifier(SET),set(global(SET)),I)) :- !. | |
| 164 | rewrite_type_set(C,NewC) :- C=..[Op|Args], | |
| 165 | maplist(rewrite_type_set,Args,NewArgs), | |
| 166 | NewC =.. [Op|NewArgs]. | |
| 167 | ||
| 168 | in_scope(Id,[identifier(List)]) :- memberchk(b(identifier(Id),_,[]),List). | |
| 169 | ||
| 170 | ||
| 171 | ||
| 172 | select_types(Types,Selected) :- sort(Types,Sorted), select_types_aux(Sorted,Selected). | |
| 173 | ||
| 174 | select_types_aux([],[]). | |
| 175 | select_types_aux([b(identifier(X),any,_)|R],Res) :- member(b(identifier(X),T,_),R), T \= any, !, select_types_aux(R,Res). | |
| 176 | select_types_aux([Id|R],[Id|Res]) :- select_types_aux(R,Res). | |
| 177 | ||
| 178 | get_typed_ast(NormExpr,TExpr) :- | |
| 179 | convert_norm_expr_to_raw(NormExpr,RawExpr), | |
| 180 | transform_raw(RawExpr,TExpr). | |
| 181 | ||
| 182 | get_identifier_types([identifier(IdsTypes)],IdsTypes). | |
| 183 | ||
| 184 | prove_predicate(Hyps,Goal) :- | |
| 185 | get_typed_ast(Goal,TGoal), | |
| 186 | maplist(get_typed_ast,Hyps,THyps), | |
| 187 | atelierb_provers_interface:prove_predicate(THyps,TGoal,proved). | |
| 188 | ||
| 189 | ||
| 190 | ||
| 191 | get_po_description(PONR,PO) :- | |
| 192 | xtl_interface:start(state(sequent(_SHyps,_Goal,success(PONR)),_Info),[description(PO)]). | |
| 193 | ||
| 194 | ||
| 195 | :- use_module(library(timeout), [time_out/3]). | |
| 196 | % specifying properties that appear in the State Properties view: | |
| 197 | prop(success(_Nr),goal). | |
| 198 | prop(success(Nr),'='('DISCHARGED',PO)) :- get_po_description(Nr,PO). | |
| 199 | prop(counter_example(_),'COUNTER_EXAMPLE_FOUND'). | |
| 200 | prop(counter_example(C),'='(ID,S)) :- member(binding(ID,_,S),C). | |
| 201 | prop(sequent(_,X,_), '='('GOAL',XS)) :- translate_norm_expr_term(X,XS). | |
| 202 | prop(sequent(Hyps,_,_),'='(HypNr,XS)) :- nth1(Nr,Hyps,X), | |
| 203 | translate_norm_expr_term(X,XS), ajoin(['HYP',Nr],HypNr). | |
| 204 | prop(sequent(_,_,Cont),'='('CONTINUATION',P)) :- cont_length(Cont,P). | |
| 205 | prop(state(sequent(Hyps,Goal,_),Info),'='(AutoProofStepNr,ProofStep)) :- | |
| 206 | (time_out(bounded_find_proof(sequent(Hyps,Goal,success(0)),Info,3,[],Proof),1500,TORes), | |
| 207 | TORes = success | |
| 208 | -> nth1(Nr,Proof,ProofStep), | |
| 209 | ajoin(['AUTO-PROOF-',Nr],AutoProofStepNr)). | |
| 210 | ||
| 211 | prop(state(S,_),Val) :- prop(S,Val). | |
| 212 | ||
| 213 | ||
| 214 | cont_length(sequent(_,_,C),R) :- !, cont_length(C,R1), R is R1+1. | |
| 215 | cont_length(success(_),R) :- !, R=0. | |
| 216 | cont_length(C,R) :- add_internal_error('Illegal continuation:',cont_length(C,R)),R=0. | |
| 217 | ||
| 218 | % ------------------------ | |
| 219 | ||
| 220 | :- discontiguous trans_prop/2, symb_trans_rule/4, symb_trans_rule/5, symb_trans_enabled/2. | |
| 221 | ||
| 222 | sequent_prover_trans_start(Rule,state(Sequent,Info),NewState) :- | |
| 223 | update_info(Sequent,Info,Info1), | |
| 224 | sequent_prover_trans(Rule,state(Sequent,Info1),NewState). | |
| 225 | sequent_prover_trans_start_desc(Rule,state(Sequent,Info),NewState,Descr) :- | |
| 226 | update_info(Sequent,Info,Info1), | |
| 227 | sequent_prover_trans_desc(Rule,state(Sequent,Info1),NewState,Descr). | |
| 228 | ||
| 229 | update_info(Sequent,Info,Info1) :- | |
| 230 | Sequent = sequent(Hyps,_,_), | |
| 231 | get_scope(Hyps,Info,[identifier(IdsTypes)]), | |
| 232 | update_meta_infos(ids_types,Info,IdsTypes,Info1). | |
| 233 | ||
| 234 | % transition rules without description information: | |
| 235 | sequent_prover_trans(Rule,state(Sequent,Info),state(NewSequent,Info)) :- | |
| 236 | trans_with_info(Rule,Sequent,NewSequent,Info). | |
| 237 | ||
| 238 | sequent_prover_trans(lasso,state(sequent(Hyps,Goal,Cont),Info),state(sequent(NewHyps,Goal,Cont),NewInfo)) :- | |
| 239 | get_meta_info(des_hyps,Info,DesHyps), | |
| 240 | used_identifiers_list([Goal|Hyps],UsedIds), | |
| 241 | find_hyps_with(UsedIds,DesHyps,SelectedHyps), | |
| 242 | SelectedHyps \= [], | |
| 243 | add_hyps(SelectedHyps,Hyps,NewHyps), | |
| 244 | list_difference(DesHyps,SelectedHyps,LeftDesHyps), | |
| 245 | update_meta_infos(des_hyps,Info,LeftDesHyps,NewInfo). | |
| 246 | ||
| 247 | % transition rules with description information: | |
| 248 | sequent_prover_trans_desc(Rule,state(Sequent,Info),state(NewSequent,Info),Descr) :- | |
| 249 | trans_desc_with_info(Rule,Sequent,NewSequent,Info,Descr). | |
| 250 | sequent_prover_trans_desc(RuleArg,state(Sequent,Info),state(NewSequent,Info1),[description(Descr)]) :- | |
| 251 | (trans_with_args(RuleArg,Sequent,NewSequent), Info1 = Info | |
| 252 | ; trans_with_args_info(RuleArg,state(Sequent,Info),state(NewSequent,Info1)) | |
| 253 | ), | |
| 254 | RuleArg=..[Rule,Arg], create_descr(Rule,Arg,Descr). | |
| 255 | sequent_prover_trans_desc(mon_deselect(Nr),state(sequent(Hyps,Goal,Cont),Info), | |
| 256 | state(sequent(Hyps0,Goal,Cont),Info1),[description(Descr)]) :- | |
| 257 | nth1(Nr,Hyps,Hyp,Hyps0), | |
| 258 | add_meta_info(des_hyps,Info,Hyp,Info1), | |
| 259 | create_descr(mon_deselect,Hyp,Descr). | |
| 260 | ||
| 261 | % transition rules requiring Infos and returning descriptions | |
| 262 | trans_desc_with_info(Rule,Sequent,NewSequent,_Info,Desc) :- | |
| 263 | trans_desc_wo_info(Rule,Sequent,NewSequent,Desc). | |
| 264 | trans_desc_with_info(Rule,Sequent,NewSequent,Info,Desc) :- | |
| 265 | trans_desc_simplification_rule(Rule,Sequent,NewSequent,Info,Desc). | |
| 266 | ||
| 267 | trans_desc_simplification_rule(simplify_goal(Rule),sequent(Hyps,Goal,Cont), | |
| 268 | NewSequent,Info,[description(Descr)]) :- | |
| 269 | simplification_rule(Goal,NewGoal,Hyps,Rule,Descr,Info), | |
| 270 | (rodin_mode, NewGoal=conjunct(_,_) | |
| 271 | -> op_to_list(NewGoal,ListOfGoals,conjunct), | |
| 272 | add_goals(Hyps,ListOfGoals,Cont,NewSequent) | |
| 273 | ; NewSequent=sequent(Hyps,NewGoal,Cont)). | |
| 274 | trans_desc_simplification_rule(simplify_hyp(Rule,Hyp),sequent(Hyps,Goal,Cont), | |
| 275 | sequent(SHyps,Goal,Cont),Info,[description(Descr)]) :- | |
| 276 | select(Hyp,Hyps,NewHyp,NewHyps), | |
| 277 | simplification_rule(Hyp,NewHyp,Hyps,Rule,Descr,Info), | |
| 278 | (rodin_mode, NewHyp=conjunct(_,_) | |
| 279 | -> append(PH,[NewHyp|TH],NewHyps), | |
| 280 | op_to_list(NewHyp,NewConjHyps,conjunct), | |
| 281 | append(NewConjHyps,TH,NTH), | |
| 282 | append(PH,NTH,AddHyps) | |
| 283 | ; AddHyps=NewHyps), | |
| 284 | without_duplicates(AddHyps,SHyps). | |
| 285 | ||
| 286 | ||
| 287 | % transition rules without descriptions but with Info being passed | |
| 288 | trans_with_info(Rule,Sequent,NewSequent,_Info) :- trans_wo_info(Rule,Sequent,NewSequent). | |
| 289 | trans_with_info(deriv_le_card,sequent(Hyps,Goal,Cont),sequent(Hyps,subset(S,T),Cont),Info) :- % covers DERIV_GE_CARD too | |
| 290 | is_less_eq(Goal,card(S),card(T)), | |
| 291 | get_meta_info(ids_types,Info,IdsTypes), | |
| 292 | same_type(S,T,IdsTypes). | |
| 293 | trans_with_info(deriv_lt_card,sequent(Hyps,Goal,Cont),sequent(Hyps,subset_strict(S,T),Cont),Info) :- % / DERIV_GT_CARD | |
| 294 | is_less(Goal,card(S),card(T)), | |
| 295 | get_meta_info(ids_types,Info,IdsTypes), | |
| 296 | same_type(S,T,IdsTypes). | |
| 297 | trans_with_info(deriv_equal_card,sequent(Hyps,equal(card(S),card(T)),Cont),sequent(Hyps,equal(S,T),Cont),Info) :- | |
| 298 | get_meta_info(ids_types,Info,IdsTypes), | |
| 299 | same_type(S,T,IdsTypes). | |
| 300 | trans_with_info(sim_rel_image_r,sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 301 | rewrite_once(image(F,set_extension([E])),set_extension([function(F,E)]),Goal,NewGoal), | |
| 302 | get_wd_pos(NewGoal,Hyps,Info,POs), | |
| 303 | add_wd_pos(Hyps,POs,sequent(Hyps,NewGoal,Cont),NewSequent). | |
| 304 | trans_with_info(sim_rel_image_l,sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 305 | select(Hyp,Hyps,Hyps0), | |
| 306 | rewrite_once(image(F,set_extension([E])),set_extension([function(F,E)]),Hyp,NewHyp), | |
| 307 | add_hyp(NewHyp,Hyps0,Hyps1), | |
| 308 | get_wd_pos(NewHyp,Hyps0,Info,POs), | |
| 309 | add_wd_pos(Hyps0,POs,sequent(Hyps1,Goal,Cont),NewSequent). | |
| 310 | trans_with_info(sim_fcomp_l,sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 311 | select(Hyp,Hyps,Hyps0), | |
| 312 | Sub = function(Comp,X), | |
| 313 | is_subterm(Sub,Hyp), | |
| 314 | split_composition(Comp,F,G), | |
| 315 | NewSub = function(G,function(F,X)), | |
| 316 | rewrite_once(Sub,NewSub,Hyp,NewHyp), | |
| 317 | add_hyp(NewHyp,Hyps0,Hyps1), | |
| 318 | get_wd_pos(NewHyp,Hyps0,Info,POs), | |
| 319 | add_wd_pos(Hyps0,POs,sequent(Hyps1,Goal,Cont),NewSequent). | |
| 320 | trans_with_info(sim_fcomp_r,sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 321 | Sub = function(Comp,X), | |
| 322 | is_subterm(Sub,Goal), | |
| 323 | split_composition(Comp,F,G), | |
| 324 | NewSub = function(G,function(F,X)), | |
| 325 | rewrite_once(Sub,NewSub,Goal,NewGoal), | |
| 326 | get_wd_pos(NewGoal,Hyps,Info,POs), | |
| 327 | add_wd_pos(Hyps,POs,sequent(Hyps,NewGoal,Cont),NewSequent). | |
| 328 | trans_with_info(xst_l,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont),Info) :- | |
| 329 | Hyp = exists(Ids,P), | |
| 330 | select(Hyp,Hyps,NewP,Hyps1), | |
| 331 | get_meta_info(ids_types,Info,IdsTypes), | |
| 332 | replace_used_ids(Ids,IdsTypes,NewIds), | |
| 333 | rewrite_pairwise_rev(Ids,NewIds,P,NewP). | |
| 334 | trans_with_info(all_r,sequent(Hyps,forall(Ids,P,Q),Cont),sequent(Hyps,NewImp,Cont),Info) :- | |
| 335 | get_meta_info(ids_types,Info,IdsTypes), | |
| 336 | replace_used_ids(Ids,IdsTypes,NewIds), | |
| 337 | rewrite_pairwise_rev(Ids,NewIds,implication(P,Q),NewImp). | |
| 338 | trans_with_info(Rule,sequent(Hyps,Goal,Cont),Cont,Info) :- axiom_with_info(Rule,Hyps,Goal,Info). | |
| 339 | trans_with_info(Rule,sequent(Hyps,Goal,Cont),Cont,Info) :- (member(Hyp,Hyps), mb_goal(Rule,Hyp,Goal,Info)) ; mb_goal(Rule,Hyps,Goal). | |
| 340 | ||
| 341 | % transitions which do not require Infos (about typed ids) | |
| 342 | trans_wo_info(Rule,sequent(Hyps,Goal,Cont),Cont) :- axiom(Rule,Hyps,Goal). | |
| 343 | trans_wo_info(dbl_hyp,sequent(Hyps,Goal,Cont),sequent(SHyps,Goal,Cont)) :- | |
| 344 | % not really necessary if we remove duplicates in Hyps everywhere else | |
| 345 | without_duplicates(Hyps,SHyps), SHyps \= Hyps. | |
| 346 | trans_wo_info(or_r,sequent(Hyps,disjunct(GA,GB),Cont),sequent(Hyps1,GA,Cont)) :- | |
| 347 | % Hyps |- G1 or G2 ===> Hyps,not(G1) |- G2 | |
| 348 | negate(GB,NotGB), % we could also negate GA and use GB as goal | |
| 349 | add_hyp(NotGB,Hyps,Hyps1). | |
| 350 | trans_wo_info(imp_r,sequent(Hyps,implication(G1,G2),Cont), | |
| 351 | sequent(Hyps1,G2,Cont)) :- | |
| 352 | % Hyps |- G1 => G2 ===> Hyps,G1 |- G2 | |
| 353 | add_hyp(G1,Hyps,Hyps1). | |
| 354 | trans_wo_info(and_r,sequent(Hyps,conjunct(G1,G2),Cont),NewSequent) :- | |
| 355 | % Hyps |- G1 & G2 ===> Hyps |- G1 + Hyps |- G2 | |
| 356 | op_to_list(conjunct(G1,G2),ListOfGoals,conjunct), | |
| 357 | add_goals(Hyps,ListOfGoals,Cont,NewSequent). | |
| 358 | trans_wo_info(neg_in,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- % covers NEG_IN_L and NEG_IN_R | |
| 359 | member(member(E,set_extension(L)),Hyps), | |
| 360 | member(InEq,Hyps), | |
| 361 | is_inequality(InEq,E,B), | |
| 362 | member(C,L), | |
| 363 | equal_terms(B,C), | |
| 364 | select(C,L,R), | |
| 365 | select(member(E,set_extension(L)),Hyps,member(E,set_extension(R)),Hyps1). | |
| 366 | trans_wo_info(contradict_r,sequent(Hyps,Goal,Cont),sequent(Hyps0,falsity,Cont)) :- | |
| 367 | Goal \= falsity, % proof rule is useless here; we just add not(falsity) to hyp | |
| 368 | add_hyp(negation(Goal),Hyps,Hyps0). | |
| 369 | trans_wo_info(lower_bound_l,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(Set),Cont)) :- | |
| 370 | Goal = exists([B],forall([X],member(X,Set),less_equal(B,X))). % TODO: Set must not contain any bound variable | |
| 371 | trans_wo_info(lower_bound_r,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(Set),Cont)) :- | |
| 372 | Goal = exists([B],forall([X],member(X,Set),greater_equal(X,B))). % TODO: Set must not contain any bound variable | |
| 373 | trans_wo_info(upper_bound_l,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(Set),Cont)) :- | |
| 374 | Goal = exists([B],forall([X],member(X,Set),greater_equal(B,X))). % TODO: Set must not contain any bound variable | |
| 375 | trans_wo_info(upper_bound_r,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(Set),Cont)) :- | |
| 376 | Goal = exists([B],forall([X],member(X,Set),less_equal(X,B))). % TODO: Set must not contain any bound variable | |
| 377 | trans_wo_info(fin_lt_0,sequent(Hyps,finite(S),Cont),sequent(Hyps,Goal1,sequent(Hyps,Goal2,Cont))):- | |
| 378 | new_identifier(S,X), | |
| 379 | new_identifier(member(S,X),N), | |
| 380 | Goal1 = exists([N],forall([X],member(X,S),less_equal(N,X))), | |
| 381 | Goal2 = subset(S,set_subtraction(integer_set,natural1_set)). | |
| 382 | trans_wo_info(fin_ge_0,sequent(Hyps,finite(S),Cont),sequent(Hyps,Goal1,sequent(Hyps,Goal2,Cont))):- | |
| 383 | new_identifier(S,X), | |
| 384 | new_identifier(member(S,X),N), | |
| 385 | Goal1 = exists([N],forall([X],member(X,S),less_equal(X,N))), | |
| 386 | Goal2 = subset(S,natural_set). | |
| 387 | trans_wo_info(fin_binter_r,sequent(Hyps,finite(I),Cont),sequent(Hyps,Disj,Cont)) :- | |
| 388 | I = intersection(_,_), | |
| 389 | finite_intersection(I,Disj). | |
| 390 | trans_wo_info(fin_kinter_r,sequent(Hyps,finite(general_intersection(S)),Cont), | |
| 391 | sequent(Hyps,conjunct(exists([X],member(X,S)),finite(X)),Cont)) :- new_identifier(S,X). | |
| 392 | trans_wo_info(fin_qinter_r,sequent(Hyps,finite(quantified_intersection([X],P,E)),Cont), | |
| 393 | sequent(Hyps,conjunct(exists([X],member(X,P)),finite(E)),Cont)). | |
| 394 | trans_wo_info(fin_kunion_r,sequent(Hyps,finite(general_union(S)),Cont), | |
| 395 | sequent(Hyps,conjunct(finite(S),forall([X],member(X,S),finite(X))),Cont)) :- new_identifier(S,X). | |
| 396 | trans_wo_info(fin_qunion_r,sequent(Hyps,finite(quantified_union([X],P,E)),Cont), | |
| 397 | sequent(Hyps,conjunct(finite(event_b_comprehension_set([X],E,P)),forall([X],P,finite(E))),Cont)). | |
| 398 | trans_wo_info(fin_setminus_r,sequent(Hyps,finite(set_subtraction(S,_)),Cont),sequent(Hyps,finite(S),Cont)). | |
| 399 | trans_wo_info(fin_rel_img_r,sequent(Hyps,finite(image(F,_)),Cont),sequent(Hyps,finite(F),Cont)). | |
| 400 | trans_wo_info(fin_rel_ran_r,sequent(Hyps,finite(range(F)),Cont),sequent(Hyps,finite(F),Cont)). | |
| 401 | trans_wo_info(fin_rel_dom_r,sequent(Hyps,finite(domain(F)),Cont),sequent(Hyps,finite(F),Cont)). | |
| 402 | trans_wo_info(fin_fun_dom,sequent(Hyps,finite(Fun),Cont),sequent(Hyps,truth,Cont1)) :- | |
| 403 | member_hyps(member(Fun,FunType),Hyps), | |
| 404 | is_fun(FunType,_,Dom,_), | |
| 405 | (member_hyps(finite(Dom),Hyps) | |
| 406 | -> Cont1 = Cont | |
| 407 | ; Cont1 = sequent(Hyps,finite(Dom),Cont)). | |
| 408 | trans_wo_info(fin_fun_ran,sequent(Hyps,finite(Fun),Cont),sequent(Hyps,truth,Cont1)) :- | |
| 409 | member_hyps(member(Fun,FunType),Hyps), | |
| 410 | is_inj(FunType,_,Ran), | |
| 411 | (member_hyps(finite(Ran),Hyps) | |
| 412 | -> Cont1 = Cont | |
| 413 | ; Cont1 = sequent(Hyps,finite(Ran),Cont)). | |
| 414 | trans_wo_info(sim_ov_rel,sequent(Hyps,member(overwrite(Fun,set_extension([couple(X,Y)])),relations(A,B)),Cont), | |
| 415 | sequent(Hyps,member(X,A),sequent(Hyps,member(Y,B),Cont))) :- | |
| 416 | member_hyps(member(Fun,FunType),Hyps), | |
| 417 | is_rel(FunType,_,A,B). | |
| 418 | trans_wo_info(sim_ov_trel,sequent(Hyps,member(overwrite(Fun,set_extension([couple(X,Y)])),total_relation(A,B)),Cont), | |
| 419 | sequent(Hyps,member(X,A),sequent(Hyps,member(Y,B),Cont))) :- | |
| 420 | member_hyps(member(Fun,FunType),Hyps), | |
| 421 | is_rel(FunType,total,A,B). | |
| 422 | trans_wo_info(sim_ov_pfun,sequent(Hyps,member(overwrite(Fun,set_extension([couple(X,Y)])),partial_function(A,B)),Cont), | |
| 423 | sequent(Hyps,member(X,A),sequent(Hyps,member(Y,B),Cont))) :- | |
| 424 | member_hyps(member(Fun,FunType),Hyps), | |
| 425 | is_fun(FunType,_,A,B). | |
| 426 | trans_wo_info(sim_ov_tfun,sequent(Hyps,member(overwrite(Fun,set_extension([couple(X,Y)])),total_function(A,B)),Cont), | |
| 427 | sequent(Hyps,member(X,A),sequent(Hyps,member(Y,B),Cont))) :- | |
| 428 | member_hyps(member(Fun,FunType),Hyps), | |
| 429 | is_fun(FunType,total,A,B). | |
| 430 | trans_wo_info(fun_image_goal,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- | |
| 431 | wd_strict_term(Goal), | |
| 432 | is_subterm(Hyp,Goal), | |
| 433 | Hyp = function(F,E), | |
| 434 | member(member(F,RType),Hyps), | |
| 435 | is_rel(RType,_,_,Ran), | |
| 436 | \+ member(member(function(F,E),Ran),Hyps), | |
| 437 | add_hyp(member(function(F,E),Ran),Hyps,Hyps1). | |
| 438 | trans_wo_info(ov_setenum_l,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont))) :- | |
| 439 | select(Hyp,Hyps,Hyps0), | |
| 440 | wd_strict_term(Hyp), | |
| 441 | Fun = function(overwrite(F,set_extension([couple(E,V)])),G), | |
| 442 | rewrite_once(Fun,V,Hyp,Hyp1), | |
| 443 | add_hyps([equal(G,E),Hyp1],Hyps0,Hyps1), | |
| 444 | rewrite_once(Fun,function(domain_subtraction(set_extension([E]),F),G),Hyp,Hyp2), | |
| 445 | add_hyps([negation(equal(G,E)),Hyp2],Hyps0,Hyps2). | |
| 446 | trans_wo_info(ov_setenum_r,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal1,sequent(Hyps2,Goal2,Cont))) :- | |
| 447 | wd_strict_term(Goal), | |
| 448 | Fun = function(overwrite(F,set_extension([couple(E,V)])),G), | |
| 449 | rewrite_once(Fun,V,Goal,Goal1), | |
| 450 | add_hyp(equal(G,E),Hyps,Hyps1), | |
| 451 | rewrite_once(Fun,function(domain_subtraction(set_extension([E]),F),G),Goal,Goal2), | |
| 452 | add_hyp(negation(equal(G,E)),Hyps,Hyps2). | |
| 453 | trans_wo_info(ov_l,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont))) :- | |
| 454 | select(Hyp,Hyps,Hyps0), | |
| 455 | wd_strict_term(Hyp), | |
| 456 | Fun = function(overwrite(F,S),G), | |
| 457 | rewrite_once(Fun,function(S,G),Hyp,Hyp1), | |
| 458 | add_hyps([member(G,domain(S)),Hyp1],Hyps0,Hyps1), | |
| 459 | rewrite_once(Fun,function(domain_subtraction(domain(S),F),G),Hyp,Hyp2), | |
| 460 | add_hyps([negation(member(G,domain(S))),Hyp2],Hyps0,Hyps2). | |
| 461 | trans_wo_info(ov_r,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal1,sequent(Hyps2,Goal2,Cont))) :- | |
| 462 | wd_strict_term(Goal), | |
| 463 | Fun = function(overwrite(F,S),G), | |
| 464 | rewrite_once(Fun,function(S,G),Goal,Goal1), | |
| 465 | add_hyp(member(G,domain(S)),Hyps,Hyps1), | |
| 466 | rewrite_once(Fun,function(domain_subtraction(domain(S),F),G),Goal,Goal2), | |
| 467 | add_hyp(negation(member(G,domain(S))),Hyps,Hyps2). | |
| 468 | trans_wo_info(subset_inter,sequent(Hyps,Goal,Cont),sequent(Hyps,NewGoal,Cont)) :- | |
| 469 | member_hyps(subset(T,U),Hyps), | |
| 470 | free_identifiers(Goal,Ids), | |
| 471 | member(T,Ids), % T and U are not bound | |
| 472 | member(U,Ids), | |
| 473 | is_subterm(Inter,Goal), | |
| 474 | select_op(U,Inter,Inter0,intersection), | |
| 475 | rewrite_once(Inter,Inter0,Goal,NewGoal), | |
| 476 | member_of(intersection,T,Inter). | |
| 477 | trans_wo_info(in_inter,sequent(Hyps,Goal,Cont),sequent(Hyps,NewGoal,Cont)) :- | |
| 478 | member_hyps(member(E,T),Hyps), | |
| 479 | free_identifiers(Goal,Ids), | |
| 480 | member(E,Ids), | |
| 481 | member(T,Ids), | |
| 482 | is_subterm(Inter,Goal), | |
| 483 | select_op(T,Inter,Inter0,intersection), | |
| 484 | rewrite_once(Inter,Inter0,Goal,NewGoal), | |
| 485 | member_of(intersection,set_extension([E]),Inter). | |
| 486 | trans_wo_info(notin_inter,sequent(Hyps,Goal,Cont),sequent(Hyps,NewGoal,Cont)) :- | |
| 487 | member_hyps(negation(member(E,T)),Hyps), | |
| 488 | free_identifiers(Goal,Ids), | |
| 489 | member(E,Ids), | |
| 490 | member(T,Ids), | |
| 491 | Inter = intersection(_,_), | |
| 492 | is_subterm(Inter,Goal), | |
| 493 | rewrite_once(Inter,empty_set,Goal,NewGoal), | |
| 494 | member_of(intersection,set_extension([E]),Inter), | |
| 495 | member_of(intersection,T,Inter). | |
| 496 | trans_wo_info(card_interv,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal1,sequent(Hyps2,Goal2,Cont))) :- | |
| 497 | wd_strict_term(Goal), | |
| 498 | rewrite_once(card(interval(A,B)),add(minus(B,A),1),Goal,Goal1), | |
| 499 | rewrite_once(card(interval(A,B)),0,Goal,Goal2), | |
| 500 | add_hyp(less_equal(A,B),Hyps,Hyps1), | |
| 501 | add_hyp(less(B,A),Hyps,Hyps2). | |
| 502 | trans_wo_info(card_empty_interv,sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont))) :- | |
| 503 | select(Hyp,Hyps,Hyps0), | |
| 504 | wd_strict_term(Hyp), | |
| 505 | rewrite_once(card(interval(A,B)),add(minus(B,A),1),Hyp,Hyp1), | |
| 506 | rewrite_once(card(interval(A,B)),0,Hyp,Hyp2), | |
| 507 | add_hyps([less_equal(A,B),Hyp1],Hyps0,Hyps1), | |
| 508 | add_hyps([less(B,A),Hyp2],Hyps0,Hyps2). | |
| 509 | trans_wo_info(simp_card_setminus_l,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(S),sequent(Hyps1,Goal,Cont))) :- | |
| 510 | select(Hyp,Hyps,Hyps0), | |
| 511 | rewrite_once(card(set_subtraction(S,T)),minus(card(S),card(intersection(S,T))),Hyp,Hyp1), | |
| 512 | add_hyp(Hyp1,Hyps0,Hyps1). | |
| 513 | trans_wo_info(simp_card_setminus_r,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(S),sequent(Hyps,NewGoal,Cont))) :- | |
| 514 | rewrite_once(card(set_subtraction(S,T)),minus(card(S),card(intersection(S,T))),Goal,NewGoal). | |
| 515 | trans_wo_info(simp_card_cprod_l,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(S),sequent(Hyps,finite(T),sequent(NewHyps,Goal,Cont)))) :- | |
| 516 | select(Hyp,Hyps,NewHyp,NewHyps), | |
| 517 | rewrite_once(card(cartesian_product(S,T)),multiplication(card(S),card(T)),Hyp,NewHyp). | |
| 518 | trans_wo_info(simp_card_cprod_r,sequent(Hyps,Goal,Cont),sequent(Hyps,finite(S),sequent(Hyps,finite(T),sequent(Hyps,NewGoal,Cont)))) :- | |
| 519 | rewrite_once(card(cartesian_product(S,T)),multiplication(card(S),card(T)),Goal,NewGoal). | |
| 520 | trans_wo_info(skip_to_cont,sequent(Hyps,Goal,Cont),NewState) :- | |
| 521 | Cont \= success(_), | |
| 522 | append_sequents(Cont,sequent(Hyps,Goal,success(PO_Nr)),NewState,PO_Nr). | |
| 523 | ||
| 524 | finite_intersection(intersection(A,B),Disj) :- finite_intersection(A,DisjA), finite_intersection(B,DisjB), !, Disj = disjunct(DisjA,DisjB). | |
| 525 | finite_intersection(S,finite(S)). | |
| 526 | ||
| 527 | % trans_desc_wo_info/4 | |
| 528 | trans_desc_wo_info(eq(Dir,X,Y),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal1,Cont),[description(Descr)]) :- | |
| 529 | select(equal(X,Y),Hyps,Hyps0), | |
| 530 | (Dir=lr, | |
| 531 | maplist(rewrite(X,Y),Hyps0,Hyps1), | |
| 532 | rewrite(X,Y,Goal,Goal1) | |
| 533 | ; Dir=rl, | |
| 534 | maplist(rewrite(Y,X),Hyps0,Hyps1), | |
| 535 | rewrite(Y,X,Goal,Goal1)), | |
| 536 | create_descr(eq,Dir,equal(X,Y),Descr). | |
| 537 | trans_desc_wo_info(eqv(Dir,X,Y),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal1,Cont),[description(Descr)]) :- | |
| 538 | select(equivalence(X,Y),Hyps,Hyps0), | |
| 539 | (Dir=lr, | |
| 540 | maplist(rewrite(X,Y),Hyps0,Hyps1), | |
| 541 | rewrite(X,Y,Goal,Goal1) | |
| 542 | ; Dir=rl, | |
| 543 | maplist(rewrite(Y,X),Hyps0,Hyps1), | |
| 544 | rewrite(Y,X,Goal,Goal1)), | |
| 545 | create_descr(eq,Dir,equal(X,Y),Descr). | |
| 546 | ||
| 547 | trans_with_args(and_l(Hyp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- | |
| 548 | % P & Q,... |- Goal ===> P,Q,... |- GOAL | |
| 549 | Hyp = conjunct(P,Q), | |
| 550 | select(Hyp,Hyps,Hyps0), | |
| 551 | add_hyps(P,Q,Hyps0,Hyps1). | |
| 552 | trans_with_args(imp_l1(Imp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- % covers auto_mh | |
| 553 | Imp = implication(P,Q), | |
| 554 | select(Imp,Hyps,Res,Hyps1), | |
| 555 | select_conjunct(PP,P,NewP), | |
| 556 | member_hyps(PP,Hyps), | |
| 557 | (NewP = truth -> Res = Q ; Res = implication(NewP,Q)). | |
| 558 | trans_with_args(imp_and_l(Hyp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- | |
| 559 | Hyp = implication(P,conjunct(Q,R)), | |
| 560 | select(Hyp,Hyps,Hyps0), | |
| 561 | add_hyps(implication(P,Q),implication(P,R),Hyps0,Hyps1). | |
| 562 | trans_with_args(imp_or_l(Hyp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,Cont)) :- | |
| 563 | Hyp = implication(disjunct(P,Q),R), | |
| 564 | select(Hyp,Hyps,Hyps0), | |
| 565 | add_hyps(implication(P,R),implication(Q,R),Hyps0,Hyps1). | |
| 566 | trans_with_args(contradict_l(P),sequent(Hyps,Goal,Cont),sequent(Hyps1,NotP,Cont)):- | |
| 567 | select(P,Hyps,Hyps0), | |
| 568 | negate(P,NotP), | |
| 569 | negate(Goal,NotGoal), | |
| 570 | add_hyp(NotGoal,Hyps0,Hyps1). | |
| 571 | trans_with_args(or_l(Hyp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont))) :- | |
| 572 | Hyp = disjunct(P,Q), | |
| 573 | select(Hyp,Hyps,Hyps0), | |
| 574 | add_hyp(P,Hyps0,Hyps1), | |
| 575 | add_hyp(Q,Hyps0,Hyps2). | |
| 576 | trans_with_args(case(D),sequent(Hyps,Goal,Cont),NewState) :- | |
| 577 | member(D,Hyps), | |
| 578 | D = disjunct(_,_), | |
| 579 | select(D,Hyps,Hyps0), | |
| 580 | extract_disjuncts(D,Hyps0,Goal,Cont,NewState). | |
| 581 | trans_with_args(imp_case(Imp),sequent(Hyps,Goal,Cont),sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont))) :- | |
| 582 | Imp = implication(P,Q), | |
| 583 | select(Imp,Hyps,Hyps0), | |
| 584 | add_hyp(negation(P),Hyps0,Hyps1), | |
| 585 | add_hyp(Q,Hyps0,Hyps2). | |
| 586 | trans_with_args(mh(Imp),sequent(Hyps,Goal,Cont),sequent(Hyps0,P,sequent(Hyps1,Goal,Cont))) :- | |
| 587 | Imp = implication(P,Q), % we prove P first and then can add Q as hypothesis | |
| 588 | select(Imp,Hyps,Hyps0), | |
| 589 | add_hyp(Q,Hyps0,Hyps1). | |
| 590 | trans_with_args(hm(Imp),sequent(Hyps,Goal,Cont),sequent(Hyps0,negation(Q),sequent(Hyps1,Goal,Cont))) :- | |
| 591 | Imp = implication(P,Q), % we prove not(Q) and then can add not(P) as hypothesis | |
| 592 | select(Imp,Hyps,Hyps0), | |
| 593 | add_hyp(negation(P),Hyps0,Hyps1). | |
| 594 | trans_with_args(def_expn_step(power_of(E,P)),sequent(Hyps,Goal,Cont),sequent(Hyps,not_equal(P,0),sequent(NewHyps,Goal,Cont))) :- | |
| 595 | select(Hyp,Hyps,Hyps0), | |
| 596 | rewrite_once(power_of(E,P),multiplication(E,power_of(E,minus(P,1))),Hyp,NewHyp), | |
| 597 | add_hyp(NewHyp,Hyps0,NewHyps). | |
| 598 | trans_with_args(def_expn_step(power_of(E,P)),sequent(Hyps,Goal,Cont),sequent(Hyps,not_equal(P,0),sequent(Hyps,NewGoal,Cont))) :- | |
| 599 | rewrite_once(power_of(E,P),multiplication(E,power_of(E,minus(P,1))),Goal,NewGoal). | |
| 600 | ||
| 601 | % trans_with_args on entire state with info: | |
| 602 | trans_with_args_info(reselect_hyp(Hyp),state(sequent(Hyps,Goal,Cont),Info),state(sequent(Hyps1,Goal,Cont),Info1)) :- | |
| 603 | remove_meta_info(des_hyps,Info,Hyp,Info1), | |
| 604 | add_hyp(Hyp,Hyps,Hyps1). | |
| 605 | trans_with_args_info(one_point_l(Eq),state(sequent(Hyps,Goal,Cont),Info),state(NewSequent,Info)) :- | |
| 606 | select(forall(Ids,P,Q),Hyps,Hyps0), | |
| 607 | select_conjunct(Eq,P,P0), | |
| 608 | is_equality(Eq,E,Y), | |
| 609 | select(Y,Ids,Ids0), | |
| 610 | rewrite(Y,E,P0,P1), | |
| 611 | rewrite(Y,E,Q,Q1), | |
| 612 | (Ids0 = [] -> NewHyp = implication(P1,Q1) ; NewHyp = forall(Ids0,P1,Q1)), | |
| 613 | add_hyp(NewHyp,Hyps0,Hyps1), | |
| 614 | get_wd_pos_of_expr(E,Hyps,Info,POs), | |
| 615 | add_wd_pos(Hyps0,POs,sequent(Hyps1,Goal,Cont),NewSequent). | |
| 616 | trans_with_args_info(one_point_r(Eq),state(sequent(Hyps,forall(Ids,P,Q),Cont),Info),state(NewSequent,Info)) :- | |
| 617 | select_conjunct(Eq,P,P0), | |
| 618 | is_equality(Eq,E,Y), | |
| 619 | select(Y,Ids,Ids0), | |
| 620 | rewrite(Y,E,P0,P1), | |
| 621 | rewrite(Y,E,Q,Q1), | |
| 622 | (Ids0 = [] -> NewGoal = implication(P1,Q1) ; NewGoal = forall(Ids0,P1,Q1)), | |
| 623 | get_wd_pos_of_expr(E,Hyps,Info,POs), | |
| 624 | add_wd_pos(Hyps,POs,sequent(Hyps,NewGoal,Cont),NewSequent). | |
| 625 | trans_with_args_info(induc_nat(X),state(sequent(Hyps,Goal,Cont),Info), | |
| 626 | state(sequent(Hyps,member(X,natural_set),sequent(Hyps1,Goal,sequent(Hyps2,GoalN1,Cont))),Info)) :- | |
| 627 | free_identifiers(Goal,Ids), | |
| 628 | member(X,Ids), | |
| 629 | of_integer_type(X,Info), | |
| 630 | new_identifier(Goal,N), | |
| 631 | add_hyp(equal(X,0),Hyps,Hyps1), | |
| 632 | rewrite(X,N,Goal,GoalN), | |
| 633 | add_hyps([member(N,natural_set),GoalN],Hyps,Hyps2), | |
| 634 | rewrite(X,add(N,1),Goal,GoalN1). | |
| 635 | trans_with_args_info(induc_nat_compl(X),state(sequent(Hyps,Goal,Cont),Info), | |
| 636 | state(sequent(Hyps,member(X,natural_set),sequent(Hyps,Goal0,sequent(Hyps2,GoalN,Cont))),Info)) :- | |
| 637 | free_identifiers(Goal,Ids), | |
| 638 | member(X,Ids), | |
| 639 | of_integer_type(X,Info), | |
| 640 | new_identifiers(Goal,2,[K,N]), | |
| 641 | rewrite(X,0,Goal,Goal0), | |
| 642 | rewrite(X,N,Goal,GoalN), | |
| 643 | rewrite(X,K,Goal,GoalK), | |
| 644 | add_hyps([member(N,natural_set),forall([K],conjunct(less_equal(0,K),less(K,N)),GoalK)],Hyps,Hyps2). | |
| 645 | ||
| 646 | ||
| 647 | /* | |
| 648 | sequent_prover_trans(auto_simplify,state(Sequent,Info),state(NewSequent,Info)) :- | |
| 649 | apply_simp_rules(Sequent,Info,NewSequent), | |
| 650 | Sequent \= NewSequent. | |
| 651 | ||
| 652 | apply_simp_rules(Sequent,Info,Res) :- | |
| 653 | ( sequent_prover_trans_desc(simplify_goal(Rule),state(Sequent,Info),state(NewSequent,Info),_) | |
| 654 | ; sequent_prover_trans_desc(simplify_hyp(Rule,_),state(Sequent,Info),state(NewSequent,Info),_)), | |
| 655 | trivial_rule(Rule), !, | |
| 656 | apply_simp_rules(NewSequent,Info,Res). | |
| 657 | % apply_simp_rules(sequent(Hyps,Goal,Cont),_,Cont) :- axiom(Rule,Hyps,Goal), !. | |
| 658 | apply_simp_rules(Sequent,_,Sequent). | |
| 659 | ||
| 660 | trivial_rule(Rule) :- sub_atom(Rule,_,_,_,'MULTI'). | |
| 661 | trivial_rule(Rule) :- sub_atom(Rule,_,_,_,'SPECIAL'). | |
| 662 | trivial_rule(Rule) :- sub_atom(Rule,_,_,_,'TYPE'). | |
| 663 | trivial_rule('Evaluate tautology'). | |
| 664 | ||
| 665 | */ | |
| 666 | ||
| 667 | symb_trans(Rule,state(Sequent,StateInfo),state(NewSequent,StateInfo),[]) :- symb_trans_rule(Rule,Sequent,NewSequent,StateInfo). | |
| 668 | symb_trans(Rule,state(Sequent,StateInfo),state(NewSequent,StateInfo),TransInfo) :- symb_trans_rule(Rule,Sequent,NewSequent,StateInfo,TransInfo). | |
| 669 | symb_trans_enabled(Rule,state(Sequent,_)) :- symb_trans_enabled(Rule,Sequent). | |
| 670 | ||
| 671 | symb_trans_rule(add_hyp(Hyp),sequent(Hyps0,Goal,Cont),NewSequent,Info,[description(Desc)]) :- % CUT | |
| 672 | parse_input(Hyp,add_hyp,TExpr), | |
| 673 | normalize_predicate(TExpr,NormExpr), | |
| 674 | get_wd_pos(NormExpr,Hyps0,Info,POs), | |
| 675 | add_hyps(POs,Hyps0,Hyps1), | |
| 676 | translate_finite_expr(NormExpr,NewExpr), | |
| 677 | add_hyps([NewExpr|POs],Hyps0,Hyps2), | |
| 678 | add_wd_pos(Hyps0,POs,sequent(Hyps1,NewExpr,sequent(Hyps2,Goal,Cont)),NewSequent), | |
| 679 | translate_norm_expr_term(NormExpr,PrettyExpr), | |
| 680 | ajoin(['add hypothesis: \'',PrettyExpr,'\''],Desc). | |
| 681 | trans_prop(add_hyp,param_names(['Hyp'])). | |
| 682 | symb_trans_enabled(add_hyp,sequent(_,_,_)). | |
| 683 | ||
| 684 | symb_trans_rule(distinct_case(Pred),sequent(Hyps0,Goal,Cont),NewSequent,Info) :- | |
| 685 | parse_input(Pred,distinct_case,TExpr), | |
| 686 | normalize_predicate(TExpr,NormExpr), | |
| 687 | get_wd_pos(NormExpr,Hyps0,Info,POs), | |
| 688 | translate_finite_expr(NormExpr,NewExpr), | |
| 689 | add_hyps([NewExpr|POs],Hyps0,Hyps1), | |
| 690 | add_hyps([negation(NewExpr)|POs],Hyps0,Hyps2), | |
| 691 | add_wd_pos(Hyps0,POs,sequent(Hyps1,Goal,sequent(Hyps2,Goal,Cont)),NewSequent). | |
| 692 | trans_prop(distinct_case,param_names(['Pred'])). | |
| 693 | symb_trans_enabled(distinct_case,sequent(_,_,_)). | |
| 694 | ||
| 695 | symb_trans_rule(exists_inst(Inst),sequent(Hyps,exists([X|Ids],Pred),Cont),NewSequent,Info) :- | |
| 696 | parse_input(Inst,exists_inst,TExpr), | |
| 697 | normalize_expression(TExpr,NormExpr), | |
| 698 | rewrite(X,NormExpr,Pred,Goal1), | |
| 699 | (Ids = [] -> Goal = Goal1 ; Goal = exists(Ids,Goal1)), | |
| 700 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 701 | add_wd_pos(Hyps,POs,sequent(Hyps,Goal,Cont),NewSequent). | |
| 702 | trans_prop(exists_inst,param_names(['Inst'])). | |
| 703 | symb_trans_enabled(exists_inst,sequent(_,exists(_,_),_)). | |
| 704 | ||
| 705 | symb_trans_rule(forall_inst(HypNr,Inst),sequent(Hyps,Goal,Cont),NewSequent,Info,[description(Desc)]) :- | |
| 706 | get_hyp(Hyps,HypNr,SelHyp), | |
| 707 | SelHyp = forall([X|Ids],P,Q), % TODO: is this compatible with Rodin? | |
| 708 | parse_input(Inst,forall_inst,TExpr), | |
| 709 | normalize_expression(TExpr,NormExpr), | |
| 710 | select(SelHyp,Hyps,NewHyp,NewHyps), | |
| 711 | rewrite(X,NormExpr,P,P1), | |
| 712 | rewrite(X,NormExpr,Q,Q1), | |
| 713 | (Ids = [] -> NewHyp = implication(P1,Q1) ; NewHyp = forall(Ids,P1,Q1)), | |
| 714 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 715 | add_wd_pos(Hyps,POs,sequent(NewHyps,Goal,Cont),NewSequent), | |
| 716 | translate_norm_expr_term(NormExpr,PrettyExpr), | |
| 717 | X='$'(XName), | |
| 718 | ajoin(['\x2200\ instantiation in hyp ',HypNr,' for ID ',XName,': \'',PrettyExpr,'\''],Desc). | |
| 719 | trans_prop(forall_inst,param_names(['HypNr','Inst'])). | |
| 720 | symb_trans_enabled(forall_inst(HypNr,none),sequent(Hyps,_,_)) :- nth1(HypNr,Hyps,forall(_,_,_)). | |
| 721 | ||
| 722 | symb_trans_rule(forall_inst_mp(HypNr,Inst),sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 723 | get_hyp(Hyps,HypNr,SelHyp), | |
| 724 | SelHyp = forall([X],P,Q), | |
| 725 | parse_input(Inst,forall_inst_mp,TExpr), | |
| 726 | normalize_expression(TExpr,NormExpr), | |
| 727 | rewrite(X,NormExpr,P,P1), | |
| 728 | rewrite(X,NormExpr,Q,Q1), | |
| 729 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 730 | select(SelHyp,Hyps,Hyps0), | |
| 731 | add_hyps(POs,Hyps0,Hyps1), | |
| 732 | add_hyps([Q1|POs],Hyps0,Hyps2), | |
| 733 | add_wd_pos(Hyps,POs,sequent(Hyps1,P1,sequent(Hyps2,Goal,Cont)),NewSequent). | |
| 734 | trans_prop(forall_inst_mp,param_names(['HypNr','Inst'])). | |
| 735 | symb_trans_enabled(forall_inst_mp,sequent(Hyps,_,_)) :- memberchk(forall([_],_,_),Hyps). | |
| 736 | ||
| 737 | symb_trans_rule(forall_inst_mt(HypNr,Inst),sequent(Hyps,Goal,Cont),NewSequent,Info) :- | |
| 738 | get_hyp(Hyps,HypNr,SelHyp), | |
| 739 | SelHyp = forall([X],P,Q), | |
| 740 | parse_input(Inst,forall_inst_mt,TExpr), | |
| 741 | normalize_expression(TExpr,NormExpr), | |
| 742 | rewrite(X,NormExpr,negation(P),P1), | |
| 743 | rewrite(X,NormExpr,negation(Q),Q1), | |
| 744 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 745 | select(SelHyp,Hyps,Hyps0), | |
| 746 | add_hyps(POs,Hyps0,Hyps1), | |
| 747 | add_hyps([P1|POs],Hyps0,Hyps2), | |
| 748 | add_wd_pos(Hyps,POs,sequent(Hyps1,Q1,sequent(Hyps2,Goal,Cont)),NewSequent). | |
| 749 | trans_prop(forall_inst_mt,param_names(['HypNr','Inst'])). | |
| 750 | symb_trans_enabled(forall_inst_mt,sequent(Hyps,_,_)) :- memberchk(forall([_],_,_),Hyps). | |
| 751 | ||
| 752 | :- use_module(probsrc(b_ast_cleanup),[clean_up_pred_or_expr/3]). | |
| 753 | symb_trans_rule(Command,sequent(Hyps,Goal,Cont),Cont,_) :- use_prover(Command,Hyps,Goal). | |
| 754 | ||
| 755 | use_prover(Command,Hyps,Goal) :- | |
| 756 | prover_command(Command,ProverList), | |
| 757 | get_typed_ast(Goal,TGoal), | |
| 758 | maplist(get_typed_ast,Hyps,THyps), | |
| 759 | maplist(clean_up_pred_or_expr(_NonGroundExceptions1),THyps,CleanTHyps), | |
| 760 | clean_up_pred_or_expr(_NonGroundExceptions2,TGoal,CleanTGoal), % TODO: exceptions | |
| 761 | (bsyntaxtree:is_truth(CleanTGoal) | |
| 762 | -> true % if ast_cleanup gives a true goal, we don't have to call a prover | |
| 763 | ; prove_sequent(ProverList,CleanTHyps,CleanTGoal) | |
| 764 | ). | |
| 765 | prove_sequent(prob_wd_prover,THyps,TGoal) :- !, | |
| 766 | well_def_analyser:prove_sequent(proving,TGoal,THyps). | |
| 767 | prove_sequent(ProverList,THyps,TGoal) :- | |
| 768 | atelierb_provers_interface:prove_predicate_with_provers(ProverList,THyps,TGoal,proved). | |
| 769 | prover_command(ml_pp,[ml,pp]). | |
| 770 | prover_command(ml,[ml]). | |
| 771 | prover_command(pp,[pp]). | |
| 772 | prover_command(prob_wd_prover,prob_wd_prover). | |
| 773 | trans_prop(Cmd,param_names([])) :- prover_command(Cmd,_). | |
| 774 | symb_trans_enabled(Cmd,sequent(_,_,_)) :- prover_command(Cmd,_). | |
| 775 | ||
| 776 | symb_trans_rule(prob_disprover,sequent(Hyps,Goal,Cont),NewState,Info) :- | |
| 777 | convert_norm_expr_to_raw(Goal,RawGoal), | |
| 778 | maplist(convert_norm_expr_to_raw,Hyps,RawHyps), | |
| 779 | AllHyps = RawHyps, SelectedHyps = RawHyps, Timeout = 1000, | |
| 780 | % TO DO: pass information about top-level types, new deferred sets, ... | |
| 781 | disprover:disprove(RawGoal,AllHyps,SelectedHyps,Timeout,OutResult), | |
| 782 | format(user_output,'ProB Disprover Result = ~w (Info=~w)~n',[OutResult,Info]), | |
| 783 | dispatch_result(OutResult,Cont,NewState). | |
| 784 | trans_prop(prob_disprover,param_names([])). | |
| 785 | symb_trans_enabled(prob_disprover,sequent(_,_,_)). | |
| 786 | ||
| 787 | symb_trans_rule(z3,sequent(Hyps,Goal,Cont),NewState,Info) :- | |
| 788 | (Hyps = [] -> ConjHyps=truth | |
| 789 | ; list_to_op(Hyps,ConjHyps,conjunct)), | |
| 790 | convert_norm_expr_to_raw(conjunct(ConjHyps,negation(Goal)),Ast), | |
| 791 | bmachine:b_type_check_raw_expr(Ast,[],Typed,open(no_quantifier)), | |
| 792 | smt_solvers_interface:smt_solve_predicate(z3,Typed,_,Res), | |
| 793 | format(user_output,'z3 Result = ~w (Info=~w)~n',[Res,Info]), | |
| 794 | dispatch_result(Res,Cont,NewState). | |
| 795 | trans_prop(z3,param_names([])). | |
| 796 | symb_trans_enabled(z3,sequent(_,_,_)). | |
| 797 | ||
| 798 | dispatch_result(contradiction_found,Cont,Cont). | |
| 799 | dispatch_result(contradiction_in_hypotheses,Cont,Cont). | |
| 800 | dispatch_result(solution_on_selected_hypotheses(S),_,counter_example(S)). | |
| 801 | dispatch_result(solution(S),_,counter_example(S)). | |
| 802 | % other results are no_solution_found(_) and time_out | |
| 803 | ||
| 804 | symb_trans_rule(rewrite_hyp(HypNr,NewHyp),sequent(Hyps,Goal,Cont),sequent(NewHyps,Goal,Cont),Info) :- | |
| 805 | get_hyp(Hyps,HypNr,SelHyp), | |
| 806 | parse_input(NewHyp,rewrite_hyp,TExpr), | |
| 807 | b_interpreter_check:norm_pred_check(TExpr,RewrittenHyp), | |
| 808 | select(SelHyp,Hyps,Hyps0), | |
| 809 | get_wd_pos(RewrittenHyp,Hyps,Info,[]), | |
| 810 | prove_predicate([SelHyp],RewrittenHyp), | |
| 811 | translate_finite_expr(RewrittenHyp,NewExpr), | |
| 812 | add_hyp(NewExpr,Hyps0,NewHyps). | |
| 813 | trans_prop(rewrite_hyp,param_names(['HypNr','NewHyp'])). | |
| 814 | symb_trans_enabled(rewrite_hyp,sequent(_,_,_)). | |
| 815 | ||
| 816 | :- use_module(probsrc(tools),[split_atom/3]). | |
| 817 | symb_trans_rule(derive_hyp(HypNrs,NewHyp),sequent(Hyps,Goal,Cont),sequent(NewHyps,Goal,Cont),Info) :- | |
| 818 | ground(HypNrs), | |
| 819 | split_atom(HypNrs,[','],Indices), | |
| 820 | maplist(get_hyp(Hyps),Indices,SelHyps), | |
| 821 | parse_input(NewHyp,derive_hyp,TExpr), | |
| 822 | b_interpreter_check:norm_pred_check(TExpr,NormExpr), | |
| 823 | get_wd_pos(NormExpr,Hyps,Info,[]), | |
| 824 | prove_predicate(SelHyps,NormExpr), | |
| 825 | translate_finite_expr(NormExpr,NewExpr), | |
| 826 | add_hyp(NewExpr,Hyps,NewHyps). | |
| 827 | trans_prop(derive_hyp,param_names(['HypNrs','NewHyp'])). | |
| 828 | symb_trans_enabled(derive_hyp,sequent(_,_,_)). | |
| 829 | ||
| 830 | symb_trans_rule(dis_binter_r(PFun),sequent(Hyps,Goal,Cont),sequent(Hyps,NormExpr,sequent(Hyps,NewGoal,Cont)),Info) :- | |
| 831 | parse_input(PFun,dis_binter_r,TExpr), | |
| 832 | normalize_predicate(TExpr,NormExpr), | |
| 833 | NormExpr = member(reverse(F),partial_function(A,B)), | |
| 834 | type_expression(A,Info), | |
| 835 | type_expression(B,Info), | |
| 836 | Sub = image(F,Inter), | |
| 837 | Inter = intersection(_,_), | |
| 838 | is_subterm(Sub,Goal), | |
| 839 | image_intersection(F,Inter,NewSub), | |
| 840 | rewrite_once(Sub,NewSub,Goal,NewGoal). | |
| 841 | trans_prop(dis_binter_r,param_names(['PFun'])). | |
| 842 | symb_trans_enabled(dis_binter_r,sequent(_,Goal,_)) :- is_subterm(image(_,Inter),Goal), Inter = intersection(_,_). | |
| 843 | ||
| 844 | symb_trans_rule(dis_binter_l(PFun),sequent(Hyps,Goal,Cont),sequent(Hyps0,NormExpr,sequent(Hyps1,Goal,Cont)),Info) :- | |
| 845 | parse_input(PFun,dis_binter_l,TExpr), | |
| 846 | normalize_predicate(TExpr,NormExpr), | |
| 847 | NormExpr = member(reverse(F),partial_function(A,B)), | |
| 848 | type_expression(A,Info), | |
| 849 | type_expression(B,Info), | |
| 850 | select(Hyp,Hyps,Hyps0), | |
| 851 | Sub = image(F,Inter), | |
| 852 | Inter = intersection(_,_), | |
| 853 | is_subterm(Sub,Hyp), | |
| 854 | Inter = intersection(_,_), | |
| 855 | image_intersection(F,Inter,NewSub), | |
| 856 | rewrite(Sub,NewSub,Hyp,NewHyp), | |
| 857 | add_hyp(NewHyp,Hyps0,Hyps1). | |
| 858 | trans_prop(dis_binter_l,param_names(['PFun'])). | |
| 859 | symb_trans_enabled(dis_binter_l,sequent(Hyps,_,_)) :- member(Hyp,Hyps), is_subterm(image(_,Inter),Hyp), Inter = intersection(_,_). | |
| 860 | ||
| 861 | symb_trans_rule(dis_setminus_r(PFun),sequent(Hyps,Goal,Cont),sequent(Hyps,NormExpr,sequent(Hyps,NewGoal,Cont)),Info) :- | |
| 862 | parse_input(PFun,dis_setminus_r,TExpr), | |
| 863 | normalize_predicate(TExpr,NormExpr), | |
| 864 | NormExpr = member(reverse(F),partial_function(A,B)), | |
| 865 | type_expression(A,Info), | |
| 866 | type_expression(B,Info), | |
| 867 | rewrite(image(F,set_subtraction(S,T)),set_subtraction(image(F,S),image(F,T)),Goal,NewGoal). | |
| 868 | trans_prop(dis_setminus_r,param_names(['PFun'])). | |
| 869 | symb_trans_enabled(dis_setminus_r,sequent(_,Goal,_)) :- is_subterm(image(_,set_subtraction(_,_)),Goal). | |
| 870 | ||
| 871 | symb_trans_rule(dis_setminus_l(PFun),sequent(Hyps,Goal,Cont),sequent(Hyps0,NormExpr,sequent(Hyps1,Goal,Cont)),Info) :- | |
| 872 | parse_input(PFun,dis_setminus_l,TExpr), | |
| 873 | normalize_predicate(TExpr,NormExpr), !, | |
| 874 | NormExpr = member(reverse(F),partial_function(A,B)), | |
| 875 | type_expression(A,Info), | |
| 876 | type_expression(B,Info), | |
| 877 | select(Hyp,Hyps,Hyps0), | |
| 878 | is_subterm(image(_,set_subtraction(_,_)),Hyp), | |
| 879 | rewrite(image(F,set_subtraction(S,T)),set_subtraction(image(F,S),image(F,T)),Hyp,NewHyp), | |
| 880 | add_hyp(NewHyp,Hyps0,Hyps1). | |
| 881 | trans_prop(dis_setminus_l,param_names(['PFun'])). | |
| 882 | symb_trans_enabled(dis_setminus_l,sequent(Hyps,_,_)) :- member(Hyp,Hyps), is_subterm(image(_,set_subtraction(_,_)),Hyp). | |
| 883 | ||
| 884 | symb_trans_rule(fin_subseteq_r(Set),sequent(Hyps,finite(S),Cont),NewSequent,Info) :- | |
| 885 | parse_input(Set,fin_subseteq_r,TExpr), | |
| 886 | normalize_expression(TExpr,NormExpr), | |
| 887 | get_meta_info(ids_types,Info,IdsTypes), % NormExpr has to be a set | |
| 888 | same_type(S,NormExpr,IdsTypes), | |
| 889 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 890 | add_wd_pos(Hyps,POs,sequent(Hyps,subset(S,NormExpr),sequent(Hyps,finite(NormExpr),Cont)),NewSequent). | |
| 891 | trans_prop(fin_subseteq_r,param_names(['Set'])). | |
| 892 | symb_trans_enabled(fin_subseteq_r,sequent(_,finite(_),_)). | |
| 893 | ||
| 894 | symb_trans_rule(fin_fun1_r(PFun),sequent(Hyps,finite(F),Cont),NewSequent,Info) :- | |
| 895 | parse_input(PFun,fin_fun1_r,TExpr), | |
| 896 | normalize_expression(TExpr,NormExpr), | |
| 897 | NormExpr = partial_function(S,T), | |
| 898 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 899 | add_wd_pos(Hyps,POs,sequent(Hyps,member(F,partial_function(S,T)),sequent(Hyps,finite(S),Cont)),NewSequent). | |
| 900 | trans_prop(fin_fun1_r,param_names(['PFun'])). | |
| 901 | symb_trans_enabled(fin_fun1_r,sequent(_,finite(_),_)). | |
| 902 | ||
| 903 | symb_trans_rule(fin_fun2_r(PFun),sequent(Hyps,finite(F),Cont),NewSequent,Info) :- | |
| 904 | parse_input(PFun,fin_fun2_r,TExpr), | |
| 905 | normalize_expression(TExpr,NormExpr), | |
| 906 | NormExpr = partial_function(S,T), | |
| 907 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 908 | add_wd_pos(Hyps,POs,sequent(Hyps,member(reverse(F),partial_function(S,T)),sequent(Hyps,finite(S),Cont)),NewSequent). | |
| 909 | trans_prop(fin_fun2_r,param_names(['PFun'])). | |
| 910 | symb_trans_enabled(fin_fun2_r,sequent(_,finite(_),_)). | |
| 911 | ||
| 912 | symb_trans_rule(fin_fun_img_r(PFun),sequent(Hyps,finite(image(F,Set)),Cont),NewSequent,Info) :- | |
| 913 | parse_input(PFun,fin_fun_img_r,TExpr), | |
| 914 | normalize_expression(TExpr,NormExpr), | |
| 915 | NormExpr = partial_function(S,T), | |
| 916 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 917 | add_wd_pos(Hyps,POs,sequent(Hyps,member(F,partial_function(S,T)),sequent(Hyps,finite(Set),Cont)),NewSequent). | |
| 918 | trans_prop(fin_fun_img_r,param_names(['PFun'])). | |
| 919 | symb_trans_enabled(fin_fun_img_r,sequent(_,finite(image(_,_)),_)). | |
| 920 | ||
| 921 | symb_trans_rule(fin_fun_ran_r(PFun),sequent(Hyps,finite(range(F)),Cont),NewSequent,Info) :- | |
| 922 | parse_input(PFun,fin_fun_ran_r,TExpr), | |
| 923 | normalize_expression(TExpr,NormExpr), | |
| 924 | NormExpr = partial_function(S,T), | |
| 925 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 926 | add_wd_pos(Hyps,POs,sequent(Hyps,member(F,partial_function(S,T)),sequent(Hyps,finite(S),Cont)),NewSequent). | |
| 927 | trans_prop(fin_fun_ran_r,param_names(['PFun'])). | |
| 928 | symb_trans_enabled(fin_fun_ran_r,sequent(_,finite(range(_)),_)). | |
| 929 | ||
| 930 | symb_trans_rule(fin_fun_dom_r(PFun),sequent(Hyps,finite(domain(F)),Cont),NewSequent,Info) :- | |
| 931 | parse_input(PFun,fin_fun_dom_r,TExpr), | |
| 932 | normalize_expression(TExpr,NormExpr), | |
| 933 | NormExpr = partial_function(S,T), | |
| 934 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 935 | add_wd_pos(Hyps,POs,sequent(Hyps,member(reverse(F),partial_function(S,T)),sequent(Hyps,finite(S),Cont)),NewSequent). | |
| 936 | trans_prop(fin_fun_dom_r,param_names(['PFun'])). | |
| 937 | symb_trans_enabled(fin_fun_dom_r,sequent(_,finite(domain(_)),_)). | |
| 938 | ||
| 939 | symb_trans_rule(fin_rel_r(Rel),sequent(Hyps,finite(R),Cont),NewSequent,Info) :- | |
| 940 | parse_input(Rel,fin_rel_r,TExpr), | |
| 941 | normalize_expression(TExpr,NormExpr), !, | |
| 942 | NormExpr = relations(S,T), | |
| 943 | get_wd_pos_of_expr(NormExpr,Hyps,Info,POs), | |
| 944 | add_wd_pos(Hyps,POs,sequent(Hyps,member(R,relations(S,T)),sequent(Hyps,finite(S),sequent(Hyps,finite(T),Cont))),NewSequent). | |
| 945 | trans_prop(fin_rel_r,param_names(['Rel'])). | |
| 946 | symb_trans_enabled(fin_rel_r,sequent(_,finite(_),_)). | |
| 947 | ||
| 948 | parse_input(Param,Res) :- parse_input(Param,'?',Res). | |
| 949 | parse_input(Param,Context,Res) :- | |
| 950 | ground(Param), | |
| 951 | (number(Param) -> number_codes(Param,CParam) | |
| 952 | ; Param = [Nr|_], number(Nr) -> CParam = Param % already codes list | |
| 953 | ; atom(Param) -> atom_codes(Param,CParam) | |
| 954 | ; ajoin(['Illegal input to proof rule ',Context,' (must be Prolog atom or string):'],Msg), | |
| 955 | add_error(sequent_prover,Msg,Param), fail | |
| 956 | ), | |
| 957 | bmachine:b_parse_only(formula,CParam,Parsed,_,_Error), | |
| 958 | transform_raw(Parsed,TExpr), | |
| 959 | adapt_for_eventb(TExpr,Res). | |
| 960 | ||
| 961 | adapt_for_eventb(Term,Res) :- atomic(Term), !, Res=Term. | |
| 962 | adapt_for_eventb(Term,Result) :- | |
| 963 | Term=..[F|Args], | |
| 964 | replace_functor(F,NewFunctor), | |
| 965 | maplist(adapt_for_eventb,Args,NewArgs), | |
| 966 | Result=..[NewFunctor|NewArgs]. | |
| 967 | ||
| 968 | replace_functor(F,NF) :- | |
| 969 | replace_functor_eventb(F,EF), !, NF=EF. | |
| 970 | replace_functor(F,F). | |
| 971 | ||
| 972 | replace_functor_eventb(concat,power_of). | |
| 973 | replace_functor_eventb(power_of,cartesian_product). | |
| 974 | replace_functor_eventb(minus_or_set_subtract,minus). | |
| 975 | replace_functor_eventb(mult_or_cart,multiplication). | |
| 976 | ||
| 977 | translate_finite_expr(X,Y) :- rewrite(member(S,fin_subset(S)),finite(S),X,Y). | |
| 978 | ||
| 979 | get_hyp(Hyps,Nr,Hyp) :- | |
| 980 | number(Nr), | |
| 981 | nth1(Nr,Hyps,Hyp). | |
| 982 | ||
| 983 | add_hyp(Hyp,Hyps0,NewHyps) :- append(Hyps0,[Hyp],Hyps1), without_duplicates(Hyps1,NewHyps). | |
| 984 | add_hyps(Hyp1,Hyp2,Hyps0,NewHyps) :- append(Hyps0,[Hyp1,Hyp2],Hyps1), without_duplicates(Hyps1,NewHyps). | |
| 985 | add_hyps(NewHyps,Hyps,SHyps) :- append(Hyps,NewHyps,All), without_duplicates(All,SHyps). | |
| 986 | ||
| 987 | % select and remove a conjunct: | |
| 988 | select_conjunct(X,conjunct(A,B),Rest) :- !, | |
| 989 | (select_conjunct(X,A,RA), conjoin(RA,B,Rest) | |
| 990 | ; | |
| 991 | select_conjunct(X,B,RB), conjoin(A,RB,Rest)). | |
| 992 | select_conjunct(X,X,truth). | |
| 993 | ||
| 994 | conjoin(truth,X,R) :- !, R=X. | |
| 995 | conjoin(X,truth,R) :- !, R=X. | |
| 996 | conjoin(X,Y,conjunct(X,Y)). | |
| 997 | ||
| 998 | ||
| 999 | ||
| 1000 | ||
| 1001 | % axioms: proof rules without antecedent, discharging goal directly | |
| 1002 | axiom(hyp,Hyps,Goal) :- member_hyps(Goal,Hyps). | |
| 1003 | axiom(hyp,Hyps,member(X,Nat)) :- | |
| 1004 | is_natural_set(Nat), | |
| 1005 | (member_hyps(greater_equal(X,0),Hyps) ; member_hyps(greater_equal(X,1),Hyps)). | |
| 1006 | axiom(hyp_or,Hyps,Goal) :- | |
| 1007 | member_of_bin_op(disjunct,P,Goal), % TODO: will not select a disjunction for P | |
| 1008 | member_hyps(P,Hyps). | |
| 1009 | axiom(false_hyp,Hyps,_Goal) :- member_hyps(falsity,Hyps). | |
| 1010 | axiom(true_goal,_,truth). | |
| 1011 | axiom(Rule,_Hyps,Goal) :- axiom_wo_hyps(Goal,Rule). | |
| 1012 | axiom(cntr,Hyps,_) :- | |
| 1013 | member(P,Hyps), | |
| 1014 | (NotP = negation(P) ; negate(P,NotP)), | |
| 1015 | select(P,Hyps,Hyps0), | |
| 1016 | member_hyps(NotP,Hyps0). | |
| 1017 | axiom(fin_rel,Hyps,finite(Fun)) :- | |
| 1018 | member_hyps(member(Fun,FunType),Hyps), | |
| 1019 | is_rel(FunType,_,Dom,Ran), | |
| 1020 | member_hyps(finite(Dom),Hyps), | |
| 1021 | member_hyps(finite(Ran),Hyps). | |
| 1022 | axiom(fin_l_lower_bound,Hyps,exists([N],forall([X],member(X,S),LessEq))) :- | |
| 1023 | member_hyps(finite(S),Hyps), | |
| 1024 | is_less_eq(LessEq,N,X). | |
| 1025 | axiom(fin_l_upper_bound,Hyps,exists([N],forall([X],member(X,S),LessEq))) :- | |
| 1026 | member_hyps(finite(S),Hyps), | |
| 1027 | is_less_eq(LessEq,X,N). | |
| 1028 | axiom(derive_goal,Hyps,Goal) :- derive_goal(Hyps,Goal), \+ is_true(Goal), \+ axiom(hyp,Hyps,Goal). | |
| 1029 | ||
| 1030 | % from chapter 2, "Modeling in Event-B" | |
| 1031 | axiom(p2,Hyps,member(Add,Nat)) :- | |
| 1032 | is_natural_set(Nat), | |
| 1033 | member(member(N,Nat),Hyps), | |
| 1034 | equal_terms(Add,add(N,1)). | |
| 1035 | axiom(p2_,Hyps,member(Sub,Nat)) :- | |
| 1036 | is_natural_set(Nat), | |
| 1037 | member(L,Hyps), | |
| 1038 | is_less(L,0,N), | |
| 1039 | equal_terms(Sub,minus(N,1)). | |
| 1040 | axiom(inc,Hyps,Goal) :- | |
| 1041 | member(L,Hyps), | |
| 1042 | is_less(L,N,M), | |
| 1043 | equal_terms(Goal,less_equal(add(N,1),M)). | |
| 1044 | axiom(dec,Hyps,Goal) :- | |
| 1045 | member(L,Hyps), | |
| 1046 | is_less_eq(L,N,M), | |
| 1047 | equal_terms(Goal,less(minus(N,1),M)). | |
| 1048 | ||
| 1049 | axiom_with_info(fun_goal,Hyps,member(F,partial_function(Ty1,Ty2)),Info) :- | |
| 1050 | type_expression(Ty1,Info), | |
| 1051 | type_expression(Ty2,Info), | |
| 1052 | member_hyps(member(F,FType),Hyps), | |
| 1053 | is_fun(FType,_,_,_). | |
| 1054 | axiom_with_info(fun_goal_rec,Hyps,member(function(Fun,En),partial_function(Ty1,Ty2)),Info) :- | |
| 1055 | type_expression(Ty1,Info), | |
| 1056 | type_expression(Ty2,Info), | |
| 1057 | function_of(Fun,F), | |
| 1058 | member(member(F,FType),Hyps), | |
| 1059 | fun_goal_check(FType,function(Fun,En)). | |
| 1060 | ||
| 1061 | axiom_wo_hyps(true,true_goal). | |
| 1062 | axiom_wo_hyps(eq(E,E),eql). | |
| 1063 | ||
| 1064 | ||
| 1065 | % rules implemented MembershipGoal reasoner | |
| 1066 | % mb_goal(Rule,Hyp,Goal,Info). | |
| 1067 | mb_goal('SUBSET_SUBSETEQ',subset_strict(A,B),subset(A,B),_). | |
| 1068 | mb_goal('DOM_SUBSET',subset(A,B),subset(domain(A),domain(B)),_). | |
| 1069 | mb_goal('RAN_SUBSET',subset(A,B),subset(range(A),range(B)),_). | |
| 1070 | mb_goal('EQUAL_SUBSETEQ',Eq,subset(A,B),Info) :- | |
| 1071 | is_equality(Eq,A,B), | |
| 1072 | get_meta_info(ids_types,Info,IdsTypes), | |
| 1073 | check_type(A,B,IdsTypes,set(_)). | |
| 1074 | mb_goal('IN_DOM_CPROD',member(X,domain(cartesian_product(A,_))),member(X,A),_). | |
| 1075 | mb_goal('IN_RAN_CPROD',member(Y,range(cartesian_product(_,B))),member(Y,B),_). | |
| 1076 | mb_goal('IN_DOM_REL',member(couple(X,_),F),member(X,domain(F)),_). | |
| 1077 | mb_goal('IN_RAN_REL',member(couple(_,Y),F),member(Y,range(F)),_). | |
| 1078 | mb_goal('SETENUM_SUBSET',subset(set_extension(L),A),member(X,A),_) :- member(X,L). | |
| 1079 | mb_goal('OVR_RIGHT_SUBSET',subset(LHS1,A),subset(LHS2,A),_) :- | |
| 1080 | op_to_list(LHS1,List1,overwrite), | |
| 1081 | op_to_list(LHS2,List2,overwrite), | |
| 1082 | append(L,List2,List1), | |
| 1083 | L \= []. | |
| 1084 | mb_goal('RELSET_SUBSET_CPROD',member(F,Rel),subset(F,cartesian_product(Dom,Ran)),_) :- is_rel(Rel,_,Dom,Ran). | |
| 1085 | ||
| 1086 | % mb_goal(Rule,Hyps,Goal). | |
| 1087 | mb_goal('DERIV_IN_SUBSET',Hyps,member(X,B)) :- member(member(X,A),Hyps), member(subset(A,B),Hyps). | |
| 1088 | ||
| 1089 | derive_goal(Hyps,Goal) :- | |
| 1090 | functor(Goal,F,2), | |
| 1091 | (comparison(F) ; F = member), | |
| 1092 | used_identifiers(Goal,GoalIds), | |
| 1093 | find_hyps_with(GoalIds,Hyps,SelectedHyps), | |
| 1094 | use_prover(prob_wd_prover,SelectedHyps,Goal). | |
| 1095 | ||
| 1096 | find_hyps_with(_,[],[]). | |
| 1097 | find_hyps_with(Ids,[Hyp|T],[Hyp|R]) :- | |
| 1098 | used_identifiers(Hyp,HypIds), | |
| 1099 | \+ list_intersection(Ids,HypIds,[]), !, | |
| 1100 | find_hyps_with(Ids,T,R). | |
| 1101 | find_hyps_with(Ids,[_|T],R) :- find_hyps_with(Ids,T,R). | |
| 1102 | ||
| 1103 | /* not used: | |
| 1104 | is_transitive(Hyps,Goal) :- | |
| 1105 | Goal=..[F,L,R], | |
| 1106 | comparison(F), | |
| 1107 | F \= not_equal, | |
| 1108 | is_transitive_aux(Hyps,F,L,R,[]). | |
| 1109 | ||
| 1110 | is_transitive_aux(Hyps,F,L,R,_) :- | |
| 1111 | Ex=..[F,L,R], | |
| 1112 | (member(Ex,Hyps) ; equiv(Ex,G2), member(G2,Hyps)). | |
| 1113 | is_transitive_aux(Hyps,F,L,R,Visited) :- | |
| 1114 | Ex=..[F,L,M], | |
| 1115 | (member(Ex,Hyps) ; equiv(Ex,G2), member(G2,Hyps)), | |
| 1116 | \+ member(M,Visited), | |
| 1117 | is_transitive_aux(Hyps,F,M,R,[L|Visited]). | |
| 1118 | ||
| 1119 | lower_bound(Hyps,B,X) :- member(L,Hyps), is_less_eq(L,B,X), number(B). | |
| 1120 | lower_bound(Hyps,B1,X) :- member(L,Hyps), is_less(L,B,X), number(B), B1 is B+1. | |
| 1121 | lower_bound(Hyps,B,X) :- member(Eq,Hyps), is_equality(Eq,B,X), number(B). | |
| 1122 | ||
| 1123 | upper_bound(Hyps,X,B) :- member(L,Hyps),is_less_eq(L,X,B), number(B). | |
| 1124 | upper_bound(Hyps,X,B1) :- member(L,Hyps), is_less(L,X,B), number(B), B1 is B-1. | |
| 1125 | upper_bound(Hyps,X,B) :- member(Eq,Hyps), is_equality(Eq,X,B), number(B). | |
| 1126 | */ | |
| 1127 | ||
| 1128 | ||
| 1129 | add_wd_pos(Hyps,POs,Sequent,NewSequent) :- | |
| 1130 | rodin_mode, !, | |
| 1131 | (POs=[] -> Conj=truth ; list_to_op(POs,Conj,conjunct)), | |
| 1132 | % Rodin requires true goal for empty list and conjunction of WD conditions | |
| 1133 | add_pos(Hyps,Sequent,NewSequent,[Conj]). | |
| 1134 | add_wd_pos(Hyps,POs,Sequent,NewSequent) :- | |
| 1135 | add_goals(Hyps,POs,Sequent,NewSequent). | |
| 1136 | ||
| 1137 | add_goals(Hyps,POs,Sequent,NewSequent) :- | |
| 1138 | reverse(POs,List), | |
| 1139 | add_pos(Hyps,Sequent,NewSequent,List). | |
| 1140 | ||
| 1141 | add_pos(_,Sequent,Sequent,[]) :- !. | |
| 1142 | add_pos(Hyps,InnerSequent,NewSequent,[PO|R]) :- add_pos(Hyps,sequent(Hyps,PO,InnerSequent),NewSequent,R). | |
| 1143 | ||
| 1144 | % add a sequent per disjunct | |
| 1145 | extract_disjuncts(Q,Hyps0,Goal,Cont,sequent(Hyps,Goal,Cont)) :- Q \= disjunct(_,_), add_hyp(Q,Hyps0,Hyps). | |
| 1146 | extract_disjuncts(disjunct(L,R),Hyps0,Goal,Cont,LRSequent) :- | |
| 1147 | extract_disjuncts(L,Hyps0,Goal,success(PO_Nr),LSequent), | |
| 1148 | extract_disjuncts(R,Hyps0,Goal,Cont,RSequent), | |
| 1149 | append_sequents(LSequent,RSequent,LRSequent,PO_Nr). | |
| 1150 | ||
| 1151 | % add sequents as last continuation | |
| 1152 | append_sequents(sequent(Hyps,Goal,Cont),InnerCont,sequent(Hyps,Goal,Sequent),PO_Nr) :- | |
| 1153 | (Cont = success(PO_Nr) -> Sequent = InnerCont | |
| 1154 | ; append_sequents(Cont,InnerCont,Sequent,PO_Nr)). | |
| 1155 | ||
| 1156 | animation_function_result(state(counter_example(_),_),[((1,1),'Counter example found.')]). | |
| 1157 | animation_function_result(state(success(Nr),_),[((1,1),Txt)]) :- | |
| 1158 | (get_po_description(Nr,PO) -> ajoin(['Proof of ',PO,' succeeded.'],Txt) | |
| 1159 | ; Txt = 'Proof succeeded.'). | |
| 1160 | animation_function_result(state(Sequent,_),Matrix) :- | |
| 1161 | Sequent = sequent(_,_,Cont), | |
| 1162 | cont_length(Cont,LCont), | |
| 1163 | findall(((RowNr,ColNr),Cell), (cell_content(RowNr,ColNr,Sequent,Cell,LCont)), Matrix). | |
| 1164 | ||
| 1165 | cell_content(Row,Col,Sequent,Cell,_) :- % Auto-Proof buttons | |
| 1166 | max_hyp_length(Sequent,0,LHyps), | |
| 1167 | member(Col,[1,2,3]),D is Col+1, | |
| 1168 | (Row is LHyps + 3, ajoin(['auto-',D],Cell) | |
| 1169 | ; Row is LHyps + 4, ajoin(['pure-',D],Cell)). | |
| 1170 | cell_content(RowNr,ColNr,Sequent,Cell,LCont) :- cell_content2(RowNr,ColNr,Sequent,Cell,LCont). | |
| 1171 | ||
| 1172 | max_hyp_length(sequent(Hyps,_,Cont),CurMax,Res) :- length(Hyps,Len),!, | |
| 1173 | (Len>CurMax -> max_hyp_length(Cont,Len,Res) ; max_hyp_length(Cont,CurMax,Res)). | |
| 1174 | max_hyp_length(_,Max,Max). | |
| 1175 | ||
| 1176 | cell_content2(Row,1,sequent(Hyps,_,_),Cell,_) :- nth1(Row,Hyps,RowHyp), translate_norm_expr_term(RowHyp,Cell). | |
| 1177 | cell_content2(Row,1,sequent(Hyps,_,_),'\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\\x2500\',_) :- | |
| 1178 | length(Hyps,LHyps), Row is LHyps + 1. | |
| 1179 | cell_content2(Row,1,sequent(Hyps,Goal,_),Cell,_) :- | |
| 1180 | length(Hyps,LHyps), Row is LHyps + 2, translate_norm_expr_term(Goal,Cell). | |
| 1181 | cell_content2(Row,Col,Sequent,Cell,LCont) :- | |
| 1182 | extract_continuations(Sequent,LCont,Cont,Col), | |
| 1183 | cell_content2(Row,1,Cont,Cell,LCont). | |
| 1184 | ||
| 1185 | extract_continuations(sequent(_,_,Cont),LCont,Cont,ColNr) :- | |
| 1186 | cont_length(Cont,ActualLCont), | |
| 1187 | ColNr is LCont - ActualLCont + 2. | |
| 1188 | extract_continuations(sequent(_,_,Cont),LCont,FoundCont,ColNr) :- | |
| 1189 | extract_continuations(Cont,LCont,FoundCont,ColNr). | |
| 1190 | ||
| 1191 | get_continuations(success(_),[]). | |
| 1192 | get_continuations(sequent(_,_,Cont),Conts) :- % ignore current sequent | |
| 1193 | get_continuations2(Cont,Conts). | |
| 1194 | get_continuations2(success(_),[]). | |
| 1195 | get_continuations2(sequent(Hyps,Goal,NxtCont),[sequent(Hyps,Goal)|CT]) :- | |
| 1196 | get_continuations2(NxtCont,CT). | |
| 1197 | ||
| 1198 | find_transitions(Sequent,Info,Trans) :- | |
| 1199 | findall(T,( sequent_prover_trans(T,state(Sequent,Info),_) | |
| 1200 | ; sequent_prover_trans_desc(T,state(Sequent,Info),_,_)),TransL), | |
| 1201 | remove_dups(TransL,Trans). | |
| 1202 | ||
| 1203 | % animation_image_right_click_transition(RowX,ColY,OperationTemplate,State) | |
| 1204 | animation_image_right_click_transition(Row,1,Trans,state(sequent(Hyps,Goal,Cont),Info)) :- nth1(Row,Hyps,Hyp), | |
| 1205 | select(Hyp,Hyps,Hyps0), | |
| 1206 | find_transitions(sequent(Hyps,Goal,Cont),Info,AllTransitions), | |
| 1207 | find_transitions(sequent(Hyps0,Goal,Cont),Info,Transitions0), | |
| 1208 | member(Trans,AllTransitions), | |
| 1209 | Trans \= mon_deselect(_), | |
| 1210 | \+ member(Trans,Transitions0). | |
| 1211 | animation_image_right_click_transition(Row,1,Trans,state(sequent(Hyps,Goal,Cont),Info)) :- | |
| 1212 | length(Hyps,LHyps), | |
| 1213 | Row is LHyps + 2, % click on goal | |
| 1214 | find_transitions(sequent([],Goal,Cont),Info,Transitions), | |
| 1215 | member(Trans,Transitions), | |
| 1216 | Trans \= reselect_hyp(_). | |
| 1217 | animation_image_right_click_transition(Row,_C,Proof,state(sequent(Hyps,Goal,_),Info)) :- | |
| 1218 | length(Hyps,LHyps), Row is LHyps + 1, % click on divider line | |
| 1219 | (bounded_find_proof(sequent(Hyps,Goal,success(0)),Info,3,[],Proof) -> true ; Proof = 'NO AUTO-PROOF-FOUND'). | |
| 1220 | animation_image_right_click_transition(Row,Col,Proof,state(sequent(Hyps,Goal,_),Info)) :- | |
| 1221 | length(Hyps,LHyps), Row > LHyps + 2, % click on Auto-Proof buttons below goal | |
| 1222 | Depth is Col+1, | |
| 1223 | Opts = [use_eager_simplification|TOpts], | |
| 1224 | (Row =:= LHyps+3 -> TOpts = [] ; TOpts = [disregard_rule(derive_goal)]), | |
| 1225 | (bounded_find_proof(sequent(Hyps,Goal,success(0)),Info,Depth,Opts,Proof) -> true ; Proof = 'NO AUTO-PROOF-FOUND'). | |
| 1226 | ||
| 1227 | % animation_image_right_click_transition(X,Y,OperationTemplate) | |
| 1228 | animation_image_right_click_transition(Row,1,mon_deselect(Row)). | |
| 1229 | ||
| 1230 | % ------------------------ | |
| 1231 | ||
| 1232 | ||
| 1233 | ||
| 1234 | ||
| 1235 | function_of(F,F) :- F \= function(_,_). | |
| 1236 | function_of(function(Fun,_),F) :- function_of(Fun,F). | |
| 1237 | ||
| 1238 | fun_goal_check(Fun,F) :- | |
| 1239 | F \= function(_,_), | |
| 1240 | is_fun(Fun,_,_,_). | |
| 1241 | fun_goal_check(Rel,function(F,_)) :- | |
| 1242 | is_rel(Rel,_,_,Ran), | |
| 1243 | fun_goal_check(Ran,F). | |
| 1244 | ||
| 1245 | ||
| 1246 | rewrite_once(X,Y,E,NewE) :- is_subterm(X,E), rewrite_once2(X,Y,E,NewE), E \= NewE. | |
| 1247 | ||
| 1248 | rewrite_once2(X,Y,E,NewE) :- equal_terms(X,E),!, NewE=Y. | |
| 1249 | rewrite_once2(_X,_Y,E,NewE) :- atomic(E),!, NewE=E. | |
| 1250 | rewrite_once2(_X,_Y,'$'(E),NewE) :- atomic(E),!, NewE='$'(E). | |
| 1251 | rewrite_once2(X,Y,C,NewC) :- C=..[Op|Args], | |
| 1252 | select(Arg,Args,NewArg,NewArgs), | |
| 1253 | rewrite_once2(X,Y,Arg,NewArg), | |
| 1254 | NewC =.. [Op|NewArgs]. | |
| 1255 | ||
| 1256 | wd_strict_term(T) :- atomic(T), !. | |
| 1257 | wd_strict_term('$'(E)) :- atomic(E), !. | |
| 1258 | wd_strict_term(T) :- | |
| 1259 | \+ with_ids(T,_), % quantified_union, quantified_intersection, event_b_comprehension_set, forall, exists -> not WD strict | |
| 1260 | T=..[F|Args], | |
| 1261 | \+ not_wd_strict(F), | |
| 1262 | wd_strict_args(Args). | |
| 1263 | ||
| 1264 | wd_strict_args([]). | |
| 1265 | wd_strict_args([T|Args]) :- wd_strict_term(T), wd_strict_args(Args). | |
| 1266 | ||
| 1267 | not_wd_strict(implication). | |
| 1268 | not_wd_strict(conjunct). | |
| 1269 | not_wd_strict(disjunct). | |
| 1270 | ||
| 1271 | is_subterm(Term,Term). | |
| 1272 | is_subterm(Subterm,Term) :- | |
| 1273 | Term=..[_|Args], | |
| 1274 | member(Arg,Args), | |
| 1275 | is_subterm(Subterm,Arg). | |
| 1276 | ||
| 1277 | ||
| 1278 | ||
| 1279 | replace_used_ids([],_,[]). | |
| 1280 | replace_used_ids(['$'(X)|T],IdsTypes,['$'(Y)|R]) :- | |
| 1281 | member(b(identifier(X),_,_),IdsTypes), !, | |
| 1282 | new_aux_identifier(IdsTypes,Y), | |
| 1283 | replace_used_ids(T,[b(identifier(Y),any,[])|IdsTypes],R). | |
| 1284 | replace_used_ids(['$'(X)|T],IdsTypes,['$'(X)|R]) :- | |
| 1285 | replace_used_ids(T,[b(identifier(X),any,[])|IdsTypes],R). | |
| 1286 | ||
| 1287 | ||
| 1288 | ||
| 1289 | same_type('$'(S),'$'(T),List) :- | |
| 1290 | member(b(identifier(S),Type,_),List), | |
| 1291 | member(b(identifier(T),Type,_),List), | |
| 1292 | Type \= any. | |
| 1293 | ||
| 1294 | ||
| 1295 | ||
| 1296 | image_intersection(F,intersection(A,B),Inter) :- image_intersection(F,A,L), image_intersection(F,B,R), !, Inter = intersection(L,R). | |
| 1297 | image_intersection(F,A,image(F,A)). | |
| 1298 | ||
| 1299 | ||
| 1300 | ||
| 1301 | ||
| 1302 | ||
| 1303 | ||
| 1304 | ||
| 1305 | :- load_files(library(system), [when(compile_time), imports([environ/2])]). | |
| 1306 | :- if(environ(prob_release,true)). | |
| 1307 | % Don't include tests in release mode. | |
| 1308 | :- else. | |
| 1309 | :- use_module(test_sequent_prover). | |
| 1310 | :- endif. |