AERA
pgm_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 "pgm_controller.h"
86 #include "mem.h"
87 
88 using namespace r_code;
89 
90 namespace r_exec {
91 
92 _PGMController::_PGMController(_View *ipgm_view) : OController(ipgm_view) {
93 
94  run_once_ = !ipgm_view->object_->code(IPGM_RUN).asBoolean();
95 }
96 
97 _PGMController::~_PGMController() {
98 }
99 
101 
102 InputLessPGMController::InputLessPGMController(_View *ipgm_view) : _PGMController(ipgm_view) {
103 
104  overlays_.push_back(new InputLessPGMOverlay(this));
105 }
106 
107 InputLessPGMController::~InputLessPGMController() {
108 }
109 
110 void InputLessPGMController::signal_input_less_pgm() { // next job will be pushed by the rMem upon processing the current signaling job, i.e. right after exiting this function.
111 
112  reductionCS_.enter();
113  if (overlays_.size()) {
114 
115  InputLessPGMOverlay *overlay = (InputLessPGMOverlay *)overlays_.front();
116  overlay->inject_productions();
117  overlay->reset();
118 
119  if (!run_once_) {
120 
121  if (is_alive()) {
122 
123  Group *host = get_view()->get_host();
124  host->enter();
125  if (host->get_c_act() > host->get_c_act_thr() && // c-active group.
126  host->get_c_sln() > host->get_c_sln_thr()) { // c-salient group.
127 
128  host->leave();
129 
130  TimeJob *next_job = new InputLessPGMSignalingJob((r_exec::View*)view_, Now() + time_scope_);
131  _Mem::Get()->push_time_job(next_job);
132  } else
133  host->leave();
134  }
135  }
136  }
137  reductionCS_.leave();
138 
139  if (run_once_)
140  invalidate();
141 }
142 
144 
145 PGMController::PGMController(_View *ipgm_view) : _PGMController(ipgm_view) {
146 
147  overlays_.push_back(new PGMOverlay(this));
148 }
149 
150 PGMController::~PGMController() {
151 }
152 
153 void PGMController::notify_reduction() {
154 
155  if (run_once_)
156  invalidate();
157 }
158 
159 void PGMController::take_input(r_exec::View *input) {
160 
161  Controller::__take_input<PGMController>(input);
162 }
163 
164 void PGMController::reduce(r_exec::View *input) {
165 
166  r_code::list<P<Overlay> >::const_iterator o;
167  uint32 oid = input->object_->get_oid();
168  if (time_scope_.count() > 0) {
169 
170  reductionCS_.enter();
171  auto now = Now(); // call must be located after the CS.enter() since (*o)->reduce() may update (*o)->birth_time.
172  for (o = overlays_.begin(); o != overlays_.end();) {
173 
174  if ((*o)->is_invalidated())
175  o = overlays_.erase(o);
176  else {
177 
178  auto birth_time = ((PGMOverlay *)*o)->get_birth_time();
179  if (birth_time.time_since_epoch().count() > 0 && now - birth_time > time_scope_) {
180  o = overlays_.erase(o);
181  } else {
182  Overlay *offspring = (*o)->reduce(input);
183  if (offspring) {
184  overlays_.push_front(offspring);
185  }
186  if (!is_alive())
187  break;
188  ++o;
189  }
190  }
191  }
192  reductionCS_.leave();
193  } else {
194 
195  reductionCS_.enter();
196  for (o = overlays_.begin(); o != overlays_.end();) {
197 
198  if ((*o)->is_invalidated())
199  o = overlays_.erase(o);
200  else {
201 
202  Overlay *offspring = (*o)->reduce(input);
203  if (offspring)
204  overlays_.push_front(offspring);
205  if (!is_alive())
206  break;
207  ++o;
208  }
209 
210  }
211  reductionCS_.leave();
212  }
213 }
214 
216 
217 AntiPGMController::AntiPGMController(_View *ipgm_view) : _PGMController(ipgm_view), successful_match_(false) {
218 
219  overlays_.push_back(new AntiPGMOverlay(this));
220 }
221 
222 AntiPGMController::~AntiPGMController() {
223 }
224 
225 void AntiPGMController::take_input(r_exec::View *input) {
226 
227  Controller::__take_input<AntiPGMController>(input);
228 }
229 
230 void AntiPGMController::reduce(r_exec::View *input) {
231 
232  reductionCS_.enter();
233  r_code::list<P<Overlay> >::const_iterator o;
234  for (o = overlays_.begin(); o != overlays_.end();) {
235 
236  if ((*o)->is_invalidated())
237  o = overlays_.erase(o);
238  else {
239 
240  Overlay *offspring = (*o)->reduce(input);
241  if (successful_match_) { // the controller has been restarted: reset the overlay and kill all others
242 
243  Overlay *overlay = *o;
244  overlay->reset();
245  overlays_.clear();
246  overlays_.push_back(overlay);
247  successful_match_ = false;
248  break;
249  }
250  ++o;
251  if (offspring)
252  overlays_.push_front(offspring);
253  }
254  }
255  reductionCS_.leave();
256 }
257 
258 void AntiPGMController::signal_anti_pgm() {
259 
260  reductionCS_.enter();
261  if (successful_match_) // a signaling job has been spawn in restart(): we are here in an old job during which a positive match occurred: do nothing.
262  successful_match_ = false;
263  else { // no positive match during this job: inject productions and restart.
264 
265  Overlay *overlay = overlays_.front();
266  ((AntiPGMOverlay *)overlay)->inject_productions();
267  overlay->reset(); // reset the first overlay and kill all others.
268  if (!run_once_ && is_alive()) {
269 
270  overlays_.clear();
271  overlays_.push_back(overlay);
272  }
273  }
274  reductionCS_.leave();
275 
276  if (run_once_)
277  invalidate();
278 }
279 
280 void AntiPGMController::restart() { // one anti overlay matched all its inputs, timings and guards.
281 
282  push_new_signaling_job();
283  successful_match_ = true;
284 }
285 
286 void AntiPGMController::push_new_signaling_job() {
287 
288  Group *host = get_view()->get_host();
289  host->enter();
290  if (get_view()->get_act() > host->get_act_thr() && // active ipgm.
291  host->get_c_act() > host->get_c_act_thr() && // c-active group.
292  host->get_c_sln() > host->get_c_sln_thr()) { // c-salient group.
293 
294  host->leave();
295  TimeJob *next_job = new AntiPGMSignalingJob((r_exec::View*)view_, Now() + Utils::GetDuration<Code>(get_object(), IPGM_TSC));
296  _Mem::Get()->push_time_job(next_job);
297  } else
298  host->leave();
299 }
300 }
r_code::_View
Definition: r_code/object.h:164
r_exec::View
Definition: view.h:102
r_code::list
Definition: list.h:99