AERA
factory.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 "factory.h"
86 #include "mdl_controller.h"
87 #include "mem.h"
88 
89 using namespace std;
90 using namespace std::chrono;
91 using namespace r_code;
92 
93 namespace r_exec {
94 
95 MkNew::MkNew(r_code::Mem *m, Code *object) : LObject(m) {
96 
97  uint16 write_index = 0;
98  code(write_index++) = Atom::Marker(Opcodes::MkNew, 2);
99  code(write_index++) = Atom::RPointer(0); // object.
100  code(write_index++) = Atom::Float(0); // psln_thr.
101  set_reference(0, object);
102 }
103 
105 
106 MkLowRes::MkLowRes(r_code::Mem *m, Code *object) : LObject(m) {
107 
108  uint16 write_index = 0;
109  code(write_index++) = Atom::Marker(Opcodes::MkLowRes, 2);
110  code(write_index++) = Atom::RPointer(0); // object.
111  code(write_index++) = Atom::Float(0); // psln_thr.
112  set_reference(0, object);
113 }
114 
116 
117 MkLowSln::MkLowSln(r_code::Mem *m, Code *object) : LObject(m) {
118 
119  uint16 write_index = 0;
120  code(write_index++) = Atom::Marker(Opcodes::MkLowSln, 2);
121  code(write_index++) = Atom::RPointer(0); // object.
122  code(write_index++) = Atom::Float(0); // psln_thr.
123  set_reference(0, object);
124 }
125 
127 
128 MkHighSln::MkHighSln(r_code::Mem *m, Code *object) : LObject(m) {
129 
130  uint16 write_index = 0;
131  code(write_index++) = Atom::Marker(Opcodes::MkHighSln, 2);
132  code(write_index++) = Atom::RPointer(0); // object.
133  code(write_index++) = Atom::Float(0); // psln_thr.
134  set_reference(0, object);
135 }
136 
138 
139 MkLowAct::MkLowAct(r_code::Mem *m, Code *object) : LObject(m) {
140 
141  uint16 write_index = 0;
142  code(write_index++) = Atom::Marker(Opcodes::MkLowAct, 2);
143  code(write_index++) = Atom::RPointer(0); // object.
144  code(write_index++) = Atom::Float(0); // psln_thr.
145  set_reference(0, object);
146 }
147 
149 
150 MkHighAct::MkHighAct(r_code::Mem *m, Code *object) : LObject(m) {
151 
152  uint16 write_index = 0;
153  code(write_index++) = Atom::Marker(Opcodes::MkHighAct, 2);
154  code(write_index++) = Atom::RPointer(0); // object.
155  code(write_index++) = Atom::Float(0); // psln_thr.
156  set_reference(0, object);
157 }
158 
160 
161 MkSlnChg::MkSlnChg(r_code::Mem *m, Code *object, float32 value) : LObject(m) {
162 
163  uint16 write_index = 0;
164  code(write_index++) = Atom::Marker(Opcodes::MkSlnChg, 3);
165  code(write_index++) = Atom::RPointer(0); // object.
166  code(write_index++) = Atom::Float(value); // change.
167  code(write_index++) = Atom::Float(0); // psln_thr.
168  set_reference(0, object);
169 }
170 
172 
173 MkActChg::MkActChg(r_code::Mem *m, Code *object, float32 value) : LObject(m) {
174 
175  uint16 write_index = 0;
176  code(write_index++) = Atom::Marker(Opcodes::MkActChg, 3);
177  code(write_index++) = Atom::RPointer(0); // object.
178  code(write_index++) = Atom::Float(value); // change.
179  code(write_index++) = Atom::Float(0); // psln_thr.
180  set_reference(0, object);
181 }
182 
184 
185 _Fact::_Fact() : LObject() {
186 }
187 
188 _Fact::_Fact(SysObject *source) : LObject(source) {
189 }
190 
191 _Fact::_Fact(_Fact *f) {
192 
193  for (uint16 i = 0; i < f->code_size(); ++i)
194  code(i) = f->code(i);
195  for (uint16 i = 0; i < f->references_size(); ++i)
196  add_reference(f->get_reference(i));
197 }
198 
199 _Fact::_Fact(uint16 opcode, Code *object, Timestamp after, Timestamp before, float32 confidence, float32 psln_thr) : LObject() {
200 
201  code(0) = Atom::Object(opcode, FACT_ARITY);
202  code(FACT_OBJ) = Atom::RPointer(0);
203  code(FACT_AFTER) = Atom::IPointer(FACT_ARITY + 1);
204  code(FACT_BEFORE) = Atom::IPointer(FACT_ARITY + 4);
205  code(FACT_CFD) = Atom::Float(confidence);
206  code(FACT_ARITY) = Atom::Float(psln_thr);
207  Utils::SetTimestamp<Code>(this, FACT_AFTER, after);
208  Utils::SetTimestamp<Code>(this, FACT_BEFORE, before);
209  add_reference(object);
210 }
211 
212 _Fact *_Fact::get_absentee() const {
213 
214  _Fact *absentee;
215  if (is_fact())
216  absentee = new AntiFact(get_reference(0), get_after(), get_before(), 1, 1);
217  else
218  absentee = new Fact(get_reference(0), get_after(), get_before(), 1, 1);
219 
220  return absentee;
221 }
222 
223 bool _Fact::is_invalidated() {
224 
225  if (LObject::is_invalidated())
226  return true;
227  if (get_reference(0)->is_invalidated()) {
228 
229  invalidate();
230  return true;
231  }
232  return false;
233 }
234 
235 bool _Fact::match_timings_sync(const _Fact *evidence) const { // intervals of the form [after,before].
236 
237  auto after = get_after();
238  auto e_after = evidence->get_after();
239  auto e_before = evidence->get_before();
240 
241  return !(e_after > after + Utils::GetTimeTolerance() || e_before <= after);
242 }
243 
244 bool _Fact::match_timings_overlap(const _Fact *evidence) const { // intervals of the form [after,before].
245 
246  auto after = get_after();
247  auto before = get_before();
248  auto e_after = evidence->get_after();
249  auto e_before = evidence->get_before();
250 
251  return !(e_after >= before || e_before <= after);
252 }
253 
254 bool _Fact::match_timings_inclusive(const _Fact *evidence) const { // intervals of the form [after,before].
255 
256  auto after = get_after();
257  auto before = get_before();
258  auto e_after = evidence->get_after();
259  auto e_before = evidence->get_before();
260 
261  return (e_after <= after && e_before >= before);
262 }
263 
264 bool _Fact::Match(const Code *lhs, uint16 lhs_base_index, uint16 lhs_index, const Code *rhs, uint16 rhs_index, uint16 lhs_arity, bool same_binding_state) {
265 
266  uint16 lhs_full_index = lhs_base_index + lhs_index;
267  Atom lhs_atom = lhs->code(lhs_full_index);
268  Atom rhs_atom = rhs->code(rhs_index);
269  uint8 lhs_descriptor = lhs_atom.getDescriptor();
270  uint8 rhs_descriptor = rhs_atom.getDescriptor();
271 
272  if (same_binding_state) {
273  if (lhs_descriptor == Atom::T_WILDCARD || lhs_descriptor == Atom::WILDCARD ||
274  rhs_descriptor == Atom::T_WILDCARD || rhs_descriptor == Atom::WILDCARD) {
275  // A wildcard will match anything including a variable when it becomes bound.
276  }
277  else {
278  bool lhs_is_VL_PTR = (lhs_descriptor == Atom::VL_PTR);
279  bool rhs_is_VL_PTR = (rhs_descriptor == Atom::VL_PTR);
280  if (lhs_is_VL_PTR != rhs_is_VL_PTR)
281  // Not the same binding state.
282  return false;
283  }
284  }
285 
286  switch (lhs_descriptor) {
287  case Atom::T_WILDCARD:
288  case Atom::WILDCARD:
289  case Atom::VL_PTR:
290  break;
291  case Atom::I_PTR:
292  switch (rhs_descriptor) {
293  case Atom::I_PTR:
294  if (!MatchStructure(lhs, lhs_atom.asIndex(), 0, rhs, rhs_atom.asIndex(), same_binding_state))
295  return false;
296  break;
297  case Atom::T_WILDCARD:
298  case Atom::WILDCARD:
299  case Atom::VL_PTR:
300  break;
301  default:
302  return false;
303  }
304  break;
305  case Atom::R_PTR:
306  switch (rhs_descriptor) {
307  case Atom::R_PTR:
308  if (!MatchObject(lhs->get_reference(lhs_atom.asIndex()), rhs->get_reference(rhs_atom.asIndex()), same_binding_state))
309  return false;
310  break;
311  case Atom::T_WILDCARD:
312  case Atom::WILDCARD:
313  case Atom::VL_PTR:
314  break;
315  default:
316  return false;
317  }
318  break;
319  default:
320  switch (rhs_descriptor) {
321  case Atom::T_WILDCARD:
322  case Atom::WILDCARD:
323  case Atom::VL_PTR:
324  break;
325  default:
326  if (!MatchAtom(lhs_atom, rhs_atom))
327  return false;
328  break;
329  }
330  break;
331  }
332 
333  if (lhs_index == lhs_arity)
334  return true;
335  return Match(lhs, lhs_base_index, lhs_index + 1, rhs, rhs_index + 1, lhs_arity, same_binding_state);
336 }
337 
338 bool _Fact::MatchAtom(Atom lhs, Atom rhs) {
339 
340  if (lhs == rhs)
341  return true;
342 
343  if (lhs.isFloat() && rhs.isFloat())
344  return Utils::Equal(lhs.asFloat(), rhs.asFloat());
345 
346  return false;
347 }
348 
349 bool _Fact::MatchStructure(const Code *lhs, uint16 lhs_base_index, uint16 lhs_index, const Code *rhs, uint16 rhs_index, bool same_binding_state) {
350 
351  uint16 lhs_full_index = lhs_base_index + lhs_index;
352  Atom lhs_atom = lhs->code(lhs_full_index);
353  Atom rhs_atom = rhs->code(rhs_index);
354  if (lhs_atom != rhs_atom)
355  return false;
356  uint16 arity = lhs_atom.getAtomCount();
357  if (arity == 0) // empty sets.
358  return true;
359  if (lhs_atom.getDescriptor() == Atom::TIMESTAMP)
360  return Utils::Synchronous(Utils::GetTimestamp(&lhs->code(lhs_full_index)), Utils::GetTimestamp(&rhs->code(rhs_index)));
361  return Match(lhs, lhs_base_index, lhs_index + 1, rhs, rhs_index + 1, arity, same_binding_state);
362 }
363 
364 bool _Fact::MatchObject(const Code *lhs, const Code *rhs, bool same_binding_state) {
365 
366  if (lhs->code(0) != rhs->code(0))
367  return false;
368  uint16 lhs_opcode = lhs->code(0).asOpcode();
369  if (lhs_opcode == Opcodes::Ent ||
370  lhs_opcode == Opcodes::Ont ||
371  lhs_opcode == Opcodes::Mdl ||
372  lhs_opcode == Opcodes::Cst)
373  return lhs == rhs;
374  return Match(lhs, 0, 1, rhs, 1, lhs->code(0).getAtomCount(), same_binding_state);
375 }
376 
377 bool _Fact::CounterEvidence(const Code *lhs, const Code *rhs) {
378 
379  uint16 opcode = lhs->code(0).asOpcode();
380  if (opcode == Opcodes::Ent ||
381  opcode == Opcodes::Ont ||
382  opcode == Opcodes::IMdl)
383  return false;
384  if (lhs->code(0) != rhs->code(0))
385  return false;
386  if (opcode == Opcodes::MkVal) {
387 
388  if (lhs->get_reference(lhs->code(MK_VAL_OBJ).asIndex()) == rhs->get_reference(rhs->code(MK_VAL_OBJ).asIndex()) &&
389  lhs->get_reference(lhs->code(MK_VAL_ATTR).asIndex()) == rhs->get_reference(rhs->code(MK_VAL_ATTR).asIndex())) { // same attribute for the same object; value_: r_ptr, atomic value or structure.
390 
391  Atom lhs_atom = lhs->code(MK_VAL_VALUE);
392  Atom rhs_atom = rhs->code(MK_VAL_VALUE);
393 
394  if (lhs_atom.isFloat()) {
395 
396  if (rhs_atom.isFloat())
397  return !MatchAtom(lhs_atom, rhs_atom);
398  else
399  return false;
400  } else if (rhs_atom.isFloat())
401  return false;
402 
403  uint16 lhs_desc = lhs_atom.getDescriptor();
404  uint16 rhs_desc = rhs_atom.getDescriptor();
405 
406  if (lhs_desc == Atom::NIL && rhs_desc == Atom::R_PTR ||
407  lhs_desc == Atom::R_PTR && rhs_desc == Atom::NIL)
408  // nil is counter-evidence of a referenced object.
409  return true;
410 
411  if (lhs_desc != rhs_desc) // values of different types.
412  return false;
413  switch (lhs_desc) {
414  case Atom::T_WILDCARD:
415  case Atom::WILDCARD:
416  return false;
417  case Atom::R_PTR:
418  return !MatchObject(lhs->get_reference(lhs->code(MK_VAL_VALUE).asIndex()), rhs->get_reference(rhs->code(MK_VAL_VALUE).asIndex()));
419  case Atom::I_PTR:
420  return !MatchStructure(lhs, lhs_atom.asIndex(), 0, rhs, rhs_atom.asIndex(), false);
421  default:
422  return !MatchAtom(lhs_atom, rhs_atom);
423  }
424  }
425  } else if (opcode == Opcodes::ICst) {
426 
427  if (lhs->get_reference(0) != rhs->get_reference(0)) // check if the icsts instantiate the same cst.
428  return false;
429 
430  for (uint32 i = 0; i < ((ICST *)lhs)->components_.size(); ++i) { // compare all components 2 by 2.
431 
432  // JTNote: This assumes that the components_ in the lhs and rhs are in the same order.
433  if (CounterEvidence(((ICST *)lhs)->components_[i], ((ICST *)rhs)->components_[i]))
434  return true;
435  }
436  }
437 
438  return false;
439 }
440 
441 MatchResult _Fact::is_evidence(const _Fact *target) const {
442 
443  if (MatchObject(get_reference(0), target->get_reference(0))) {
444 
445  MatchResult r;
446  if (target->code(0) == code(0))
447  r = MATCH_SUCCESS_POSITIVE;
448  else
449  r = MATCH_SUCCESS_NEGATIVE;
450 
451  if (target->match_timings_overlap(this))
452  return r;
453  } else if (is_fact()) { // check for a counter-evidence only if the evidence is a fact.
454 
455  if (target->match_timings_inclusive(this)) { // check timings first as this is less expensive than the counter-evidence check.
456 
457  if (CounterEvidence(get_reference(0), target->get_reference(0)))
458  // If the target is an anti-fact, then counter-evidence is a positive success.
459  return target->is_anti_fact() ? MATCH_SUCCESS_POSITIVE : MATCH_SUCCESS_NEGATIVE;
460  }
461  }
462  return MATCH_FAILURE;
463 }
464 
465 MatchResult _Fact::is_timeless_evidence(const _Fact *target) const {
466 
467  if (MatchObject(get_reference(0), target->get_reference(0))) {
468 
469  MatchResult r;
470  if (target->code(0) == code(0))
471  r = MATCH_SUCCESS_POSITIVE;
472  else
473  r = MATCH_SUCCESS_NEGATIVE;
474 
475  return r;
476  } else if (target->code(0) == code(0)) { // check for a counter-evidence only if the evidence is a fact.
477 
478  if (CounterEvidence(get_reference(0), target->get_reference(0)))
479  // If the target is an anti-fact, then counter-evidence is a positive success.
480  return target->is_anti_fact() ? MATCH_SUCCESS_POSITIVE : MATCH_SUCCESS_NEGATIVE;
481  }
482  return MATCH_FAILURE;
483 }
484 
485 Timestamp _Fact::get_after() const {
486 
487  return Utils::GetTimestamp<Code>(this, FACT_AFTER);
488 }
489 
490 Timestamp _Fact::get_before() const {
491 
492  return Utils::GetTimestamp<Code>(this, FACT_BEFORE);
493 }
494 
495 void _Fact::trace() const {
496 
497  std::cout << "<" << get_oid() << " " << Utils::RelativeTime(get_after()) << " " << Utils::RelativeTime(get_before()) << ">" << std::endl;
498 }
499 
501 
502 void *Fact::operator new(size_t s) {
503 
504  return _Mem::Get()->_build_object(Atom::Object(Opcodes::Fact, FACT_ARITY));
505 }
506 
507 Fact::Fact() : _Fact() {
508 
509  code(0) = Atom::Object(Opcodes::Fact, FACT_ARITY);
510 }
511 
512 Fact::Fact(SysObject *source) : _Fact(source) {
513 }
514 
515 Fact::Fact(Fact *f) : _Fact(f) {
516 }
517 
518 Fact::Fact(Code *object, Timestamp after, Timestamp before, float32 confidence, float32 psln_thr) : _Fact(Opcodes::Fact, object, after, before, confidence, psln_thr) {
519 }
520 
522 
523 void *AntiFact::operator new(size_t s) {
524 
525  return _Mem::Get()->_build_object(Atom::Object(Opcodes::AntiFact, FACT_ARITY));
526 }
527 
528 AntiFact::AntiFact() : _Fact() {
529 
530  code(0) = Atom::Object(Opcodes::AntiFact, FACT_ARITY);
531 }
532 
533 AntiFact::AntiFact(SysObject *source) : _Fact(source) {
534 }
535 
536 AntiFact::AntiFact(AntiFact *f) : _Fact(f) {
537 }
538 
539 AntiFact::AntiFact(Code *object, Timestamp after, Timestamp before, float32 confidence, float32 psln_thr) : _Fact(Opcodes::AntiFact, object, after, before, confidence, psln_thr) {
540 }
541 
543 
544 Pred::Pred() : LObject(), is_promoted_(false) {
545 }
546 
547 Pred::Pred(SysObject *source) : LObject(source), is_promoted_(false) {
548 }
549 
550 Pred::Pred(_Fact *target, const Pred* simulations_source, float32 psln_thr) : LObject() {
551  vector<P<Sim>> simulations_copy;
552  for (uint16 i = 0; i < simulations_source->get_simulations_size(); ++i)
553  simulations_copy.push_back(simulations_source->get_simulation(i));
554  construct(target, simulations_copy, psln_thr);
555  defeasible_validities_ = simulations_source->defeasible_validities_;
556 }
557 
558 void Pred::construct(_Fact *target, const vector<P<Sim> >& simulations, float32 psln_thr) {
559 
560  uint16 write_index = PRED_ARITY;
561  code(0) = Atom::Object(Opcodes::Pred, PRED_ARITY);
562  code(PRED_TARGET) = Atom::RPointer(0);
563  add_reference(target);
564 
565  code(PRED_SIMS) = Atom::IPointer(++write_index);
566  code(write_index) = Atom::Set(simulations.size());
567  for (auto i = 0; i < simulations.size(); ++i) {
568  code(++write_index) = Atom::RPointer(references_size());
569  add_reference(simulations[i]);
570  }
571 
572  code(PRED_ARITY) = Atom::Float(psln_thr);
573  is_promoted_ = false;
574 }
575 
577 
578  if (LObject::is_invalidated())
579  return true;
580  for (uint16 i = 0; i < get_simulations_size(); ++i) {
581 
582  if (get_simulation(i)->is_invalidated()) {
583 
584  invalidate();
585  return true;
586  }
587  }
588  for (uint32 i = 0; i < grounds_.size(); ++i) {
589 
590  if (grounds_[i]->is_invalidated()) {
591 
592  invalidate();
593  return true;
594  }
595  }
596 
597  for (auto d = defeasible_validities_.begin(); d != defeasible_validities_.end(); ++d) {
598  if ((*d)->is_invalidated()) {
599  invalidate();
600  return true;
601  }
602  }
603 
604  if (get_reference(0)->is_invalidated()) {
605 
606  invalidate();
607  return true;
608  }
609  return false;
610 }
611 
612 bool Pred::grounds_invalidated(_Fact *evidence) {
613 
614  for (uint32 i = 0; i < grounds_.size(); ++i) {
615 
616  switch (evidence->is_evidence(grounds_[i])) {
617  case MATCH_SUCCESS_NEGATIVE:
618  return true;
619  default:
620  break;
621  }
622  }
623  return false;
624 }
625 
627 
628  for (uint16 i = 0; i < get_simulations_size(); ++i) {
629 
630  auto sim = get_simulation(i);
631  if (sim->root_ == root)
632  return sim;
633  }
634 
635  return NULL;
636 }
637 
638 bool Pred::has_simulation(Sim* sim) const
639 {
640  for (uint16 i = 0; i < get_simulations_size(); ++i) {
641  if (get_simulation(i) == sim)
642  return true;
643  }
644 
645  return false;
646 }
647 
649 
650 Goal::Goal() : LObject(), ground_(NULL) {
651 }
652 
653 Goal::Goal(SysObject *source) : LObject(source), ground_(NULL) {
654 }
655 
656 Goal::Goal(_Fact *target, Code *actor, Sim* sim, float32 psln_thr) : LObject(), ground_(NULL) {
657 
658  code(0) = Atom::Object(Opcodes::Goal, GOAL_ARITY);
659  code(GOAL_TARGET) = Atom::RPointer(0);
660  code(GOAL_ACTR) = Atom::RPointer(1);
661  code(GOAL_SIM) = (sim ? Atom::RPointer(2) : Atom::Nil());
662  code(GOAL_ARITY) = Atom::Float(psln_thr);
663  add_reference(target);
664  add_reference(actor);
665  if (sim)
666  add_reference(sim);
667 }
668 
669 bool Goal::invalidate() { // return false when was not invalidated, true otherwise.
670 
671  if (has_sim())
672  get_sim()->invalidate();
673  return LObject::invalidate();
674 }
675 
676 bool Goal::is_invalidated() {
677 
678  if (LObject::is_invalidated())
679  return true;
680  if (has_sim() && get_sim()->get_f_super_goal()->is_invalidated()) {
681 
682  invalidate();
683  return true;
684  }
685  return false;
686 }
687 
688 bool Goal::ground_invalidated(_Fact *evidence) {
689 
690  if (ground_ != NULL)
691  return ground_->get_pred()->grounds_invalidated(evidence);
692  return false;
693 }
694 
695 bool Goal::is_requirement() const {
696 
697  if (has_sim() && get_sim()->is_requirement_)
698  return true;
699  return false;
700 }
701 
702 bool Goal::is_self_goal() const {
703 
704  return (get_actor() == _Mem::Get()->get_self());
705 }
706 
708 
709 Sim::Sim(Sim *s) : root_(s->root_), solution_controller_(s->solution_controller_), is_requirement_(false) {
710  for (uint16 i = 0; i < s->code_size(); ++i)
711  code(i) = s->code(i);
712  for (uint16 i = 0; i < s->references_size(); ++i)
713  add_reference(s->get_reference(i));
714 }
715 
716 Sim::Sim(SimMode mode, microseconds thz, Fact *super_goal, bool opposite, Controller *root, float32 psln_thr, Controller *solution_controller,
717  float32 solution_cfd, Timestamp solution_before) : root_(root), solution_controller_(solution_controller), is_requirement_(false) {
718  code(0) = Atom::Object(Opcodes::Sim, SIM_ARITY);
719  code(SIM_MODE) = Atom::Float(mode);
720  code(SIM_THZ) = Atom::IPointer(SIM_ARITY + 1);
721  code(SIM_F_SUPER_GOAL) = Atom::RPointer(0);
722  add_reference(super_goal);
723  code(SIM_OPPOSITE) = Atom::Boolean(opposite);
724 
725  // Special case: Put the controller's model in the code so that it appears in the decompiled output,
726  // otherwise the C++ code doesn't look at these objects.
727  // This only works because the seed code never creates a sim object or changes its controllers.
728  if (root) {
729  code(SIM_ROOT_MODEL) = Atom::RPointer(references_size());
730  add_reference(root->get_core_object());
731  }
732  else
733  code(SIM_ROOT_MODEL) = Atom::Nil();
734  if (solution_controller) {
735  code(SIM_SOLUTION_MODEL) = Atom::RPointer(references_size());
736  add_reference(solution_controller->get_core_object());
737  }
738  else
739  code(SIM_SOLUTION_MODEL) = Atom::Nil();
740 
741  code(SIM_SOLUTION_CFD) = Atom::Float(solution_cfd);
742  code(SIM_SOLUTION_BEFORE) = Atom::IPointer(SIM_ARITY + 4);
743  code(SIM_ARITY) = Atom::Float(psln_thr);
744 
745  Utils::SetDuration<Code>(this, SIM_THZ, thz);
746  Utils::SetTimestamp<Code>(this, SIM_SOLUTION_BEFORE, solution_before);
747 }
748 
749 bool Sim::invalidate() {
750 
751  if (LObject::is_invalidated())
752  return true;
753  if (get_f_super_goal()->is_invalidated())
754  return true;
755 
756  return LObject::invalidate();
757 }
758 
759 bool Sim::is_invalidated() {
760 
761  if (LObject::is_invalidated())
762  return true;
763  if (get_f_super_goal()->is_invalidated()) {
764 
765  invalidate();
766  return true;
767  }
768  return false;
769 }
770 
772 {
773  Sim* result = this;
774  while (result) {
775  if (result->get_mode() == SIM_ROOT)
776  return result;
777 
778  result = result->get_f_super_goal()->get_goal()->get_sim();
779  }
780 
781  // A goal had a NULL Sim object. This shouldn't happen.
782  return NULL;
783 }
784 
786  Sim* rootSim = get_root_sim();
787  if (!rootSim)
788  // We don't expect this. Return true so that f_obj is injected as a goal anyway.
789  return true;
790 
791  uint16 opcode = f_obj->code(0).asOpcode();
792  Code* obj = f_obj->get_reference(0);
793  // Debug: Do we need a critical section for this?
794  for (int i = 0; i < rootSim->goalTargets_.size(); ++i) {
795  _Fact* goalTarget = rootSim->goalTargets_[i];
796  // TODO: Actually match timings. For now, ignore timings and just check the fact opcode and match the object.
797  if (opcode == goalTarget->code(0).asOpcode() && _Fact::MatchObject(obj, goalTarget->get_reference(0), true))
798  // Already registered.
799  return false;
800  }
801 
802  rootSim->goalTargets_.push_back(f_obj);
803  return true;
804 }
805 
807  for (auto d = list.begin(); d != list.end(); ++d) {
808  if (original_fact == d->original_fact_)
809  return true;
810  }
811 
812  return false;
813 }
814 
815 
817 
818 MkRdx::MkRdx() : LObject(), bindings_(NULL) {
819 }
820 
821 MkRdx::MkRdx(SysObject *source) : LObject(source), bindings_(NULL) {
822 }
823 
824 MkRdx::MkRdx(Code *imdl_fact, Code *input, Code *output, float32 psln_thr, BindingMap *binding_map) : LObject(), bindings_(binding_map) {
825 
826  uint16 extent_index = MK_RDX_ARITY + 1;
827  code(0) = Atom::Marker(Opcodes::MkRdx, MK_RDX_ARITY);
828  code(MK_RDX_CODE) = Atom::RPointer(references_size()); // code.
829  add_reference(imdl_fact);
830  code(MK_RDX_INPUTS) = Atom::IPointer(extent_index); // inputs.
831  code(MK_RDX_ARITY) = Atom::Float(psln_thr);
832  code(extent_index++) = Atom::Set(1); // set of one input.
833  code(extent_index++) = Atom::RPointer(references_size());
834  add_reference(input);
835  code(MK_RDX_PRODS) = Atom::IPointer(extent_index); // set of one production.
836  code(extent_index++) = Atom::Set(1);
837  code(extent_index++) = Atom::RPointer(references_size());
838  add_reference(output);
839 }
840 
841 MkRdx::MkRdx(Code *imdl_fact, Code *input1, Code *input2, Code *output, float32 psln_thr, BindingMap *binding_map) : LObject(), bindings_(binding_map) {
842 
843  uint16 extent_index = MK_RDX_ARITY + 1;
844  code(0) = Atom::Marker(Opcodes::MkRdx, MK_RDX_ARITY);
845  code(MK_RDX_CODE) = Atom::RPointer(references_size()); // code.
846  add_reference(imdl_fact);
847  code(MK_RDX_INPUTS) = Atom::IPointer(extent_index); // inputs.
848  code(MK_RDX_ARITY) = Atom::Float(psln_thr);
849  code(extent_index++) = Atom::Set(2); // set of two inputs.
850  code(extent_index++) = Atom::RPointer(references_size());
851  add_reference(input1);
852  if (input2) {
853  code(extent_index++) = Atom::RPointer(references_size());
854  add_reference(input2);
855  }
856  else
857  code(extent_index++) = Atom::Nil();
858  code(MK_RDX_PRODS) = Atom::IPointer(extent_index); // set of one production.
859  code(extent_index++) = Atom::Set(1);
860  code(extent_index++) = Atom::RPointer(references_size());
861  add_reference(output);
862 }
863 
865 
866 Success::Success() : LObject() {
867 }
868 
869 Success::Success(_Fact *object, _Fact *evidence, Code* object_mk_rdx, float32 psln_thr) : LObject() {
870 
871  code(0) = Atom::Object(Opcodes::Success, SUCCESS_ARITY);
872  code(SUCCESS_OBJ) = Atom::RPointer(references_size());
873  add_reference(object);
874 
875  if (evidence) {
876  code(SUCCESS_EVD) = Atom::RPointer(references_size());
877  add_reference(evidence);
878  }
879  else
880  code(SUCCESS_EVD) = Atom::Nil();
881 
882  if (object_mk_rdx) {
883  code(SUCCESS_OBJ_MK_RDX) = Atom::RPointer(references_size());
884  add_reference(object_mk_rdx);
885  }
886  else
887  code(SUCCESS_OBJ_MK_RDX) = Atom::Nil();
888 
889  code(SUCCESS_ARITY) = Atom::Float(psln_thr);
890 }
891 
893 
894 Perf::Perf() : LObject() {
895 }
896 
897 Perf::Perf(microseconds reduction_job_avg_latency, microseconds d_reduction_job_avg_latency, microseconds time_job_avg_latency, microseconds d_time_job_avg_latency) : LObject() {
898 
899  code(0) = Atom::Object(Opcodes::Perf, PERF_ARITY);
900  code(PERF_RDX_LTCY) = Atom::Float(reduction_job_avg_latency.count());
901  code(PERF_D_RDX_LTCY) = Atom::Float(d_reduction_job_avg_latency.count());
902  code(PERF_TIME_LTCY) = Atom::Float(time_job_avg_latency.count());
903  code(PERF_D_TIME_LTCY) = Atom::Float(d_time_job_avg_latency.count());
904  code(PERF_ARITY) = Atom::Float(1);
905 }
906 
908 
909 ICST::ICST() : LObject() {
910 }
911 
912 ICST::ICST(SysObject *source) : LObject(source) {
913 }
914 
915 bool ICST::is_invalidated() {
916 
917  if (LObject::is_invalidated()) {
918  return true; }
919  for (uint32 i = 0; i < components_.size(); ++i) {
920 
921  if (components_[i]->is_invalidated()) {
922 
923  invalidate();
924  return true;
925  }
926  }
927  return false;
928 }
929 
930 bool ICST::contains(const _Fact *component, uint16 &component_index) const {
931 
932  for (uint32 i = 0; i < components_.size(); ++i) {
933 
934  if (components_[i] == component) {
935 
936  component_index = i;
937  return true;
938  }
939  }
940 
941  return false;
942 }
943 
944 bool ICST::r_contains(const _Fact* component) const {
945 
946  for (auto i = components_.begin(); i != components_.end(); ++i) {
947  if (*i == component)
948  return true;
949 
950  if ((*i)->get_reference(0)->code(0).asOpcode() == Opcodes::ICst &&
951  ((ICST*)(*i)->get_reference(0))->r_contains(component))
952  return true;
953  }
954 
955  return false;
956 }
957 
958 }
r_exec::Pred::get_simulation
Sim * get_simulation(uint16 i) const
Definition: factory.h:468
r_exec::Sim::get_f_super_goal
Fact * get_f_super_goal() const
Definition: factory.h:266
r_exec::ICST::contains
bool contains(const _Fact *component, uint16 &component_index) const
Definition: factory.cpp:930
r_exec::ICST::r_contains
bool r_contains(const _Fact *component) const
Definition: factory.cpp:944
r_exec::Goal::get_sim
Sim * get_sim() const
Definition: factory.h:550
r_code::Atom
Definition: atom.h:104
r_exec::Sim
Definition: factory.h:248
r_exec::_Fact
Definition: factory.h:155
r_code::SysObject
Definition: r_code/object.h:136
r_exec::LObject
Definition: r_exec/object.h:195
r_exec::ICST
Definition: factory.h:655
core::P
Definition: base.h:103
r_exec::Sim::register_goal_target
bool register_goal_target(_Fact *f_obj)
Definition: factory.cpp:785
r_code::Code
Definition: r_code/object.h:224
r_exec::_Fact::MatchObject
static bool MatchObject(const r_code::Code *lhs, const r_code::Code *rhs, bool same_binding_state=false)
Definition: factory.cpp:364
r_exec::Sim::DefeasiblePromotedFact::has_original_fact
static bool has_original_fact(const r_code::list< DefeasiblePromotedFact > &list, const _Fact *original_fact)
Definition: factory.cpp:806
r_exec::Pred::get_simulations_size
uint16 get_simulations_size() const
Definition: factory.h:458
r_exec::Sim::get_root_sim
Sim * get_root_sim()
Definition: factory.cpp:771
r_exec::Pred
Definition: factory.h:394
r_exec::Pred::has_simulation
bool has_simulation(Sim *sim) const
Definition: factory.cpp:638
r_code::Mem
Definition: r_code/object.h:420
r_exec::Controller
Definition: controller.h:104
r_code::list
Definition: list.h:99
r_exec::Pred::is_invalidated
bool is_invalidated() override
Definition: factory.cpp:576
r_exec::Goal::has_sim
bool has_sim() const
Definition: factory.h:543