| 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. |