operations_pos([],_I,_LI,_AM,_A,[],false).
operations_pos([operation(Name,Results,_Parameters,_Body)|FurtherOps],Invariant,
LinkingInvariant,AbsMachine,AbstractOperations,Results,ViolationFound) :-
% there might be no abstract operation with the same name (includes, etc.)
\+ (member(operation(Name,_AbsResults,_AbsParameters,_AbsBody),AbstractOperations)), !,
operations_pos(FurtherOps,Invariant,LinkingInvariant,AbsMachine,AbstractOperations,Results,ViolationFound).
operations_pos([operation(Name,Results,_Parameters,Body)|FurtherOps],Invariant,
LinkingInvariant,AbsMachine,AbstractOperations,[PreRefPoResult,RefPoResult|ListOpPos],ViolationFound) :-
% first find the matching abstract operation
member(operation(Name,_AbsResults,_AbsParameters,AbsBody),AbstractOperations),
% check if we have preconditions - otherwise we assume true
(get_texpr_expr(Body,precondition(Precondition0,RealBody)) -> true
; RealBody=Body, create_texpr(truth,pred,[],Precondition0)),
add_labels_to_texpr(Precondition0,['P1 (concrete PRE)'], Precondition),
(get_texpr_expr(AbsBody,precondition(AbsPrecondition0,AbsRealBody))
-> true
; AbsRealBody=AbsBody, create_texpr(truth,pred,[],AbsPrecondition0)
),
add_labels_to_texpr(AbsPrecondition0,['P (abstract PRE)'], AbsPrecondition),
% refinement po for the preconditions
create_negation(Precondition,NegPrecondition), % description
conjunct_predicates([Invariant,LinkingInvariant,AbsPrecondition,NegPrecondition],PreRefPo),
cbc_solve_predicate(PreRefPo,State,PreRefPoRes),
assign_violation_found(PreRefPoRes,V2,RTxt2),
% result string and print
% This PO is in Section 14.3, page 225 of Schneider's B Book; part of obligation 4 on page 530 of Abrial's B Book
ajoin([Name, ' Precondition Refinement I & J & P => P1: Counter-Example found: ', RTxt2],PreRefPoResult),
formatsilent(' * ~w~n',[PreRefPoResult]),
(debug_mode(off) -> true ; nested_print_bexpr(PreRefPo), write(State),nl),
% for the refinement of operations, we need to rename existing output variables (i.e. prime them)
prime_identifiers(Results,PrimedResults),
list_renamings_to_primed_vars(Results,Renamings),
rename_bt(RealBody,Renamings,RealBodyWithPrimedVariables),
create_equals(Results,PrimedResults,EqualResultsPred),
% refinement po for the operation
% I & J & P => [S1[out'/out]] not S not (J & out'=out)
conjunct_predicates([LinkingInvariant|EqualResultsPred],RHS),
create_negation(RHS,NegRHS),
set_reference_machine(AbsMachine),
weakest_precondition(AbsRealBody,NegRHS,RHS2),
delete_reference_machine,
create_negation(RHS2,NegRHS2),
weakest_precondition(RealBodyWithPrimedVariables,NegRHS2,RHS3),
create_negation(RHS3,NegRHS3),
conjunct_predicates([Invariant,LinkingInvariant,Precondition,NegRHS3],RefPo),
cbc_solve_predicate(RefPo,State2,RefPoRes),
assign_violation_found(RefPoRes,V1,RTxt),
% result string and print
ajoin([Name, ' Refinement I & J & P => S1 not S not J: Counter-Example found: ', RTxt],RefPoResult),
formatsilent(' * ~w~n',[RefPoResult]),
(debug_mode(off) -> true ; nested_print_bexpr(RefPo), write(State2),nl),
operations_pos(FurtherOps,Invariant,LinkingInvariant,AbsMachine,AbstractOperations,ListOpPos,SubViolationFound),
merge_violation_found([V1,V2,SubViolationFound],ViolationFound).