AERA
hlp_overlay.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_overlay.h"
86 #include "hlp_controller.h"
87 #include "hlp_context.h"
88 #include "mem.h"
89 
90 using namespace r_code;
91 
92 namespace r_exec {
93 
94 bool HLPOverlay::EvaluateBWDGuards(Controller *c, HLPBindingMap *bindings) {
95 
96  HLPOverlay o(c, bindings);
97  return o.evaluate_bwd_guards();
98 }
99 
100 bool HLPOverlay::EvaluateFWDTimings(Controller *c, HLPBindingMap *bindings) {
101 
102  HLPOverlay o(c, bindings);
103  return o.evaluate_fwd_timings();
104 }
105 
106 bool HLPOverlay::ScanBWDGuards(Controller *c, HLPBindingMap *bindings) {
107 
108  const HLPOverlay o(c, bindings);
109  return o.scan_bwd_guards();
110 }
111 
112 HLPOverlay::HLPOverlay(Controller *c, HLPBindingMap *bindings) : Overlay(c, true), bindings_(bindings) {
113 }
114 
115 HLPOverlay::HLPOverlay(Controller *c, const HLPBindingMap *bindings, bool load_code) : Overlay(c, load_code) {
116 
117  bindings_ = new HLPBindingMap((HLPBindingMap *)bindings);
118 }
119 
120 HLPOverlay::~HLPOverlay() {
121 }
122 
123 Atom *HLPOverlay::get_value_code(uint16 id) const {
124 
125  return bindings_->get_value_code(id);
126 }
127 
128 uint16 HLPOverlay::get_value_code_size(uint16 id) const {
129 
130  return bindings_->get_value_code_size(id);
131 }
132 
133 inline bool HLPOverlay::evaluate_guards(uint16 guard_set_iptr_index) {
134 
135  uint16 guard_set_index = code_[guard_set_iptr_index].asIndex();
136  uint16 guard_count = code_[guard_set_index].getAtomCount();
137  for (uint16 i = 1; i <= guard_count; ++i) {
138 
139  // Get the HLPContext like in HLPOverlay::evaluate.
140  HLPContext c(code_, guard_set_index + i, this);
141  if (!c.evaluate())
142  return false;
143  if (c.dereference()[0].isBooleanFalse())
144  // This is a boolean guard (not an assignment) and it is false.
145  return false;
146  }
147  return true;
148 }
149 
150 bool HLPOverlay::evaluate_fwd_guards() {
151 
152  return evaluate_guards(HLP_FWD_GUARDS);
153 }
154 
155 bool HLPOverlay::evaluate_bwd_guards() {
156 
157  return evaluate_guards(HLP_BWD_GUARDS);
158 }
159 
160 bool HLPOverlay::evaluate(uint16 index) {
161 
162  HLPContext c(code_, index, this);
163  return c.evaluate();
164 }
165 
166 bool HLPOverlay::evaluate_fwd_timings() {
167 
168  int16 fwd_after_guard_index = -1;
169  int16 fwd_before_guard_index = -1;
170 
171  uint16 bm_fwd_after_index = bindings_->get_fwd_after_index();
172  uint16 bm_fwd_before_index = bindings_->get_fwd_before_index();
173 
174  uint16 guard_set_index = code_[HLP_BWD_GUARDS].asIndex();
175  uint16 guard_count = code_[guard_set_index].getAtomCount();
176  for (uint16 i = 1; i <= guard_count; ++i) { // find the relevant guards.
177 
178  uint16 index = guard_set_index + i;
179  Atom a = code_[index];
180  if (a.getDescriptor() == Atom::ASSIGN_PTR) {
181 
182  uint16 _i = a.asAssignmentIndex();
183  if (_i == bm_fwd_after_index)
184  fwd_after_guard_index = i;
185  if (_i == bm_fwd_before_index)
186  fwd_before_guard_index = i;
187  }
188  }
189 
190  // These are assignment guards, so we don't need result_index to check a boolean guard.
191  if (!bindings_->has_fwd_before()) {
192  // We need to evaluate forward before.
193  if (fwd_before_guard_index == -1)
194  // None of the backward guards assigns the variable for forward before.
195  return false;
196  if (!evaluate(guard_set_index + fwd_before_guard_index))
197 #if 1 // Debug: temporary solution to handle dependecies among guards. The full solution would recurse through the guards.
198  {
199  // This may depend on forward after, so try evaluating it first.
200  if (fwd_after_guard_index == -1)
201  // None of the backward guards assigns the variable for forward after.
202  return false;
203  if (!evaluate(guard_set_index + fwd_after_guard_index))
204  return false;
205  // Now try again to evaluate forward before.
206  if (!evaluate(guard_set_index + fwd_before_guard_index))
207  return false;
208  }
209 #else
210  return false;
211 #endif
212  }
213 
214  if (!bindings_->has_fwd_after()) {
215  // We need to evaluate forward after.
216  if (fwd_after_guard_index == -1)
217  // None of the backward guards assigns the variable for forward after.
218  return false;
219  if (!evaluate(guard_set_index + fwd_after_guard_index))
220  return false;
221  }
222 
223  return true;
224 }
225 
226 bool HLPOverlay::scan_bwd_guards() const {
227 
228  uint16 guard_set_index = code_[HLP_BWD_GUARDS].asIndex();
229  uint16 guard_count = code_[guard_set_index].getAtomCount();
230  for (uint16 i = 1; i <= guard_count; ++i) {
231 
232  uint16 index = guard_set_index + i;
233  Atom a = code_[index];
234  switch (a.getDescriptor()) {
235  case Atom::I_PTR:
236  if (!scan_location(a.asIndex(), index))
237  return false;
238  break;
239  case Atom::ASSIGN_PTR:
240  // If scan_location fails, then succeed if the assignment variable is already bound.
241  if (!scan_location(a.asIndex(), index) && !bindings_->scan_variable(a.asAssignmentIndex()))
242  return false;
243  break;
244  }
245  }
246  return true;
247 }
248 
249 bool HLPOverlay::scan_location(uint16 index, uint16 parent_guard_index) const {
250 
251  Atom a = code_[index];
252  switch (a.getDescriptor()) {
253  case Atom::I_PTR:
254  return scan_location(a.asIndex(), parent_guard_index);
255  case Atom::ASSIGN_PTR:
256  return scan_location(a.asIndex(), parent_guard_index);
257  case Atom::VL_PTR:
258  if (bindings_->scan_variable(a.asIndex()))
259  return true;
260  else
261  return scan_variable(a.asIndex(), parent_guard_index);
262  case Atom::OPERATOR: {
263  uint16 atom_count = a.getAtomCount();
264  for (uint16 j = 1; j <= atom_count; ++j) {
265 
266  if (!scan_location(index + j, parent_guard_index))
267  return false;
268  }
269  return true;
270  }
271  default:
272  return true;
273  }
274 }
275 
276 bool HLPOverlay::scan_variable(uint16 index, uint16 parent_guard_index) const { // check if the variable can be bound.
277 
278  uint16 guard_set_index = code_[HLP_BWD_GUARDS].asIndex();
279  uint16 guard_count = code_[guard_set_index].getAtomCount();
280  for (uint16 i = 1; i <= guard_count; ++i) {
281 
282  uint16 guard_index = guard_set_index + i;
283  Atom a = code_[guard_index];
284  switch (a.getDescriptor()) {
285  case Atom::ASSIGN_PTR:
286  if (a.asAssignmentIndex() == index) {
287  if (guard_index == parent_guard_index)
288  // Prevent loops.
289  return false;
290  return scan_location(a.asIndex(), guard_index);
291  }
292  break;
293  }
294  }
295 
296  return false;
297 }
298 
299 Code *HLPOverlay::get_unpacked_object() const {
300 
301  return ((HLPController *)controller_)->get_unpacked_object();
302 }
303 
304 void HLPOverlay::store_evidence(_Fact *evidence, bool prediction, bool is_simulation) {
305 
306  if (prediction) {
307 
308  if (!is_simulation)
309  ((HLPController *)controller_)->store_predicted_evidence(evidence);
310  } else
311  ((HLPController *)controller_)->store_evidence(evidence);
312 }
313 }
r_code::Atom
Definition: atom.h:104
r_code::Code
Definition: r_code/object.h:224
r_exec::HLPOverlay::evaluate
bool evaluate(uint16 index)
Definition: hlp_overlay.cpp:160
r_exec::HLPBindingMap
Definition: binding_map.h:393
r_exec::HLPOverlay
Definition: hlp_overlay.h:98
r_exec::Controller
Definition: controller.h:104
r_exec::HLPContext
Definition: hlp_context.h:97