86 #include "auto_focus.h"
87 #include "reduction_job.h"
89 #include "model_base.h"
90 #include "hlp_context.h"
91 #include "mdl_controller.h"
94 using namespace std::chrono;
95 using namespace r_code;
101 switch (view->get_sync()) {
102 case View::SYNC_AXIOM:
103 case View::SYNC_ONCE_AXIOM:
112 TPX::TPX(AutoFocusController *auto_focus, _Fact *target, _Fact *pattern, BindingMap *bindings) :
_Object(), auto_focus_(auto_focus), target_(target), abstracted_target_(pattern), target_bindings_(bindings), cst_hook_(NULL) {
114 if (bindings->is_fully_specified()) {
116 Code *target_payload = target->get_reference(0)->get_reference(0)->get_reference(0);
117 if (target_payload->code(0).asOpcode() == Opcodes::ICst) {
119 Code *cst = target_payload->get_reference(0);
120 cst_hook_ = (CSTController *)((
r_exec::View *)cst->get_view(auto_focus->get_primary_group(),
true))->controller_;
125 TPX::TPX(AutoFocusController *auto_focus, _Fact *target) :
_Object(), auto_focus_(auto_focus) {
128 abstracted_target_ = (_Fact *)bm->abstract_object(target,
false);
130 target_bindings_ = bm;
136 bool TPX::take_input(View *input, _Fact *abstracted_input, BindingMap *bm) {
138 return filter(input, abstracted_input, bm);
141 void TPX::signal(View *input)
const {
144 void TPX::ack_pred_success(Success* success) {
147 bool TPX::filter(View *input, _Fact *abstracted_input, BindingMap *bm) {
149 if (input->object_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst)
151 if (target_bindings_->intersect(bm)) {
153 if (target_bindings_->is_fully_specified())
155 for (uint32 i = 0; i < new_maps_.size(); ++i)
156 if (new_maps_[i]->intersect(bm)) {
160 _bm->reset_fwd_timings(input->object_);
162 if (_bm->match_fwd_strict(input->object_, (_Fact *)target_->get_reference(0)->get_reference(0))) {
163 new_maps_.push_back(_bm);
166 for (i = cache.begin(now); i != cache.end(); ++i) {
170 if (_bm->intersect(i->bindings_)) {
172 auto_focus_->inject_input(i->input_, i->abstraction_, i->bindings_);
178 if (cst_hook_ != NULL)
179 cst_hook_->take_input(input);
180 CInput ci(input, abstracted_input, bm);
182 if (i != cache.end()) {
184 if (i->ijt_ < ci.ijt_)
196 _TPX::_TPX(AutoFocusController *auto_focus, _Fact *target, _Fact *pattern, BindingMap *bindings) : TPX(auto_focus, target, pattern, bindings) {
198 inputs_.reserve(InputsInitialSize);
201 _TPX::_TPX(AutoFocusController *auto_focus, _Fact *target) : TPX(auto_focus, target) {
207 void _TPX::filter_icst_components(ICST *icst, uint32 icst_index, vector<Component> &components) {
209 uint32 found_component_count = 0;
210 uint32 *found =
new uint32[icst->components_.size()];
211 for (uint32 j = 0; j < components.size(); ++j) {
213 for (uint32 i = 0; i < icst->components_.size(); ++i) {
215 if (components[j].discarded)
217 if (components[j].
object == icst->components_[i]) {
219 found[found_component_count] = j;
220 ++found_component_count;
225 if (found_component_count > 0) {
227 for (uint32 i = 0; i < found_component_count; ++i)
228 components[found[i]].discarded =
true;
230 components[icst_index].discarded =
true;
236 Code* candidate = fact->get_reference(0);
237 if (candidate->code(0).asOpcode() == Opcodes::ICst) {
239 uint16 component_index;
240 if (icst->
contains(component, component_index)) {
241 Code* cst = candidate->get_reference(0);
243 Code* unpacked_cst = cst->get_reference(cst->references_size() - CST_HIDDEN_REFS);
244 return (
_Fact*)unpacked_cst->get_reference(component_index);
249 for (uint32 i = 0; i < icst->components_.size(); ++i) {
264 for (i = inputs_.begin(); i != inputs_.end(); ++i) {
266 if (component_pattern) {
273 vector<P<_Fact> >::const_iterator f_icst;
274 for (f_icst = f_icsts_.begin(); f_icst != f_icsts_.end(); ++f_icst) {
277 if (component_pattern) {
287 uint16 opcode = component->get_reference(0)->code(0).asOpcode();
288 if (opcode == Opcodes::Cmd || opcode == Opcodes::IMdl)
296 uint16 opcode = component->get_reference(0)->code(0).asOpcode();
297 if (opcode == Opcodes::Cmd || opcode == Opcodes::IMdl)
302 if (results.size() > 0)
305 _Fact* component_pattern;
306 _Fact* f_icst = make_f_icst(component, component_pattern, new_cst);
308 results.push_back(FindFIcstResult(f_icst, component_pattern));
311 _Fact *_TPX::make_f_icst(_Fact *component, _Fact*& component_pattern,
P<Code> &new_cst) {
313 uint16 opcode = component->get_reference(0)->code(0).asOpcode();
314 if (opcode == Opcodes::Cmd || opcode == Opcodes::IMdl)
318 vector<Component> components;
319 vector<uint32> icst_components;
322 for (i = inputs_.begin(); i != inputs_.end(); ++i) {
324 if (component == i->input_) {
326 components.push_back(Component(component));
327 }
else if (component->match_timings_sync(i->input_)) {
329 Code *icst = i->input_->get_reference(0);
330 if (icst->code(0).asOpcode() == Opcodes::ICst)
331 icst_components.push_back(components.size());
332 components.push_back(Component(i->input_));
336 for (uint32 j = 0; j < icst_components.size(); ++j) {
338 ICST *icst = (ICST *)components[icst_components[j]].object->get_reference(0);
339 filter_icst_components(icst, j, components);
342 uint32 actual_size = 0;
343 for (uint32 j = 0; j < components.size(); ++j) {
345 if (components[j].discarded)
351 if (actual_size <= 1)
356 for (_i = inputs_.begin(); _i != inputs_.end(); ++_i) {
358 for (uint32 j = 0; j < components.size(); ++j) {
360 if (_i->input_ == components[j].object)
361 _i->eligible_cause_ =
false;
366 new_cst = build_cst(components, bm, component);
368 component_pattern = (_Fact*)new_cst->get_reference(0);
369 _Fact *f_icst = bm->build_f_ihlp(new_cst, Opcodes::ICst,
false);
371 f_icst->set_reference(0, bm->bind_pattern(f_icst->get_reference(0)));
372 f_icsts_.push_back(f_icst);
376 Code *_TPX::build_cst(
const vector<Component> &components, BindingMap *bm, _Fact *main_component) {
378 Code *cst = _Mem::Get()->build_object(Atom::CompositeState(Opcodes::Cst, CST_ARITY));
380 uint16 actual_component_count = 0;
382 for (uint16 i = 0; i < components.size(); ++i) {
383 if (components[i].discarded)
385 if (components[i].
object == main_component) {
386 cst->add_reference(bm->abstract_object(main_component,
false));
387 ++actual_component_count;
392 for (uint16 i = 0; i < components.size(); ++i) {
394 if (components[i].discarded)
396 if (components[i].
object == main_component)
400 cst->add_reference(bm->abstract_object(components[i].object,
true));
401 ++actual_component_count;
404 uint16 extent_index = CST_ARITY;
406 cst->code(CST_TPL_ARGS) = Atom::IPointer(++extent_index);
407 cst->code(extent_index) = Atom::Set(0);
409 cst->code(CST_OBJS) = Atom::IPointer(++extent_index);
410 cst->code(extent_index) = Atom::Set(actual_component_count);
411 for (uint16 i = 0; i < actual_component_count; ++i)
412 cst->code(++extent_index) = Atom::RPointer(i);
414 cst->code(CST_FWD_GUARDS) = Atom::IPointer(++extent_index);
415 cst->code(extent_index) = Atom::Set(0);
417 cst->code(CST_BWD_GUARDS) = Atom::IPointer(++extent_index);
418 cst->code(extent_index) = Atom::Set(0);
420 cst->code(CST_OUT_GRPS) = Atom::IPointer(++extent_index);
421 cst->code(extent_index) = Atom::Set(1);
422 cst->code(++extent_index) = Atom::RPointer(cst->references_size());
424 cst->code(CST_ARITY) = Atom::Float(1);
426 cst->add_reference(auto_focus_->get_view()->get_host());
431 Code *_TPX::build_mdl_head(HLPBindingMap *bm, uint16 tpl_arg_count, _Fact *lhs, _Fact *rhs, uint16 &write_index,
bool allow_shared_timing_vars) {
433 Code* abstract_lhs = bm->abstract_object(lhs,
false, allow_shared_timing_vars ? 0 : -1);
435 int rhs_first_search_index = (allow_shared_timing_vars ? 0 : -1);
436 if (abstract_lhs->get_reference(0)->code(0).asOpcode() == Opcodes::IMdl) {
437 Code* imdl = abstract_lhs->get_reference(0);
440 auto exposed_args_index = imdl->code(I_HLP_EXPOSED_ARGS).asIndex();
441 auto exposed_args_count = imdl->code(exposed_args_index).getAtomCount();
442 auto exposed_after_index = exposed_args_index + (exposed_args_count - 1);
443 if (exposed_args_count >= 2 &&
444 imdl->code(exposed_after_index).getDescriptor() == Atom::VL_PTR)
445 rhs_first_search_index = imdl->code(exposed_after_index).asIndex();
447 Code* abstract_rhs = bm->abstract_object(rhs,
false, rhs_first_search_index);
449 return build_mdl_head_from_abstract(tpl_arg_count, abstract_lhs, abstract_rhs, write_index);
452 Code* _TPX::build_mdl_head_from_abstract(uint16 tpl_arg_count,
Code* abstract_lhs,
Code* abstract_rhs, uint16& write_index) {
453 Code* mdl = _Mem::Get()->build_object(Atom::Model(Opcodes::Mdl, MDL_ARITY));
454 mdl->add_reference(abstract_lhs);
455 mdl->add_reference(abstract_rhs);
457 write_index = MDL_ARITY;
459 mdl->code(MDL_TPL_ARGS) = Atom::IPointer(++write_index);
460 if (tpl_arg_count >= 2) {
462 mdl->code(write_index) = Atom::Set(tpl_arg_count - 1);
464 for (uint16 i = 0; i < tpl_arg_count - 2; ++i)
465 mdl->code(++write_index) = Atom::VLPointer(i);
467 mdl->code(write_index) = Atom::IPointer(write_index + 1);
470 mdl->code(write_index) = Atom::Object(Opcodes::TI, 2);
471 mdl->code(++write_index) = Atom::VLPointer(tpl_arg_count - 2);
472 mdl->code(++write_index) = Atom::VLPointer(tpl_arg_count - 1);
475 mdl->code(write_index) = Atom::Set(tpl_arg_count);
476 for (uint16 i = 0; i < tpl_arg_count; ++i)
477 mdl->code(++write_index) = Atom::VLPointer(i);
480 mdl->code(MDL_OBJS) = Atom::IPointer(++write_index);
481 mdl->code(write_index) = Atom::Set(2);
482 mdl->code(++write_index) = Atom::RPointer(0);
483 mdl->code(++write_index) = Atom::RPointer(1);
488 void _TPX::build_mdl_tail(
Code *mdl, uint16 write_index) {
490 mdl->code(MDL_OUT_GRPS) = Atom::IPointer(++write_index);
491 mdl->code(write_index) = Atom::Set(1);
492 mdl->code(++write_index) = Atom::RPointer(2);
494 mdl->code(MDL_STRENGTH) = Atom::Float(0);
495 mdl->code(MDL_CNT) = Atom::Float(1);
496 mdl->code(MDL_SR) = Atom::Float(1);
497 mdl->code(MDL_DSR) = Atom::Float(1);
498 mdl->code(MDL_ARITY) = Atom::Float(1);
500 mdl->add_reference(auto_focus_->get_view()->get_host());
503 void _TPX::inject_hlps()
const {
505 vector<P<Code> >::const_iterator c;
506 for (c = csts_.begin(); c != csts_.end(); ++c)
507 _Mem::Get()->pack_hlp(*c);
508 auto_focus_->inject_hlps(csts_);
509 auto_focus_->inject_hlps(mdls_);
512 void _TPX::inject_hlps(Timestamp analysis_starting_time) {
514 if (auto_focus_->decompile_models()) {
518 for (i = inputs_.begin(); i != inputs_.end(); ++i)
519 tmp.push_back((
Code *)i->input_);
521 std::string header(
"> from buffer -------------------\n\n");
524 td->add_objects(tmp);
527 auto analysis_end = Now();
528 auto d = duration_cast<microseconds>(analysis_end - analysis_starting_time);
529 auto timing = to_string(d.count());
530 header = Utils::ToString_s_ms_us(Now(), Utils::GetTimeReference());
531 std::string s0 = (
" > ");
532 s0 += get_header() + std::string(
":production [");
533 std::string s1(
"us] -------------------\n\n");
534 header += s0 + timing + s1;
536 td =
new TDecompiler(1, header);
537 td->add_objects(mdls_);
549 GTPX::GTPX(AutoFocusController *auto_focus, _Fact *target, _Fact *pattern, BindingMap *bindings, Fact *f_imdl) : _TPX(auto_focus, target, pattern, bindings), f_imdl_(f_imdl) {
555 bool GTPX::take_input(View *input, _Fact *abstracted_input, BindingMap *bm) {
557 if (!filter(input, abstracted_input, bm))
560 inputs_.push_back(Input(input, abstracted_input, bm));
564 void GTPX::signal(View *input)
const {
566 if (!auto_focus_->gtpx_on())
569 if (((_Fact *)input->object_)->is_fact()) {
571 ReductionJob<GTPX> *j =
new ReductionJob<GTPX>(
new View(input), (GTPX *)
this);
572 #ifdef WITH_DETAIL_OID
573 OUTPUT_LINE((TraceLevel)0,
" make ReductionJob<GTPX> " << j->get_job_id() <<
"(" << j->get_detail_oid() <<
574 "): controller(" << get_detail_oid() <<
")->reduce(View(fact_" << input->object_->get_oid() <<
"))");
576 _Mem::Get()->push_reduction_job(j);
582 _Fact* consequent = target_->get_goal()->get_target();
584 if (consequent->is_anti_fact() && success->
get_evidence()->is_fact() &&
585 success->
get_evidence()->is_evidence(consequent) == MATCH_SUCCESS_POSITIVE) {
587 auto analysis_starting_time = Now();
597 uint16 inputs_index = mk_rdx->code(MK_RDX_INPUTS).asIndex();
598 if (mk_rdx->code(0).asOpcode() != r_exec::Opcodes::MkRdx ||
599 mk_rdx->code(inputs_index).getAtomCount() < 2)
602 _Fact* cause = (
_Fact*)mk_rdx->get_first_input();
603 MkRdx* req_mk_rdx = (
MkRdx*)mk_rdx->get_reference(mk_rdx->code(inputs_index + 2).asIndex());
604 if (req_mk_rdx->code(0).asOpcode() != r_exec::Opcodes::MkRdx)
607 _Fact* f_icst = (
_Fact*)req_mk_rdx->get_first_input();
609 auto period = duration_cast<microseconds>(consequent->get_after() - cause->get_after());
613 if (build_mdl(cause, f_icst, consequent, guard_builder, period))
614 inject_hlps(analysis_starting_time);
616 if (target_->get_goal()->has_sim()) {
617 auto controller = target_->get_goal()->get_sim()->root_;
625 predictions_.push_back((
_Fact*)success->
get_object()->get_pred()->get_reference(0));
630 _Fact *consequent = (
_Fact *)input->object_->get_reference(0)->get_reference(1);
634 P<Code> unused = consequent_bm->abstract_object(consequent,
false);
637 for (uint32 i = 0; i < predictions_.size(); ++i) {
640 bm->reset_fwd_timings(predictions_[i]);
641 if (bm->match_fwd_strict(predictions_[i], consequent))
645 auto analysis_starting_time = Now();
647 if (target_->get_reference(0)->code(0).asOpcode() == Opcodes::MkVal)
653 microseconds lhs_duration;
654 microseconds rhs_duration;
657 for (i = inputs_.begin(); i != inputs_.end();) {
659 if (i->input_->get_after() >= consequent->get_after()) {
661 i = inputs_.erase(i);
665 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst) {
673 if (!cause.eligible_cause_) {
679 if (Utils::Synchronous(cause.input_->get_after(), target_->get_after())) {
685 period = duration_cast<microseconds>(consequent->get_after() - cause.input_->get_after());
686 lhs_duration = duration_cast<microseconds>(cause.input_->get_before() - cause.input_->get_after());
687 rhs_duration = duration_cast<microseconds>(consequent->get_before() - consequent->get_after());
688 guard_builder =
new TimingGuardBuilder(period);
690 vector<FindFIcstResult> results;
693 if (results.size() == 0) {
695 if (build_mdl(cause.input_, NULL, consequent, guard_builder, period))
696 inject_hlps(analysis_starting_time);
699 if (build_mdl(results[0].f_icst, results[0].component_pattern, consequent, guard_builder, period, new_cst))
700 inject_hlps(analysis_starting_time);
706 bool GTPX::build_mdl(_Fact *cause, _Fact* f_icst, _Fact *consequent, GuardBuilder *guard_builder, microseconds period) {
707 if (consequent->is_anti_fact()) {
710 vector<FindFIcstResult> results;
713 results.push_back(FindFIcstResult(f_icst, NULL));
716 find_f_icst(target_->get_goal()->get_target(), results, new_cst);
717 if (results.size() == 0)
719 _Fact* f_icst = results[0].f_icst;
723 _Fact* goal_target = target_->get_goal()->get_target();
724 bm->init(goal_target->get_reference(0), MK_VAL_VALUE);
726 bm->init(f_icst, FACT_AFTER);
727 bm->init(f_icst, FACT_BEFORE);
731 P<Code> m0 = build_mdl_head(bm, 3, cause, consequent, write_index,
false);
732 guard_builder->build(m0, NULL, cause, write_index);
733 build_mdl_tail(m0, write_index);
735 return build_requirement(bm, m0, period + milliseconds(20), results, NULL);
741 P<Code> m0 = build_mdl_head(bm, 0, cause, consequent, write_index);
742 guard_builder->build(m0, NULL, cause, write_index);
743 build_mdl_tail(m0, write_index);
745 Code *_m0 = ModelBase::Get()->check_existence(m0);
748 else if (_m0 == m0) {
756 bool GTPX::build_mdl(_Fact *f_icst, _Fact *cause_pattern, _Fact *consequent, GuardBuilder *guard_builder, microseconds period,
Code *new_cst) {
761 P<Code> m0 = build_mdl_head(bm, 0, f_icst, consequent, write_index);
762 guard_builder->build(m0, NULL, cause_pattern, write_index);
763 build_mdl_tail(m0, write_index);
765 Code *_m0 = ModelBase::Get()->check_existence(m0);
768 else if (_m0 == m0) {
771 csts_.push_back(new_cst);
778 std::string GTPX::get_header()
const {
780 return std::string(
"GTPX");
785 PTPX::PTPX(AutoFocusController *auto_focus, _Fact *target, _Fact *pattern, BindingMap *bindings, Fact *f_imdl) : _TPX(auto_focus, target, pattern, bindings), f_imdl_(f_imdl) {
791 void PTPX::signal(View *input)
const {
793 if (!auto_focus_->ptpx_on())
796 if (((_Fact *)input->object_)->is_anti_fact()) {
798 ReductionJob<PTPX> *j =
new ReductionJob<PTPX>(
new View(input), (PTPX *)
this);
799 #ifdef WITH_DETAIL_OID
800 OUTPUT_LINE((TraceLevel)0,
" make ReductionJob<PTPX> " << j->get_job_id() <<
"(" << j->get_detail_oid() <<
801 "): controller(" << get_detail_oid() <<
")->reduce(View(fact_" << input->object_->get_oid() <<
"))");
803 _Mem::Get()->push_reduction_job(j);
809 auto_focus_->copy_cross_buffer(inputs_);
811 auto analysis_starting_time = Now();
814 Fact* f_imdl = (Fact *)f_imdl_;
815 Timestamp f_imdl_after = f_imdl->get_after();
816 Timestamp f_imdl_before = f_imdl->get_before();
820 P<_Fact> consequent =
new Fact(f_imdl->get_reference(0), f_imdl_after, f_imdl_before, f_imdl->get_cfd(), f_imdl->get_psln_thr());
821 consequent->set_opposite();
823 vector<Input> discarded_f_mk_vals;
824 vector<Input> discarded_f_icsts;
825 vector<Code*> accepted_mk_vals;
830 P<Code> unused = end_bm->abstract_object(consequent,
false);
833 for (i = inputs_.begin(); i != inputs_.end();) {
835 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::Cmd)
837 i = inputs_.erase(i);
838 else if (i->input_->get_after() > consequent->get_after())
840 i = inputs_.erase(i);
841 else if (!end_bm->intersect(i->bindings_)) {
843 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::MkVal &&
844 !_Mem::Get()->matches_axiom(i->input_->get_reference(0)))
846 discarded_f_mk_vals.push_back(*i);
847 else if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst)
849 discarded_f_icsts.push_back(*i);
851 i = inputs_.erase(i);
854 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::MkVal &&
855 !_Mem::Get()->matches_axiom(i->input_->get_reference(0)))
857 accepted_mk_vals.push_back(i->input_->get_reference(0));
864 for (
auto f_mk_val = discarded_f_mk_vals.begin(); f_mk_val != discarded_f_mk_vals.end();) {
866 for (
auto accepted = accepted_mk_vals.begin(); accepted != accepted_mk_vals.end(); ++accepted) {
868 if (_Fact::Match(f_mk_val->input_->get_reference(0), 0, MK_VAL_ATTR,
869 *accepted, MK_VAL_ATTR, MK_VAL_ARITY)) {
877 inputs_.push_back(Input(*f_mk_val));
881 f_mk_val = discarded_f_mk_vals.erase(f_mk_val);
885 for (
auto f_icst = discarded_f_icsts.begin(); f_icst != discarded_f_icsts.end(); ++f_icst) {
886 bool contains =
false;
887 for (
auto f_mk_val = discarded_f_mk_vals.begin(); f_mk_val != discarded_f_mk_vals.end(); ++f_mk_val) {
888 if (((ICST*)f_icst->input_->get_reference(0))->r_contains(f_mk_val->input_)) {
896 inputs_.push_back(Input(*f_icst));
901 microseconds lhs_duration;
902 microseconds rhs_duration;
904 for (i = inputs_.begin(); i != inputs_.end(); ++i) {
906 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst)
911 if (!cause.eligible_cause_)
914 period = duration_cast<microseconds>(consequent->get_after() - cause.input_->get_after());
915 lhs_duration = duration_cast<microseconds>(cause.input_->get_before() - cause.input_->get_after());
916 rhs_duration = duration_cast<microseconds>(consequent->get_before() - consequent->get_after());
917 if (period.count() == 0 && lhs_duration == rhs_duration)
920 guard_builder =
new GuardBuilder();
922 guard_builder =
new TimingGuardBuilder(period);
924 vector<FindFIcstResult> results;
927 if (results.size() == 0) {
929 if (build_mdl(cause.input_, consequent, guard_builder, period))
930 inject_hlps(analysis_starting_time);
933 for (
size_t i = 0; i < results.size(); ++i) {
934 if (build_mdl(results[i].f_icst, results[i].component_pattern, consequent, guard_builder, period, new_cst))
935 inject_hlps(analysis_starting_time);
940 _Fact* cause_pattern;
941 P<_Fact> f_icst = make_f_icst(cause.input_, cause_pattern, new_cst);
943 if (build_mdl(f_icst, cause_pattern, consequent, guard_builder, period, new_cst))
944 inject_hlps(analysis_starting_time);
951 bool PTPX::build_mdl(_Fact *cause, _Fact *consequent, GuardBuilder *guard_builder, microseconds period) {
956 P<Code> m0 = build_mdl_head(bm, 0, cause, consequent, write_index);
957 guard_builder->build(m0, NULL, cause, write_index);
958 build_mdl_tail(m0, write_index);
960 Code *_m0 = ModelBase::Get()->check_existence(m0);
963 else if (_m0 == m0) {
971 bool PTPX::build_mdl(_Fact *f_icst, _Fact *cause_pattern, _Fact *consequent, GuardBuilder *guard_builder, microseconds period,
Code *new_cst) {
976 P<Code> m0 = build_mdl_head(bm, 0, f_icst, consequent, write_index);
977 guard_builder->build(m0, NULL, cause_pattern, write_index);
978 build_mdl_tail(m0, write_index);
980 Code *_m0 = ModelBase::Get()->check_existence(m0);
983 else if (_m0 == m0) {
986 csts_.push_back(new_cst);
993 std::string PTPX::get_header()
const {
995 return std::string(
"PTPX");
1000 CTPX::CTPX(AutoFocusController *auto_focus, View *premise) : _TPX(auto_focus, premise->object_), stored_premise_(false), premise_(premise) {
1008 _Fact *input_object = (_Fact *)input->object_;
1010 _Fact *abstracted_input = (_Fact *)bm->abstract_object(input_object,
false);
1011 Input i(input, abstracted_input, bm);
1012 inputs_.push_front(i);
1013 if (input_object == target_)
1014 stored_premise_ =
true;
1019 View *_view =
new View(input);
1020 ReductionJob<CTPX> *j =
new ReductionJob<CTPX>(_view,
this);
1021 #ifdef WITH_DETAIL_OID
1022 OUTPUT_LINE((TraceLevel)0,
" make ReductionJob " << j->get_job_id() <<
"(" << j->get_detail_oid() <<
1023 "): CTPX(" << get_detail_oid() <<
")->reduce(View(fact_" << input->object_->get_oid() <<
"))");
1025 _Mem::Get()->push_reduction_job(j);
1030 auto analysis_starting_time = Now();
1032 if (!stored_premise_)
1033 inputs_.push_back(Input(premise_, abstracted_target_, target_bindings_));
1035 _Fact *consequent = (_Fact *)input->object_;
1040 P<Code> unused = end_bm->abstract_object(consequent,
false);
1043 bool have_delta =
false;
1044 BindingMap bm_with_delta;
1045 if (target_->get_reference(0)->code(0).asOpcode() == Opcodes::MkVal) {
1047 float32 delta = consequent->get_reference(0)->code(MK_VAL_VALUE).asFloat() -
1048 target_->get_reference(0)->code(MK_VAL_VALUE).asFloat();
1051 P<Code> delta_code(
new LObject());
1052 delta_code->code(0) = Atom::Float(delta);
1053 bm_with_delta.init(delta_code, 0);
1059 set<_Fact*> only_intersects_delta_imdls;
1062 for (i = inputs_.begin(); i != inputs_.end();) {
1064 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst) {
1066 bool icstIsOK =
true;
1067 ICST *icst = (ICST*)i->input_->get_reference(0);
1068 for (uint32 j = 0; j < icst->components_.size(); ++j) {
1072 P<Code> unused = component_bm->abstract_object(icst->components_[j],
false);
1074 if (!(target_bindings_->intersect(component_bm) || end_bm->intersect(component_bm))) {
1081 i->input_->get_after() >= consequent->get_after())
1082 i = inputs_.erase(i);
1088 if (i->input_->get_after() >= consequent->get_after())
1090 i = inputs_.erase(i);
1091 else if (!(target_bindings_->intersect(i->bindings_) || end_bm->intersect(i->bindings_))) {
1094 if (have_delta && i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::IMdl &&
1095 bm_with_delta.intersect(i->bindings_)) {
1096 only_intersects_delta_imdls.insert(i->input_);
1100 i = inputs_.erase(i);
1106 bool need_guard =
false;
1107 if (target_->get_reference(0)->code(0).asOpcode() == Opcodes::MkVal) {
1108 Atom target_val = target_->get_reference(0)->code(MK_VAL_VALUE);
1109 if (target_val.isFloat())
1111 else if (target_val.getDescriptor() == Atom::I_PTR) {
1112 if (hasUserDefinedOperators(target_->get_reference(0)->code(target_val.asIndex()).asOpcode()))
1117 auto period = duration_cast<microseconds>(Utils::GetTimestamp<Code>(consequent, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1120 for (i = inputs_.begin(); i != inputs_.end(); ++i) {
1122 if (target_ == i->input_)
1125 if (i->input_->get_reference(0)->code(0).asOpcode() == Opcodes::ICst)
1130 if (!cause.eligible_cause_)
1133 if (Utils::Synchronous(cause.input_->get_after(), target_->get_after()))
1138 if (need_guard && (cause.input_->get_reference(0)->code(0).asOpcode() != Opcodes::IMdl ||
1139 only_intersects_delta_imdls.find(cause.input_) != only_intersects_delta_imdls.end())) {
1141 if ((guard_builder = find_guard_builder(cause.input_, consequent, period)) == NULL)
1144 guard_builder = get_default_guard_builder(cause.input_, consequent, period);
1146 vector<FindFIcstResult> results;
1148 if (results.size() == 0) {
1150 if (build_mdl(cause.input_, consequent, guard_builder, period))
1151 inject_hlps(analysis_starting_time);
1156 if (build_mdl(results[0].f_icst, results[0].component_pattern, consequent, guard_builder, period))
1157 inject_hlps(analysis_starting_time);
1162 GuardBuilder *CTPX::get_default_guard_builder(_Fact *cause, _Fact *consequent, microseconds period) {
1164 Code *cause_payload = cause->get_reference(0);
1165 uint16 opcode = cause_payload->code(0).asOpcode();
1166 if (opcode == Opcodes::Cmd || opcode == Opcodes::IMdl) {
1168 auto offset = duration_cast<microseconds>(consequent->get_after() - cause->get_after());
1169 auto cmd_duration = duration_cast<microseconds>(cause->get_before() - cause->get_after());
1170 return new NoArgCmdGuardBuilder(period, offset, cmd_duration);
1173 return new TimingGuardBuilder(period);
1182 GuardBuilder *CTPX::find_guard_builder(_Fact *cause, _Fact *consequent, microseconds period) {
1184 Code *cause_payload = cause->get_reference(0);
1185 uint16 opcode = cause_payload->code(0).asOpcode();
1186 if (opcode == Opcodes::Cmd) {
1187 uint16 cmd_arg_set_index = cause_payload->code(CMD_ARGS).asIndex();
1188 uint16 cmd_arg_count = cause_payload->code(cmd_arg_set_index).getAtomCount();
1193 auto result = OpContext::build_and_evaluate_expression(target_, consequent, Atom::Operator(Opcodes::Sub, 2));
1197 for (
size_t i = 0; i < result.size(); ++i) {
1198 if (result[i] != Atom::Nil()) {
1206 uint16 extent_index = 0;
1209 for (uint16 i = 1; i <= cmd_arg_count; ++i) {
1210 Atom s = cause_payload->code(cmd_arg_set_index + i);
1211 uint16 cmd_index = cmd_arg_set_index + i;
1213 if (s.getDescriptor() == Atom::I_PTR) {
1214 cmd_index = s.asIndex();
1215 match = _Fact::MatchStructure(cause_payload, cmd_index, 0, &searched_for, 0, s.getAtomCount());
1218 match = _Fact::Match(cause_payload, cmd_index, 0, &searched_for, 0, s.getAtomCount());
1221 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1222 return new ACGuardBuilder(period, period - offset, cmd_arg_set_index + i);
1229 result = OpContext::build_and_evaluate_expression(target_, consequent, Atom::Operator(Opcodes::Div, 2));
1233 for (
int i = 0; i < result.size(); ++i) {
1234 if (result[i] != Atom::Nil()) {
1243 uint16 extent_index = 0;
1245 for (uint16 i = 1; i <= cmd_arg_count; ++i) {
1246 Atom s = cause_payload->code(cmd_arg_set_index + i);
1247 uint16 cmd_index = cmd_arg_set_index + i;
1249 if (s.getDescriptor() == Atom::I_PTR) {
1250 cmd_index = s.asIndex();
1251 match = _Fact::MatchStructure(cause_payload, cmd_index, 0, &searched_for, 0, s.getAtomCount());
1254 match = _Fact::Match(cause_payload, cmd_index, 0, &searched_for, 0, s.getAtomCount());
1257 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1258 return new MCGuardBuilder(period, period - offset, cmd_arg_set_index + i);
1263 else if (opcode == Opcodes::IMdl) {
1265 float32 q0 = target_->get_reference(0)->code(MK_VAL_VALUE).asFloat();
1266 float32 q1 = consequent->get_reference(0)->code(MK_VAL_VALUE).asFloat();
1269 float32 searched_for = q1 - q0;
1270 Code* imdl = cause->get_reference(0);
1271 uint16 imdl_exposed_args_index = imdl->code(I_HLP_EXPOSED_ARGS).asIndex();
1272 uint16 imdl_exposed_args_count = imdl->code(imdl_exposed_args_index).getAtomCount();
1274 for (uint16 i = 1; i <= imdl_exposed_args_count; ++i) {
1276 Atom s = imdl->code(imdl_exposed_args_index + i);
1279 float32 _s = s.asFloat();
1280 if (Utils::Equal(_s, searched_for)) {
1281 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1289 searched_for = q1 / q0;
1290 for (uint16 i = imdl_exposed_args_index + 1; i <= imdl_exposed_args_count; ++i) {
1292 Atom s = imdl->code(i);
1295 float32 _s = s.asFloat();
1296 if (Utils::Equal(_s, searched_for)) {
1297 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1299 return new MCGuardBuilder(period, period - offset,
1306 else if (opcode == Opcodes::MkVal) {
1308 Atom s = cause_payload->code(MK_VAL_VALUE);
1311 float32 _s = s.asFloat();
1312 float32 q0 = target_->get_reference(0)->code(MK_VAL_VALUE).asFloat();
1313 float32 q1 = consequent->get_reference(0)->code(MK_VAL_VALUE).asFloat();
1316 float32 searched_for = (q1 - q0) / period.count();
1317 if (Utils::Equal(_s, searched_for)) {
1319 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1320 return new SGuardBuilder(period, period - offset);
1325 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1326 return new MGuardBuilder(period, q1 / q0, offset);
1330 auto offset = duration_cast<microseconds>(Utils::GetTimestamp<Code>(cause, FACT_AFTER) - Utils::GetTimestamp<Code>(target_, FACT_AFTER));
1331 return new AGuardBuilder(period, q1 - q0, offset);
1343 bool CTPX::build_mdl(_Fact *cause, _Fact *consequent, GuardBuilder *guard_builder, microseconds period) {
1346 bm->init(target_->get_reference(0), MK_VAL_VALUE);
1347 bm->init(target_, FACT_AFTER);
1348 bm->init(target_, FACT_BEFORE);
1353 P<Code> m0 = build_mdl_head(bm, 3, cause, consequent, write_index,
false);
1354 guard_builder->build(m0, NULL, cause, write_index);
1355 build_mdl_tail(m0, write_index);
1356 return build_requirement(bm, m0, period);
1361 bool CTPX::build_mdl(_Fact *f_icst, _Fact *cause_pattern, _Fact *consequent, GuardBuilder *guard_builder, microseconds period) {
1364 bm->init(target_->get_reference(0), MK_VAL_VALUE);
1365 bm->init(target_, FACT_AFTER);
1366 bm->init(target_, FACT_BEFORE);
1369 Code *m0 = build_mdl_head(bm, 3, f_icst, consequent, write_index);
1370 guard_builder->build(m0, NULL, cause_pattern, write_index);
1371 build_mdl_tail(m0, write_index);
1373 return build_requirement(bm, m0, period);
1376 bool CTPX::build_requirement(HLPBindingMap *bm,
Code *m0, microseconds period) {
1378 vector<FindFIcstResult> results;
1381 if (results.size() == 0)
1384 return _TPX::build_requirement(bm, m0, period, results, new_cst);
1387 bool _TPX::build_requirement(HLPBindingMap* bm,
Code* m0, microseconds period,
const vector<FindFIcstResult>& results,
Code* new_cst) {
1388 _Fact* f_icst = results[0].f_icst;
1389 _Fact* premise_pattern = results[0].component_pattern;
1390 P<Fact> f_im0 = bm->build_f_ihlp(m0, Opcodes::IMdl,
false);
1392 f_im0->set_reference(0, bm->bind_pattern(f_im0->get_reference(0)));
1393 Utils::SetTimestamp<Code>(f_im0, FACT_AFTER, f_icst->get_after());
1394 Utils::SetTimestamp<Code>(f_im0, FACT_BEFORE, f_icst->get_before());
1399 P<Code> m1 = build_mdl_head(_bm, 0, f_icst, f_im0, write_index);
1401 guard_builder->build(m1, premise_pattern, NULL, write_index);
1402 build_mdl_tail(m1, write_index);
1406 Code* rhs_object = m0->get_reference(1)->get_reference(0);
1407 for (uint16 i = 0; i < rhs_object->code_size(); ++i) {
1408 Atom v = rhs_object->code(i);
1409 if (v.getDescriptor() == Atom::VL_PTR) {
1411 if (!(m0->get_reference(0)->get_reference(0)->includes(v) || m0->includes(v))) {
1413 int16 exposed_args_position = bm->get_ihlp_exposed_args_position(v.asIndex());
1414 if (exposed_args_position >= 0) {
1415 Code* m1_rhs_object = m1->get_reference(1)->get_reference(0);
1416 uint16 i_exposed_args = m1_rhs_object->code(I_HLP_EXPOSED_ARGS).asIndex();
1417 Atom m1_rhs_var = m1_rhs_object->code(i_exposed_args + 1 + exposed_args_position);
1419 if (!m1->get_reference(0)->get_reference(0)->includes(m1_rhs_var))
1429 ModelBase::Get()->check_existence(m0, m1, _m0, _m1);
1432 else if (_m1 == m1) {
1437 mdls_.push_back(m0);
1439 csts_.push_back(new_cst);
1440 mdls_.push_back(m1);
1445 std::string CTPX::get_header()
const {
1447 return std::string(
"CTPX");