AERA
hlp_controller.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #include "hlp_controller.h"
86 #include "hlp_overlay.h"
87 #include "mem.h"
88 
89 using namespace r_code;
90 
91 namespace r_exec {
92 
93 HLPController::HLPController(_View *view) : OController(view), strong_requirement_count_(0), weak_requirement_count_(0), requirement_count_(0) {
94 
95  bindings_ = new HLPBindingMap();
96 
97  Code *object = get_unpacked_object();
98  bindings_->init_from_hlp(object, get_object()); // init a binding map from the patterns.
99 
100  has_tpl_args_ = object->code(object->code(HLP_TPL_ARGS).asIndex()).getAtomCount() > 0;
101  ref_count_ = 0;
102  last_match_time_ = Now();
103 }
104 
105 HLPController::~HLPController() {
106 }
107 
108 void HLPController::invalidate() {
109 
110  invalidated_ = 1;
111  controllers_.clear();
112 }
113 
114 void HLPController::add_requirement(bool strong) {
115 
116  reductionCS_.enter();
117  if (strong)
118  ++strong_requirement_count_;
119  else
120  ++weak_requirement_count_;
121  ++requirement_count_;
122  reductionCS_.leave();
123 }
124 
125 void HLPController::remove_requirement(bool strong) {
126 
127  reductionCS_.enter();
128  if (strong)
129  --strong_requirement_count_;
130  else
131  --weak_requirement_count_;
132  --requirement_count_;
133  reductionCS_.leave();
134 }
135 
136 uint32 HLPController::get_requirement_count(uint32 &weak_requirement_count, uint32 &strong_requirement_count) {
137 
138  uint32 r_c;
139  reductionCS_.enter();
140  r_c = requirement_count_;
141  weak_requirement_count = weak_requirement_count_;
142  strong_requirement_count = strong_requirement_count_;
143  reductionCS_.leave();
144  return r_c;
145 }
146 
147 uint32 HLPController::get_requirement_count() {
148 
149  uint32 r_c;
150  reductionCS_.enter();
151  r_c = requirement_count_;
152  reductionCS_.leave();
153  return r_c;
154 }
155 
156 uint16 HLPController::get_out_group_count() const {
157 
158  return get_object()->code(get_object()->code(HLP_OUT_GRPS).asIndex()).getAtomCount();
159 }
160 
161 Code *HLPController::get_out_group(uint16 i) const {
162 
163  Code *hlp = get_object();
164  uint16 out_groups_index = hlp->code(HLP_OUT_GRPS).asIndex() + 1; // first output group index.
165  return hlp->get_reference(hlp->code(out_groups_index + i).asIndex());
166 }
167 
168 bool HLPController::evaluate_bwd_guards(HLPBindingMap *bm, bool narrow_fwd_timings) {
169 
170  bool saved_fwd_timings = false;
171  Timestamp save_fwd_after, save_fwd_before;
172  if (narrow_fwd_timings && bm->has_fwd_after() && bm->has_fwd_before()) {
173  // The forward timings have previously-bound values from matching the requirement.
174  save_fwd_after = bm->get_fwd_after();
175  save_fwd_before = bm->get_fwd_before();
176  saved_fwd_timings = true;
177  }
178 
179  bool result = HLPOverlay::EvaluateBWDGuards(this, bm);
180 
181  if (saved_fwd_timings) {
182  // Call match_fwd_timings to narrow the forward timings set by the backward guards to the previously-bound values.
183  if (!bm->match_fwd_timings(save_fwd_after, save_fwd_before))
184  // The backward guards updated the forward timings outside the previously-bound values. (We don't expect this.)
185  return false;
186  }
187 
188  return result;
189 }
190 
191 bool HLPController::inject_prediction(Fact *prediction, float32 confidence) const { // prediction is simulated: f->pred->f->target.
192 
193  Code *primary_host = get_host();
194  float32 sln_thr = primary_host->code(GRP_SLN_THR).asFloat();
195  if (confidence > sln_thr) { // do not inject if cfd is too low.
196 
197  View *view = new View(View::SYNC_ONCE, Now(), confidence, 1, primary_host, primary_host, prediction); // SYNC_ONCE,res=1.
198  _Mem::Get()->inject(view);
199  return true;
200  }
201 
202  return false;
203 }
204 
205 MatchResult HLPController::check_evidences(_Fact *target, _Fact *&evidence) {
206 
207  MatchResult r = MATCH_FAILURE;
208  evidences_.CS_.enter();
209  auto now = Now();
211  for (e = evidences_.list_.begin(); e != evidences_.list_.end();) {
212 
213  if ((*e).is_too_old(now)) // garbage collection.
214  e = evidences_.list_.erase(e);
215  else {
216 
217  if ((r = (*e).evidence_->is_evidence(target)) != MATCH_FAILURE) {
218 
219  evidence = (*e).evidence_;
220  evidences_.CS_.leave();
221  return r;
222  }
223  ++e;
224  }
225  }
226  evidence = NULL;
227  evidences_.CS_.leave();
228  return r;
229 }
230 
231 MatchResult HLPController::check_predicted_evidences(_Fact *target, _Fact *&evidence) {
232 
233  MatchResult r = MATCH_FAILURE;
234  predicted_evidences_.CS_.enter();
235  auto now = Now();
237  for (e = predicted_evidences_.list_.begin(); e != predicted_evidences_.list_.end();) {
238 
239  if ((*e).is_too_old(now)) // garbage collection.
240  e = predicted_evidences_.list_.erase(e);
241  else {
242 
243  if ((r = (*e).evidence_->is_evidence(target)) != MATCH_FAILURE) {
244 
245  if (target->get_cfd() < (*e).evidence_->get_cfd()) {
246 
247  evidence = (*e).evidence_;
248  predicted_evidences_.CS_.leave();
249  return r;
250  } else
251  r = MATCH_FAILURE;
252  }
253  ++e;
254  }
255  }
256  evidence = NULL;
257  predicted_evidences_.CS_.leave();
258  return r;
259 }
260 
261 bool HLPController::become_invalidated() {
262 
263  if (is_invalidated())
264  return true;
265 
266  for (uint16 i = 0; i < controllers_.size(); ++i) {
267 
268  if (controllers_[i] != NULL && controllers_[i]->is_invalidated()) {
269 
270  kill_views();
271  return true;
272  }
273  }
274 
275  if (has_tpl_args()) {
276 
277  if (refCount_ == 1 && ref_count_ > 1) { // the ctrler was referenced by others, is no longer and has tpl args: it will not be able to predict: kill.
278 
279  kill_views();
280  return true;
281  } else
282  ref_count_ = refCount_;
283  }
284 
285  return false;
286 }
287 
288 bool HLPController::is_orphan() {
289 
290  if (has_tpl_args_) {
291 
292  if (get_requirement_count() == 0) {
293 
294  kill_views();
295  return true;
296  }
297  }
298  return false;
299 }
300 
302  uint16 out_group_count = get_out_group_count();
303  for (uint16 i = 0; i < out_group_count; ++i) {
304 
305  Group* out_group = (Group*)get_out_group(i);
306  View* view = new NotificationView(origin, out_group, marker);
307  _Mem::Get()->inject_notification(view, true);
308  }
309 }
310 
312 
313 HLPController::EvidenceEntry::EvidenceEntry() : evidence_(NULL) {
314 }
315 
316 HLPController::EvidenceEntry::EvidenceEntry(_Fact *evidence) : evidence_(evidence) {
317 
318  load_data(evidence);
319 }
320 
321 HLPController::EvidenceEntry::EvidenceEntry(_Fact *evidence, _Fact *payload) : evidence_(evidence) {
322 
323  load_data(payload);
324 }
325 
326 void HLPController::EvidenceEntry::load_data(_Fact *evidence) {
327 
328  after_ = evidence->get_after();
329  before_ = evidence->get_before();
330  confidence_ = evidence->get_cfd();
331 }
332 
334 
335 HLPController::PredictedEvidenceEntry::PredictedEvidenceEntry() : EvidenceEntry() {
336 }
337 
338 HLPController::PredictedEvidenceEntry::PredictedEvidenceEntry(_Fact *evidence) : EvidenceEntry(evidence, evidence->get_pred()->get_target()) {
339 }
340 }
r_code::list::const_iterator
Definition: list.h:266
r_exec::HLPController::evaluate_bwd_guards
bool evaluate_bwd_guards(HLPBindingMap *bm, bool narrow_fwd_timings=false)
Definition: hlp_controller.cpp:168
r_code::_View
Definition: r_code/object.h:164
r_code::Code
Definition: r_code/object.h:224
r_exec::View
Definition: view.h:102
r_exec::Group
Definition: group.h:108
r_exec::HLPBindingMap
Definition: binding_map.h:393
r_exec::HLPController::inject_notification_into_out_groups
void inject_notification_into_out_groups(r_code::Code *origin, r_code::Code *marker) const
Definition: hlp_controller.cpp:301
r_exec::NotificationView
Definition: view.h:212
r_exec::Fact
Definition: factory.h:360