Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
init_soar.cpp
Go to the documentation of this file.
1 #include <portability.h>
2 #include "soar_rand.h" // provides SoarRand, a better random number generator (see bug 595)
3 
4 /*************************************************************************
5  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
6  * FOR LICENSE AND COPYRIGHT INFORMATION.
7  *************************************************************************/
8 
9 /*************************************************************************
10  *
11  * file: init_soar.cpp
12  *
13  * =======================================================================
14  * Routines for initializing Soar, signal handling (ctrl-c interrupt),
15  * exiting Soar (cleanup and error msgs), setting sysparams, and
16  * the core routines for "running" Soar (do_one_top_level_phase, etc.)
17  * =======================================================================
18  */
19 
20 #include "init_soar.h"
21 #include "agent.h"
22 #include "consistency.h"
23 #include "callback.h"
24 #include "agent.h"
25 #include "print.h"
26 #include "production.h"
27 #include "decide.h"
28 #include "recmem.h"
29 #include "explain.h"
30 #include "symtab.h"
31 #include "wmem.h"
32 #include "io_soar.h"
33 #include "rete.h"
34 #include "gdatastructs.h"
35 #include "xml.h"
36 #include "utilities.h"
37 
38 #include <assert.h>
39 #include <time.h>
40 
41 #include "reinforcement_learning.h"
42 #include "wma.h"
43 #include "episodic_memory.h"
44 #include "semantic_memory.h"
45 
46 /* REW: begin 08.20.97 these defined in consistency.c */
49 /* REW: end 08.20.97 */
50 
51 #if (defined(REAL_TIME_BEHAVIOR) || defined(ATTENTION_LAPSE))
52 /* RMJ; just a temporary variable, but we don't want to
53  reallocate it every time we process a phase, so we make it global
54  and allocate memory for it in init_soar() (init agent.c) */
55 struct timeval *current_real_time;
56 #endif
57 
58 #ifdef ATTENTION_LAPSE
59 /* RMJ; just a temporary variable, but we don't want to
60  reallocate it every time we process a phase, so we make it global */
61 int64_t lapse_duration;
62 #endif
63 
64 /* ===================================================================
65 
66  Exiting Soar
67 
68  Exit_soar() and abort_with_fatal_error(msg) both terminate Soar, closing
69  the log file before exiting. Abort_with_fatal_error(msg) also prints
70  an error message and tries to write a file before exiting.
71 =================================================================== */
72 
73 // JRV: these functions are no longer used with SML
74 //void just_before_exit_soar (agent* thisAgent) {
75 // soar_invoke_callbacks(thisAgent,
76 // SYSTEM_TERMINATION_CALLBACK,
77 // (soar_call_data) TRUE);
78 //}
79 
80 //void exit_soar (agent* thisAgent) {
84 // just_before_exit_soar(thisAgent);
85 // exit (0);
87 //}
88 
89 void abort_with_fatal_error (agent* thisAgent, const char *msg) {
90  FILE *f;
91  const char* warning = "Soar cannot recover from this error. \nYou will have to restart Soar to run an agent.\nData is still available for inspection, but may be corrupt.\nIf a log was open, it has been closed for safety.";
92 
93  print (thisAgent, "%s", msg);
94  print (thisAgent, "%s", warning);
95 
96  fprintf (stderr,"%s",msg);
97  fprintf (stderr,"%s",warning);
98 
99  xml_generate_error(thisAgent, msg);
100  xml_generate_error(thisAgent, warning);
101 
102  f = fopen("soarerror", "w");
103  fprintf (f,"%s",msg);
104  fprintf (f,"%s",warning);
105  fclose(f);
106 
107  assert(false);
108 
109  // Since we're no longer terminating, should we be invoking this event?
110  // Note that this is a soar callback, not a gSKI callback, so it isn't being used for now anyway
111  //soar_invoke_callbacks(thisAgent,
112  // SYSTEM_TERMINATION_CALLBACK,
113  // (soar_call_data) FALSE);
114 }
115 
116 /* ===================================================================
117 
118  Signal Handling
119 
120  Setup things so control_c_handler() gets control whenever the program
121  receives a SIGINT (e.g., from a ctrl-c at the keyboard). The handler
122  just sets the stop_soar flag.
123 =================================================================== */
124 
125 /* This is deprecated. -AJC (8/9/02) */
126 //char * c_interrupt_msg = "*** Ctrl-C Interrupt ***";
127 
128 /* AGR 581 The variable the_signal is not used at all, so I thought I
129  would remove it. Unfortunately, the signal command at the end of this
130  function requires a function name that has a single integer parameter.
131  It's probably some unix thing. So I left the variable in the parameter
132  list and instead changed the calling functions to use a parameter.
133  94.11.15 (although this was done a month or two earlier--this comment
134  was placed here in retrospect.) */
135 
136 /* Removed these because they are deprecated -AJC (8/6/02) */
137 
138 //void control_c_handler (int the_signal) {
140 //#ifndef _WINDOWS
141 //
142 // cons * c;
143 // agent * the_agent;
145 // for(c = thisKernel->all_soar_agents; c != NIL; c = c->rest) {
146 // the_agent = ((agent *) c->first);
147 // the_agent->stop_soar = TRUE;
148 // the_agent->reason_for_stopping = c_interrupt_msg;
149 // }
150 //*/
151 // /* --- reinstall this signal handler -- some brain-damaged OS's uninstall
152 // it after delivering the signal --- */
153 // signal (SIGINT, control_c_handler);
154 //
155 //#endif
156 
157 
158 //void setup_signal_handling (void) {
159 //#ifndef _WINDOWS
160 // if (signal(SIGINT, control_c_handler) == SIG_ERR) {
161 // fprintf(stderr, "setup_signal_handling: unable to install signal handler.\n");
162 // fprintf(stderr, " Ctrl-C will not interrupt Soar.\n");
163 // }
164 //
165 //#endif /* _WINDOWS */
166 
167 /* ===================================================================
168 
169  Sysparams
170 
171 =================================================================== */
172 
173 
174 void set_sysparam (agent* thisAgent, int param_number, int64_t new_value) {
175  if ((param_number < 0) || (param_number > HIGHEST_SYSPARAM_NUMBER)) {
176  print (thisAgent, "Internal error: tried to set bad sysparam #: %d\n", param_number);
177  return;
178  }
179  thisAgent->sysparams[param_number] = new_value;
180 
181  soar_invoke_callbacks(thisAgent,
183  reinterpret_cast<soar_call_data>(param_number));
184 }
185 
186 void init_sysparams (agent* thisAgent) {
187  int i;
188 
189  for (i=0; i<HIGHEST_SYSPARAM_NUMBER+1; i++) thisAgent->sysparams[i] = 0;
190 
191  /* --- set all params to zero, except the following: --- */
194  thisAgent->sysparams[TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM] = NONE_WME_TRACE; /* RPM 6/05 Changed from timetag to none */
197  thisAgent->sysparams[TRACE_LOADING_SYSPARAM] = TRUE; /* KJC 8/96 */
198  thisAgent->sysparams[MAX_ELABORATIONS_SYSPARAM] = 100;
199  thisAgent->sysparams[MAX_CHUNKS_SYSPARAM] = 50;
200  thisAgent->sysparams[MAX_NIL_OUTPUT_CYCLES_SYSPARAM] = 15;
201  thisAgent->sysparams[MAX_GOAL_DEPTH] = 100; /* generate an interrupt so users can recover before exceed program stack*/
202  thisAgent->sysparams[MAX_MEMORY_USAGE_SYSPARAM] = 100000000; /* default to 100MB. Event generated when exceeded*/
203 
204 //#ifdef USE_X_DISPLAY
205 // thisAgent->sysparams[RESPOND_TO_LOAD_ERRORS_SYSPARAM] = FALSE;
206 //#else
208 //#endif
209 
210 #ifdef ATTENTION_LAPSE
211  /* RMJ */
213 #endif /* ATTENTION_LAPSE */
214 
215  // voigtjr: turning learning off by default
216  thisAgent->sysparams[LEARNING_ON_SYSPARAM] = FALSE;
217 
218  thisAgent->sysparams[LEARNING_ONLY_SYSPARAM] = FALSE; /* AGR MVL1 */
219  thisAgent->sysparams[LEARNING_EXCEPT_SYSPARAM] = FALSE; /* KJC 8/96 */
223  thisAgent->sysparams[PRINT_WARNINGS_SYSPARAM] = TRUE;
224  thisAgent->sysparams[PRINT_ALIAS_SYSPARAM] = TRUE; /* AGR 627 */
225  thisAgent->sysparams[EXPLAIN_SYSPARAM] = FALSE; /* KJC 7/96 */
226  thisAgent->sysparams[USE_LONG_CHUNK_NAMES] = TRUE; /* kjh(B14) */
228  thisAgent->sysparams[TIMERS_ENABLED] = TRUE;
229 
230  // JRV: Chunk through local negations by default
232 
234 }
235 
236 /* ===================================================================
237 
238  Adding and Removing Pwatchs
239 
240  Productions_being_traced is a (consed) list of all productions
241  on which a pwatch has been set. Pwatchs are added/removed via
242  calls to add_pwatch() and remove_pwatch().
243 =================================================================== */
244 /* list of production structures */
245 
246 
247 void add_pwatch (agent* thisAgent, production *prod)
248 {
249  if (prod->trace_firings) return;
250  prod->trace_firings = TRUE;
251  push (thisAgent, prod, thisAgent->productions_being_traced);
252 }
253 
254 Bool remove_pwatch_test_fn (agent* /*thisAgent*/, cons *c,
255  void *prod_to_remove_pwatch_of)
256 {
257  return (c->first == static_cast<production *>(prod_to_remove_pwatch_of));
258 }
259 
260 void remove_pwatch (agent* thisAgent, production *prod) {
261  if (! prod->trace_firings) return;
262  prod->trace_firings = FALSE;
263  free_list (thisAgent,
264  extract_list_elements ( thisAgent,
265  &thisAgent->productions_being_traced,
266  remove_pwatch_test_fn, prod));
267 }
268 
269 /* ===================================================================
270 
271  Reinitializing Soar
272 
273  Reset_statistics() resets all the statistics (except the firing counts
274  on each individual production). Reinitialize_soar() does all the
275  work for an init-soar.
276 =================================================================== */
277 
279  int t;
280  production * p;
281 
282  for (t = 0; t < NUM_PRODUCTION_TYPES; t++) {
283  for (p = thisAgent->all_productions_of_type[t];
284  p != NIL;
285  p = p->next)
286  p->firing_count = 0;
287  }
288 }
289 
290 void reset_statistics (agent* thisAgent) {
291 
292  thisAgent->d_cycle_count = 0;
293  thisAgent->decision_phases_count = 0;
294  thisAgent->e_cycle_count = 0;
295  thisAgent->e_cycles_this_d_cycle = 0;
296  thisAgent->chunks_this_d_cycle = 0;
297  thisAgent->production_firing_count = 0;
298  thisAgent->start_dc_production_firing_count = 0;
299  thisAgent->wme_addition_count = 0;
300  thisAgent->wme_removal_count = 0;
301  thisAgent->max_wm_size = 0;
302 
303  thisAgent->start_dc_wme_addition_count = 0;
304  thisAgent->start_dc_wme_removal_count = 0;
305 
306  thisAgent->cumulative_wm_size = 0.0;
307  thisAgent->num_wm_sizes_accumulated = 0;
308 /* REW: begin 09.15.96 */
309  thisAgent->pe_cycle_count = 0;
310  thisAgent->pe_cycles_this_d_cycle = 0;
311 /* REW: end 09.15.96 */
312  thisAgent->d_cycle_last_output = 0; // KJC 11/17/05
313 
314  thisAgent->run_phase_count = 0 ;
315  thisAgent->run_elaboration_count = 0 ;
316  thisAgent->run_last_output_count = 0 ;
317  thisAgent->run_generated_output_count = 0 ;
318 
319  thisAgent->inner_e_cycle_count = 0;
320 
322 
323  reset_timers(thisAgent);
324  reset_max_stats(thisAgent);
325 
326  thisAgent->wma_timers->reset();
327  thisAgent->epmem_timers->reset();
328  thisAgent->smem_timers->reset();
329 
330  thisAgent->wma_d_cycle_count = 0;
331 }
332 
333 void reset_timers (agent* thisAgent) {
334 #ifndef NO_TIMING_STUFF
335  thisAgent->timers_cpu.reset();
336  thisAgent->timers_kernel.reset();
337  thisAgent->timers_phase.reset();
338 #ifdef DETAILED_TIMER_STATS
339  thisAgent->timers_gds.set_enabled(&(thisAgent->sysparams[TIMERS_ENABLED]));
340  thisAgent->timers_gds.reset();
341 #endif
342 
343  thisAgent->timers_total_cpu_time.reset();
344  thisAgent->timers_total_kernel_time.reset();
345  thisAgent->timers_input_function_cpu_time.reset();
346  thisAgent->timers_output_function_cpu_time.reset();
347 
348  for (int i=0;i < NUM_PHASE_TYPES; i++) {
349  thisAgent->timers_decision_cycle_phase[i].reset();
350  thisAgent->timers_monitors_cpu_time[i].reset();
351 #ifdef DETAILED_TIMER_STATS
352  thisAgent->timers_ownership_cpu_time[i].reset();
353  thisAgent->timers_chunking_cpu_time[i].reset();
354  thisAgent->timers_match_cpu_time[i].reset();
355  thisAgent->timers_gds_cpu_time[i].reset();
356 #endif
357  }
358 
359  thisAgent->last_derived_kernel_time_usec = 0;
360 #endif // NO_TIMING_STUFF
361 }
362 
363 void reset_max_stats (agent* thisAgent) {
366  thisAgent->max_dc_wm_changes_value = 0;
367  thisAgent->max_dc_wm_changes_cycle = 0;
368 #ifndef NO_TIMING_STUFF
369  thisAgent->max_dc_time_cycle = 0;
370  thisAgent->max_dc_time_usec = 0;
371 
372  thisAgent->max_dc_epmem_time_sec = 0;
373  thisAgent->total_dc_epmem_time_sec = -1;
374  thisAgent->max_dc_epmem_time_cycle = 0;
375 
376  thisAgent->max_dc_smem_time_sec = 0;
377  thisAgent->total_dc_smem_time_sec = -1;
378  thisAgent->max_dc_smem_time_cycle = 0;
379 #endif // NO_TIMING_STUFF
380 }
381 
382 bool reinitialize_soar (agent* thisAgent) {
383 
384  /* kjh (CUSP-B4) begin */
385  int64_t cur_TRACE_CONTEXT_DECISIONS_SYSPARAM;
386  int64_t cur_TRACE_PHASES_SYSPARAM;
387  int64_t cur_TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM;
388  int64_t cur_TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM;
389  int64_t cur_TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM;
390  int64_t cur_TRACE_FIRINGS_PREFERENCES_SYSPARAM;
391  int64_t cur_TRACE_WM_CHANGES_SYSPARAM;
392  int64_t cur_TRACE_GDS_SYSPARAM;
393  /* kjh (CUSP-B4) end */
394 
395  thisAgent->did_PE = FALSE; /* RCHONG: 10.11 */
396 
397  soar_invoke_callbacks(thisAgent,
399  0);
400 
401  /* kjh (CUSP-B4) begin */
402  /* Stash trace state: */
403  cur_TRACE_CONTEXT_DECISIONS_SYSPARAM = thisAgent->sysparams[TRACE_CONTEXT_DECISIONS_SYSPARAM];
404  cur_TRACE_PHASES_SYSPARAM = thisAgent->sysparams[TRACE_PHASES_SYSPARAM];
405  cur_TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM = thisAgent->sysparams[TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM];
406  cur_TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM = thisAgent->sysparams[TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM];
407  cur_TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM = thisAgent->sysparams[TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM];
408  cur_TRACE_FIRINGS_PREFERENCES_SYSPARAM = thisAgent->sysparams[TRACE_FIRINGS_PREFERENCES_SYSPARAM];
409  cur_TRACE_WM_CHANGES_SYSPARAM = thisAgent->sysparams[TRACE_WM_CHANGES_SYSPARAM];
410  cur_TRACE_GDS_SYSPARAM = thisAgent->sysparams[TRACE_GDS_SYSPARAM];
411 
412  /* Temporarily disable tracing: */
421  /* kjh (CUSP-B4) end */
422 
423  bool wma_was_enabled = wma_enabled( thisAgent );
425 
428 
429  clear_goal_stack (thisAgent);
430 
431  if ( wma_was_enabled )
432  {
434  }
435 
436  thisAgent->rl_params->apoptosis->set_value( rl_apoptosis );
437 
438  thisAgent->rl_stats->reset();
439  thisAgent->wma_stats->reset();
440  thisAgent->epmem_stats->reset();
441  thisAgent->smem_stats->reset();
442  thisAgent->dyn_counters->clear();
443 
444  thisAgent->active_level = 0; /* Signal that everything should be retracted */
445  thisAgent->FIRING_TYPE = IE_PRODS;
446  do_preference_phase (thisAgent); /* allow all i-instantiations to retract */
447 
448  reset_explain(thisAgent);
449  bool ok = reset_id_counters (thisAgent);
450  reset_wme_timetags (thisAgent);
451  reset_statistics (thisAgent);
452 
453  // JRV: For XML generation
454  xml_reset( thisAgent );
455 
456 
457  /* RDF 01282003: Reinitializing the various halt and stop flags */
458  thisAgent->system_halted = FALSE;
459  thisAgent->stop_soar = FALSE; // voigtjr: this line doesn't exist in other kernel
460  thisAgent->reason_for_stopping = 0;
461  thisAgent->substate_break_level = 0;
462 
463  thisAgent->go_number = 1;
464  thisAgent->go_type = GO_DECISION;
465 
466  /* kjh (CUSP-B4) begin */
467  /* Restore trace state: */
468  set_sysparam(thisAgent, TRACE_CONTEXT_DECISIONS_SYSPARAM, cur_TRACE_CONTEXT_DECISIONS_SYSPARAM);
469  set_sysparam(thisAgent, TRACE_PHASES_SYSPARAM, cur_TRACE_PHASES_SYSPARAM);
470  set_sysparam(thisAgent, TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, cur_TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM);
471  set_sysparam(thisAgent, TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, cur_TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM);
472  set_sysparam(thisAgent, TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM, cur_TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM);
473  set_sysparam(thisAgent, TRACE_FIRINGS_PREFERENCES_SYSPARAM, cur_TRACE_FIRINGS_PREFERENCES_SYSPARAM);
474  set_sysparam(thisAgent, TRACE_WM_CHANGES_SYSPARAM, cur_TRACE_WM_CHANGES_SYSPARAM);
475  set_sysparam(thisAgent, TRACE_GDS_SYSPARAM, cur_TRACE_GDS_SYSPARAM);
476  /* kjh (CUSP-B4) end */
477 
478  soar_invoke_callbacks(thisAgent,
480  0);
481 
482  thisAgent->input_cycle_flag = TRUE; /* reinitialize flag AGR REW1 */
483  thisAgent->current_phase = INPUT_PHASE; /* moved here June 05 from loop below. KJC */
484 
485  /* REW: begin 09.15.96 */
486  thisAgent->FIRING_TYPE = IE_PRODS; /* KJC 10.05.98 was PE */
487  thisAgent->did_PE = FALSE;
488  /* REW: end 09.15.96 */
489 
490  // reset old stats information
491  stats_close(thisAgent);
492  delete thisAgent->stats_db;
493  thisAgent->stats_db = new soar_module::sqlite_database();
494 
495  // voigtjr: WARN_IF_TIMERS_REPORT_ZERO block goes here in other kernel
496  return ok ;
497 }
498 
499 /* ===================================================================
500 
501  Running Soar
502 
503  Do_one_top_level_phase() runs Soar one top-level phase. Note that
504  this does not start/stop the total_cpu_time timer--the caller must
505  do this.
506 
507  Each of the following routines runs Soar for a certain duration,
508  or until stop_soar gets set to TRUE.
509  - Run_forever() runs Soar forever.
510  - Run_for_n_phases() runs Soar for a given number (n) of top-level
511  phases. (If n==-1, it runs forever.)
512  - Run_for_n_elaboration_cycles() runs Soar for a given number (n)
513  of elaboration cycles. (Here, decision phase is counted as
514  an elaboration cycle.) (If n==-1, it runs forever.)
515  - Run_for_n_decision_cycles() runs Soar for a given number (n) of
516  decision cycles. (If n==-1, it runs forever.)
517  - Run_for_n_selections_of_slot (int64_t n, Symbol *attr_of_slot): this
518  runs Soar until the nth time a selection is made for a given
519  type of slot. Attr_of_slot should be either state_symbol or
520  operator_symbol.
521  - Run_for_n_selections_of_slot_at_level (int64_t n, Symbol *attr_of_slot,
522  goal_stack_level level): this runs Soar for n selections of the
523  given slot at the given level, or until the goal stack is popped
524  so that level no longer exists.
525 =================================================================== */
526 
527 void do_one_top_level_phase (agent* thisAgent)
528 {
529  // Symbol *iterate_goal_sym; kjc commented /* RCHONG: end 10.11 */
530 
531  if (thisAgent->system_halted)
532  {
533  print (thisAgent,
534  "\nSystem halted. Use (init-soar) before running Soar again.");
535  xml_generate_error(thisAgent, "System halted. Use (init-soar) before running Soar again.");
536  thisAgent->stop_soar = TRUE;
537  thisAgent->reason_for_stopping = "System halted.";
538  return;
539  }
540 
541  smem_attach( thisAgent );
542 
543  /*
544  * This code was commented by SoarTech with the addition of gSKI
545  * because gSKI requires the existence of a ^state and ^io link
546  * before the first Run cmd is issued.
547  * But what if we uncommented this code anyway, then if ever
548  * gSKI isn't wrapped around the kernel, this code will
549  * execute and create the links. KJC 4/05
550  *
551  * if (! thisAgent->top_goal)
552  * {
553  * create_top_goal(thisAgent);
554  * if (thisAgent->sysparams[TRACE_CONTEXT_DECISIONS_SYSPARAM])
555  * {
556  * print_string (thisAgent, "\n");
557  * print_lowest_slot_in_context_stack (thisAgent);
558  * }
559  * thisAgent->current_phase = INPUT_PHASE;
560  * thisAgent->d_cycle_count++;
561  * }
562  */
563 
564  switch (thisAgent->current_phase) {
565 
566  case INPUT_PHASE:
567 
568  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
569  print_phase (thisAgent, "\n--- Input Phase --- \n",0);
570 
571  /* for Operand2 mode using the new decision cycle ordering,
572  * we need to do some initialization in the INPUT PHASE, which
573  * now comes first. e_cycles are also zeroed before the APPLY Phase.
574  */
575  thisAgent->chunks_this_d_cycle = 0;
576  thisAgent->e_cycles_this_d_cycle = 0;
577  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
578  thisAgent->timers_phase.start();
579  #endif
580 
581  /* we check e_cycle_count because Soar 7 runs multiple input cycles per decision */
582  /* always true for Soar 8 */
583  if (thisAgent->e_cycles_this_d_cycle==0) {
584  soar_invoke_callbacks(thisAgent,
586  reinterpret_cast<soar_call_data>(INPUT_PHASE) );
587  } /* end if e_cycles_this_d_cycle == 0 */
588 
589  #ifdef REAL_TIME_BEHAVIOR /* RM Jones */
590  test_for_input_delay(thisAgent);
591  #endif
592  #ifdef ATTENTION_LAPSE /* RM Jones */
593  determine_lapsing(thisAgent);
594  #endif
595 
596  if (thisAgent->input_cycle_flag == TRUE) { /* Soar 7 flag, but always true for Soar8 */
597  soar_invoke_callbacks(thisAgent,
599  reinterpret_cast<soar_call_data>(INPUT_PHASE));
600 
601  do_input_cycle(thisAgent);
602 
603  thisAgent->run_phase_count++ ;
604  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
605  soar_invoke_callbacks(thisAgent,
607  reinterpret_cast<soar_call_data>(INPUT_PHASE) );
608 
609  if (thisAgent->input_period)
610  thisAgent->input_cycle_flag = FALSE;
611  } /* END if (input_cycle_flag==TRUE) AGR REW1 this line and 1 previous line */
612 
613  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
614  print_phase (thisAgent, "\n--- END Input Phase --- \n",1);
615 
616  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
617  thisAgent->timers_phase.stop();
618  thisAgent->timers_decision_cycle_phase[INPUT_PHASE].update(thisAgent->timers_phase);
619  #endif
620 
621  thisAgent->current_phase = PROPOSE_PHASE;
622 
623  break; /* END of INPUT PHASE */
624 
626 
627  case PROPOSE_PHASE: /* added in 8.6 to clarify Soar8 decision cycle */
628 
629  #ifndef NO_TIMING_STUFF
630  thisAgent->timers_phase.start();
631  #endif
632 
633  /* e_cycles_this_d_cycle will always be zero UNLESS we are
634  * running by ELABORATIONS.
635  * We only want to do the following if we've just finished INPUT and are
636  * starting PROPOSE. If this is the second elaboration for PROPOSE, then
637  * just do the while loop below. KJC June 05
638  */
639  if (thisAgent->e_cycles_this_d_cycle < 1) {
640  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
641  print_phase(thisAgent, "\n--- Proposal Phase ---\n",0);
642 
643  soar_invoke_callbacks(thisAgent,
645  reinterpret_cast<soar_call_data>(PROPOSE_PHASE) );
646 
647  // We need to generate this event here in case no elaborations fire...
648  // FIXME return the correct enum top_level_phase constant in soar_call_data?
649  /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
651 
652  /* 'Prime the decision for a new round of production firings at the end of
653  * REW: 05.05.97 */ /* KJC 04.05 moved here from INPUT_PHASE for 8.6.0 */
655 
656  thisAgent->FIRING_TYPE = IE_PRODS;
657  thisAgent->applyPhase = FALSE; /* KJC 04/05: do we still need this line? gSKI does*/
659 
660  if (thisAgent->current_phase == DECISION_PHASE)
661  { // no elaborations will fire this phase
662  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
663  // FIXME return the correct enum top_level_phase constant in soar_call_data?
664  /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
666  }
667  }
668 
669  /* max-elaborations are checked in determine_highest_active... and if they
670  * are reached, the current phase is set to DECISION. phase is also set
671  * to DECISION when PROPOSE is done.
672  */
673 
674  while (thisAgent->current_phase != DECISION_PHASE) {
675  if (thisAgent->e_cycles_this_d_cycle)
676  { // only for 2nd cycle or higher. 1st cycle fired above
677  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
679  }
680 
681  do_preference_phase(thisAgent);
682  do_working_memory_phase(thisAgent);
683 
684  if ( smem_enabled( thisAgent ) )
685  {
686  smem_go( thisAgent, true );
687  }
688 
689  // allow epmem searches in proposal phase
690  // FIXME should turn this into a command line option
691  if ( epmem_enabled( thisAgent ) )
692  {
693  // epmem_go( thisAgent, false );
694  }
695 
696  /* Update accounting. Moved here by KJC 04/05/05 */
697  thisAgent->e_cycle_count++;
698  thisAgent->e_cycles_this_d_cycle++;
699  thisAgent->run_elaboration_count++ ;
701  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
703 
704  if (thisAgent->system_halted) break;
705  if (thisAgent->go_type == GO_ELABORATION) break;
706  }
707 
708  /* If we've finished PROPOSE, then current_phase will be equal to DECISION
709  * otherwise, we're only stopping because we're running by ELABORATIONS, so
710  * don't do the end-of-phase updating in that case.
711  */
712  if (thisAgent->current_phase == DECISION_PHASE) {
713  /* This is a HACK for Soar 8.6.0 beta release... KCoulter April 05
714  * We got here, because we should move to DECISION, so PROPOSE is done
715  * Set phase back to PROPOSE, do print_phase, callbacks, and then
716  * reset phase to DECISION
717  */
718  thisAgent->current_phase = PROPOSE_PHASE;
719  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM]) {
720  print_phase(thisAgent, "\n--- END Proposal Phase ---\n",1);
721  }
722 
723  thisAgent->run_phase_count++ ;
724  soar_invoke_callbacks(thisAgent,
726  reinterpret_cast<soar_call_data>(PROPOSE_PHASE) );
727  thisAgent->current_phase = DECISION_PHASE;
728  }
729 
730  #ifndef NO_TIMING_STUFF
731  thisAgent->timers_phase.stop();
732  thisAgent->timers_decision_cycle_phase[PROPOSE_PHASE].update(thisAgent->timers_phase);
733  #endif
734 
735  break; /* END of Soar8 PROPOSE PHASE */
736 
738  case PREFERENCE_PHASE:
739  /* starting with 8.6.0, PREFERENCE_PHASE is only Soar 7 mode -- applyPhase not valid here */
740  /* needs to be updated for gSKI interface, and gSKI needs to accommodate Soar 7 */
741 
742  /* JC ADDED: Tell gski about elaboration phase beginning */
743  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
745 
746  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
747  thisAgent->timers_phase.start();
748  #endif
749 
750  soar_invoke_callbacks(thisAgent,
752  reinterpret_cast<soar_call_data>(PREFERENCE_PHASE) );
753 
754  do_preference_phase(thisAgent);
755 
756  thisAgent->run_phase_count++ ;
757  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
758  soar_invoke_callbacks(thisAgent,
760  reinterpret_cast<soar_call_data>(PREFERENCE_PHASE) );
761  thisAgent->current_phase = WM_PHASE;
762 
763  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
764  thisAgent->timers_phase.stop();
765  thisAgent->timers_decision_cycle_phase[PREFERENCE_PHASE].update(thisAgent->timers_phase);
766  #endif
767 
768  /* tell gSKI PREF_PHASE ending...
769  */
770  break; /* END of Soar7 PREFERENCE PHASE */
771 
773  case WM_PHASE:
774  /* starting with 8.6.0, WM_PHASE is only Soar 7 mode; see PROPOSE and APPLY */
775  /* needs to be updated for gSKI interface, and gSKI needs to accommodate Soar 7 */
776 
777  /* we need to tell gSKI WM Phase beginning... */
778 
779  #ifndef NO_TIMING_STUFF /* REW: begin 28.07.96 */
780  thisAgent->timers_phase.start();
781  #endif
782 
783  soar_invoke_callbacks(thisAgent,
785  reinterpret_cast<soar_call_data>(WM_PHASE) );
786 
787  do_working_memory_phase(thisAgent);
788 
789  thisAgent->run_phase_count++ ;
790  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
791  soar_invoke_callbacks(thisAgent,
793  reinterpret_cast<soar_call_data>(WM_PHASE) );
794 
795  thisAgent->current_phase = OUTPUT_PHASE;
796 
797  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
798  thisAgent->timers_phase.stop();
799  thisAgent->timers_decision_cycle_phase[WM_PHASE].update(thisAgent->timers_phase);
800  #endif
801 
802  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
804 
805  break; /* END of Soar7 WM PHASE */
806 
808  case APPLY_PHASE: /* added in 8.6 to clarify Soar8 decision cycle */
809 
810  #ifndef NO_TIMING_STUFF
811  thisAgent->timers_phase.start();
812  #endif
813 
814  /* e_cycle_count will always be zero UNLESS we are running by ELABORATIONS.
815  * We only want to do the following if we've just finished DECISION and are
816  * starting APPLY. If this is the second elaboration for APPLY, then
817  * just do the while loop below. KJC June 05
818  */
819  if (thisAgent->e_cycles_this_d_cycle < 1) {
820 
821  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
822  print_phase (thisAgent, "\n--- Application Phase ---\n",0);
823 
824  soar_invoke_callbacks(thisAgent,
826  reinterpret_cast<soar_call_data>(APPLY_PHASE) );
827 
828  // We need to generate this event here in case no elaborations fire...
829  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
831 
832  /* 'prime' the cycle for a new round of production firings
833  * in the APPLY (pref/wm) phase *//* KJC 04.05 moved here from end of DECISION */
835 
836  thisAgent->FIRING_TYPE = PE_PRODS; /* might get reset in det_high_active_prod_level... */
837  thisAgent->applyPhase = TRUE; /* KJC 04/05: do we still need this line? gSKI does*/
839  if (thisAgent->current_phase == OUTPUT_PHASE)
840  { // no elaborations will fire this phase
841  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
842  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
844  }
845  }
846  /* max-elaborations are checked in determine_highest_active... and if they
847  * are reached, the current phase is set to OUTPUT. phase is also set
848  * to OUTPUT when APPLY is done.
849  */
850 
851  while (thisAgent->current_phase != OUTPUT_PHASE) {
852  /* JC ADDED: Tell gski about elaboration phase beginning */
853  if (thisAgent->e_cycles_this_d_cycle)
854  { // only for 2nd cycle or higher. 1st cycle fired above
855  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
857  }
858 
859  do_preference_phase(thisAgent);
860  do_working_memory_phase(thisAgent);
861 
862  if ( smem_enabled( thisAgent ) )
863  {
864  smem_go( thisAgent, true );
865  }
866 
867  /* Update accounting. Moved here by KJC 04/05/05 */
868  thisAgent->e_cycle_count++;
869  thisAgent->e_cycles_this_d_cycle++;
870  thisAgent->run_elaboration_count++ ;
871 
872  if (thisAgent->FIRING_TYPE == PE_PRODS) {
873  thisAgent->pe_cycle_count++;
874  thisAgent->pe_cycles_this_d_cycle++;
875  }
877  // FIXME return the correct enum top_level_phase constant in soar_call_data? /*(soar_call_data)((thisAgent->applyPhase == TRUE)? gSKI_K_APPLY_PHASE: gSKI_K_PROPOSAL_PHASE)*/
879 
880  if (thisAgent->system_halted) break;
881  if (thisAgent->go_type == GO_ELABORATION) break;
882  }
883 
884  /* If we've finished APPLY, then current_phase will be equal to OUTPUT
885  * otherwise, we're only stopping because we're running by ELABORATIONS, so
886  * don't do the end-of-phase updating in that case.
887  */
888  if (thisAgent->current_phase == OUTPUT_PHASE) {
889  /* This is a HACK for Soar 8.6.0 beta release... KCoulter April 05
890  * We got here, because we should move to OUTPUT, so APPLY is done
891  * Set phase back to APPLY, do print_phase, callbacks and reset phase to OUTPUT
892  */
893  thisAgent->current_phase = APPLY_PHASE;
894  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM]) {
895  print_phase(thisAgent, "\n--- END Application Phase ---\n",1);
896  }
897  thisAgent->run_phase_count++ ;
898  soar_invoke_callbacks(thisAgent,
900  reinterpret_cast<soar_call_data>(APPLY_PHASE) );
901 
902  thisAgent->current_phase = OUTPUT_PHASE;
903  }
904 
905  #ifndef NO_TIMING_STUFF
906  thisAgent->timers_phase.stop();
907  thisAgent->timers_decision_cycle_phase[APPLY_PHASE].update(thisAgent->timers_phase);
908  #endif
909 
910  break; /* END of Soar8 APPLY PHASE */
911 
913  case OUTPUT_PHASE:
914 
915  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
916  print_phase (thisAgent, "\n--- Output Phase ---\n",0);
917 
918  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
919  thisAgent->timers_phase.start();
920  #endif
921 
922  soar_invoke_callbacks(thisAgent,
924  reinterpret_cast<soar_call_data>(OUTPUT_PHASE) );
925 
928  do_output_cycle(thisAgent);
929 
930  if ( smem_enabled( thisAgent ) )
931  {
932  smem_go( thisAgent, false );
933  }
934 
936  assert( thisAgent->wma_d_cycle_count == thisAgent->d_cycle_count );
938 
939  // update histories only first, allows:
940  // - epmem retrieval cues to be biased by activation
941  // - epmem encoding to capture wmes that may be forgotten shortly
942  if ( wma_enabled( thisAgent ) )
943  {
944  wma_go( thisAgent, wma_histories );
945  }
946 
947  if ( epmem_enabled( thisAgent ) && ( thisAgent->epmem_params->phase->get_value() == epmem_param_container::phase_output ) )
948  {
949  // since we consolidated wma histories from this decision,
950  // we need to pretend it's the next time step in case
951  // an epmem retrieval wants to know current activation value
952  thisAgent->wma_d_cycle_count++;
953  {
954  epmem_go( thisAgent );
955  }
956  thisAgent->wma_d_cycle_count--;
957  }
958 
959  // now both update histories and forget, allows
960  // - epmem retrieval to affect history
961  // - epmem encoding to capture wmes that may be forgotten shortly
962  if ( wma_enabled( thisAgent ) )
963  {
964  wma_go( thisAgent, wma_histories );
965  wma_go( thisAgent, wma_forgetting );
966  }
967 
969  assert( thisAgent->wma_d_cycle_count == thisAgent->d_cycle_count );
971 
972  // RL apoptosis
973  {
975  if ( rl_apoptosis != rl_param_container::apoptosis_none )
976  {
978  thisAgent->rl_prods->forget();
979  thisAgent->rl_prods->time_forward();
980 
981  for ( rl_production_memory::object_set::iterator p=thisAgent->rl_prods->forgotten_begin(); p!=thisAgent->rl_prods->forgotten_end(); p++ )
982  {
983  // conditions:
984  // - no matched instantiations AND
985  // - if RL...
986  // - no update count
987  // - not in some state's prev_op_rl_rules list
988  if ( ( (*p)->instantiations == NIL ) && ( !(*p)->rl_rule || ( ( static_cast<int64_t>( (*p)->rl_update_count ) == 0 ) && ( (*p)->rl_ref_count == 0 ) ) ) )
989  {
990  excise_production( thisAgent, const_cast< production* >( *p ), FALSE );
991  }
992  }
993  }
994  }
995 
996  // Count the outputs the agent generates (or times reaching max-nil-outputs without sending output)
997  if (thisAgent->output_link_changed || ((++(thisAgent->run_last_output_count)) >= static_cast<uint64_t>(thisAgent->sysparams[MAX_NIL_OUTPUT_CYCLES_SYSPARAM])))
998  {
999  thisAgent->run_last_output_count = 0 ;
1000  thisAgent->run_generated_output_count++ ;
1001  }
1002 
1003  thisAgent->run_phase_count++ ;
1004  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
1005  soar_invoke_callbacks(thisAgent,
1007  reinterpret_cast<soar_call_data>(OUTPUT_PHASE) );
1008 
1009  /* REW: begin 09.15.96 */
1010  // JRV: Get rid of the cached XML after every decision but before the after-decision-phase callback
1011  xml_invoke_callback( thisAgent ); // invokes XML_GENERATION_CALLBACK, clears XML state
1012 
1013  /* KJC June 05: moved here from DECISION Phase */
1014  soar_invoke_callbacks(thisAgent,
1016  reinterpret_cast<soar_call_data>(OUTPUT_PHASE) );
1017  #ifndef NO_TIMING_STUFF /* timers stopped KJC 10-04-98 */
1018  thisAgent->timers_phase.stop();
1019  thisAgent->timers_decision_cycle_phase[OUTPUT_PHASE].update(thisAgent->timers_phase);
1020  #endif
1021 
1022  // Update per-cycle statistics
1023  {
1024  uint64_t dc_time_usec = 0;
1025 #ifndef NO_TIMING_STUFF
1026  uint64_t derived_kernel_time_usec = get_derived_kernel_time_usec(thisAgent);
1027  dc_time_usec = derived_kernel_time_usec - thisAgent->last_derived_kernel_time_usec;
1028  if (thisAgent->max_dc_time_usec < dc_time_usec) {
1029  thisAgent->max_dc_time_usec = dc_time_usec;
1030  thisAgent->max_dc_time_cycle = thisAgent->d_cycle_count;
1031  }
1032  if (thisAgent->sysparams[DECISION_CYCLE_MAX_USEC_INTERRUPT] > 0) {
1033  if (dc_time_usec >= static_cast<uint64_t>(thisAgent->sysparams[DECISION_CYCLE_MAX_USEC_INTERRUPT])) {
1034  thisAgent->stop_soar++;
1035  thisAgent->reason_for_stopping = "decision cycle time greater than interrupt threshold";
1036  }
1037  }
1038  thisAgent->last_derived_kernel_time_usec = derived_kernel_time_usec;
1039 
1040  double total_epmem_time = thisAgent->epmem_timers->total->value();
1041  if (thisAgent->total_dc_epmem_time_sec >= 0)
1042  {
1043  double delta_epmem_time = total_epmem_time - thisAgent->total_dc_epmem_time_sec;
1044  if (thisAgent->max_dc_epmem_time_sec < delta_epmem_time) {
1045  thisAgent->max_dc_epmem_time_sec = delta_epmem_time;
1046  thisAgent->max_dc_epmem_time_cycle = thisAgent->d_cycle_count;
1047  }
1048  }
1049  thisAgent->total_dc_epmem_time_sec = total_epmem_time;
1050 
1051  double total_smem_time = thisAgent->smem_timers->total->value();
1052  if (thisAgent->total_dc_smem_time_sec >= 0)
1053  {
1054  double delta_smem_time = total_smem_time - thisAgent->total_dc_smem_time_sec;
1055  if (thisAgent->max_dc_smem_time_sec < delta_smem_time) {
1056  thisAgent->max_dc_smem_time_sec = delta_smem_time;
1057  thisAgent->max_dc_smem_time_cycle = thisAgent->d_cycle_count;
1058  }
1059  }
1060  thisAgent->total_dc_smem_time_sec = total_smem_time;
1061 
1062 #endif // NO_TIMING_STUFF
1063 
1064  uint64_t dc_wm_changes = thisAgent->wme_addition_count - thisAgent->start_dc_wme_addition_count;
1065  dc_wm_changes += thisAgent->wme_removal_count - thisAgent->start_dc_wme_removal_count;
1066  if (thisAgent->max_dc_wm_changes_value < dc_wm_changes) {
1067  thisAgent->max_dc_wm_changes_value = dc_wm_changes;
1068  thisAgent->max_dc_wm_changes_cycle = thisAgent->d_cycle_count;
1069  }
1070  thisAgent->start_dc_wme_addition_count = thisAgent->wme_addition_count;
1071  thisAgent->start_dc_wme_removal_count = thisAgent->wme_removal_count;
1072 
1073  uint64_t dc_firing_counts = thisAgent->production_firing_count - thisAgent->start_dc_production_firing_count;
1074  if (thisAgent->max_dc_production_firing_count_value < dc_firing_counts) {
1075  thisAgent->max_dc_production_firing_count_value = dc_firing_counts;
1076  thisAgent->max_dc_production_firing_count_cycle = thisAgent->d_cycle_count;
1077  }
1079 
1080  // Commit per-cycle stats to db
1081  if (thisAgent->dc_stat_tracking) {
1082  stats_db_store(thisAgent, dc_time_usec, dc_wm_changes, dc_firing_counts);
1083  }
1084  }
1085 
1086  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
1087  print_phase (thisAgent, "\n--- END Output Phase ---\n",1);
1088  thisAgent->current_phase = INPUT_PHASE;
1089  thisAgent->d_cycle_count++;
1090  thisAgent->wma_d_cycle_count++;
1091  /* REW: end 09.15.96 */
1092  break;
1093 
1095  case DECISION_PHASE:
1096  /* not yet cleaned up for 8.6.0 release */
1097 
1098  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
1099  print_phase (thisAgent, "\n--- Decision Phase ---\n",0);
1100 
1101  #ifndef NO_TIMING_STUFF /* REW: 28.07.96 */
1102  thisAgent->timers_phase.start();
1103  #endif
1104 
1105  thisAgent->decision_phases_count++; /* counts decisions, not cycles, for more accurate stats */
1106 
1107  /* AGR REW1 begin */
1108  if (!thisAgent->input_period)
1109  thisAgent->input_cycle_flag = TRUE;
1110  else if ((thisAgent->d_cycle_count % thisAgent->input_period) == 0)
1111  thisAgent->input_cycle_flag = TRUE;
1112  /* AGR REW1 end */
1113 
1114  soar_invoke_callbacks(thisAgent,
1116  reinterpret_cast<soar_call_data>(DECISION_PHASE) );
1117 
1118  do_decision_phase(thisAgent);
1119 
1120  thisAgent->run_phase_count++ ;
1121  thisAgent->run_elaboration_count++ ; // All phases count as a run elaboration
1122 
1123  soar_invoke_callbacks(thisAgent,
1125  reinterpret_cast<soar_call_data>(DECISION_PHASE) );
1126 
1127  if (thisAgent->sysparams[TRACE_CONTEXT_DECISIONS_SYSPARAM]) {
1128  // #ifdef USE_TCL
1129  print_string (thisAgent, "\n");
1130  // #else
1131  //if(thisAgent->printer_output_column != 1)
1132  // print_string ("\n");
1133  // #endif /* USE_TCL */
1135  }
1136 
1137  /* reset elaboration counter */
1138  thisAgent->e_cycles_this_d_cycle = 0;
1139  thisAgent->pe_cycles_this_d_cycle = 0;
1140 
1141  /* REW: begin 09.15.96 */
1142 #ifdef AGRESSIVE_ONC
1143  /* test for Operator NC, if TRUE, generate substate and go to OUTPUT */
1144  if ((thisAgent->ms_o_assertions == NIL) &&
1145  (thisAgent->bottom_goal->id.operator_slot->wmes != NIL))
1146  {
1147 
1148  soar_invoke_callbacks(thisAgent, thisAgent,
1150  static_cast<soar_call_data>(thisAgent->current_phase) );
1151 
1152  do_decision_phase(thisAgent);
1153 
1155  static_cast<soar_call_data>(thisAgent->current_phase) );
1156 
1157  if (thisAgent->sysparams[TRACE_CONTEXT_DECISIONS_SYSPARAM]) {
1158  // #ifdef USE_TCL
1159  print_string (thisAgent, "\n");
1160  // #else
1161  // if(thisAgent->printer_output_column != 1) print_string ("\n");
1162  // #endif /* USE_TCL */
1164  }
1165  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
1166  print_phase (thisAgent, "\n--- END Decision Phase ---\n",1);
1167 
1168  /* set phase to OUTPUT */
1169  thisAgent->current_phase = OUTPUT_PHASE;
1170 
1171  /* REW: begin 28.07.96 */
1172 #ifndef NO_TIMING_STUFF
1173  thisAgent->timers_phase.stop();
1174  thisAgent->timers_decision_cycle_phase[DECISION_PHASE].update(thisAgent->timers_phase);
1175 #endif
1176  /* REW: end 28.07.96 */
1177 
1178  break;
1179 
1180  } else
1181 #endif //AGRESSIVE_ONC
1182 
1183  if ( epmem_enabled( thisAgent ) && ( thisAgent->epmem_params->phase->get_value() == epmem_param_container::phase_selection ) )
1184  epmem_go( thisAgent );
1185 
1186  {
1187  if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM])
1188  print_phase (thisAgent, "\n--- END Decision Phase ---\n",1);
1189 
1190  /* printf("\nSetting next phase to APPLY following a decision...."); */
1191  thisAgent->applyPhase = TRUE;
1192  thisAgent->FIRING_TYPE = PE_PRODS;
1193  thisAgent->current_phase = APPLY_PHASE;
1194  }
1195 
1196  /* REW: begin 28.07.96 */
1197  #ifndef NO_TIMING_STUFF
1198  thisAgent->timers_phase.stop();
1199  thisAgent->timers_decision_cycle_phase[DECISION_PHASE].update(thisAgent->timers_phase);
1200  #endif
1201  /* REW: end 28.07.96 */
1202 
1203  break; /* end DECISION phase */
1204 
1206 
1207  default: // 2/24/05: added default case to quell gcc compile warning
1208  assert(false && "Invalid phase enumeration value!");
1209  break;
1210 
1211  } /* end switch stmt for current_phase */
1212 
1213  /* --- update WM size statistics --- */
1214  if (thisAgent->num_wmes_in_rete > thisAgent->max_wm_size)
1215  thisAgent->max_wm_size = thisAgent->num_wmes_in_rete;
1216  thisAgent->cumulative_wm_size += thisAgent->num_wmes_in_rete;
1217  thisAgent->num_wm_sizes_accumulated++;
1218 
1219  if (thisAgent->system_halted) {
1220  thisAgent->stop_soar = TRUE;
1221  thisAgent->reason_for_stopping = "System halted.";
1222  soar_invoke_callbacks(thisAgent,
1224  reinterpret_cast<soar_call_data>(thisAgent->current_phase) );
1225 
1226  // To model episodic task, after halt, perform RL update with next-state value 0
1227  if ( rl_enabled( thisAgent ) )
1228  {
1229  for ( Symbol *g = thisAgent->bottom_goal; g; g = g->id.higher_goal)
1230  {
1231  rl_tabulate_reward_value_for_goal( thisAgent, g );
1232  rl_perform_update( thisAgent, 0, true, g );
1233  }
1234  }
1235  }
1236 
1237  if (thisAgent->stop_soar) {
1238  if (thisAgent->reason_for_stopping) {
1239  print(thisAgent, "\n%s\n", thisAgent->reason_for_stopping);
1240  }
1241  }
1242 }
1243 
1244 void run_forever (agent* thisAgent) {
1245  #ifndef NO_TIMING_STUFF
1246  thisAgent->timers_cpu.start();
1247  thisAgent->timers_kernel.start();
1248  #endif
1249 
1250  thisAgent->stop_soar = FALSE;
1251  thisAgent->reason_for_stopping = 0;
1252  while (! thisAgent->stop_soar) {
1253  do_one_top_level_phase(thisAgent);
1254  }
1255 
1256  #ifndef NO_TIMING_STUFF
1257  thisAgent->timers_kernel.stop();
1258  thisAgent->timers_cpu.stop();
1259  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1260  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1261  #endif
1262 }
1263 
1264 void run_for_n_phases (agent* thisAgent, int64_t n) {
1265  if (n == -1) { run_forever(thisAgent); return; }
1266  if (n < -1) return;
1267 #ifndef NO_TIMING_STUFF
1268  thisAgent->timers_cpu.start();
1269  thisAgent->timers_kernel.start();
1270 #endif
1271  thisAgent->stop_soar = FALSE;
1272  thisAgent->reason_for_stopping = "";
1273  while (!thisAgent->stop_soar && n) {
1274  do_one_top_level_phase(thisAgent);
1275  n--;
1276  }
1277 #ifndef NO_TIMING_STUFF
1278  thisAgent->timers_kernel.stop();
1279  thisAgent->timers_cpu.stop();
1280  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1281  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1282 #endif
1283 }
1284 
1285 void run_for_n_elaboration_cycles (agent* thisAgent, int64_t n) {
1286  int64_t e_cycles_at_start, d_cycles_at_start, elapsed_cycles = 0;
1287  go_type_enum save_go_type = GO_PHASE;
1288 
1289  if (n == -1) { run_forever(thisAgent); return; }
1290  if (n < -1) return;
1291 #ifndef NO_TIMING_STUFF
1292  thisAgent->timers_cpu.start();
1293  thisAgent->timers_kernel.start();
1294 #endif
1295  thisAgent->stop_soar = FALSE;
1296  thisAgent->reason_for_stopping = 0;
1297  e_cycles_at_start = thisAgent->e_cycle_count;
1298  d_cycles_at_start = thisAgent->d_cycle_count;
1299  elapsed_cycles = -1;
1300  save_go_type = thisAgent->go_type;
1301  thisAgent->go_type = GO_ELABORATION;
1302  /* need next line or runs only the input phase for "d 1" after init-soar */
1303  if (d_cycles_at_start == 0) d_cycles_at_start++;
1304  while (!thisAgent->stop_soar) {
1305  elapsed_cycles++;
1306  if (n==elapsed_cycles) break;
1307  do_one_top_level_phase(thisAgent);
1308  }
1309  thisAgent->go_type = save_go_type;
1310 
1311 #ifndef NO_TIMING_STUFF
1312  thisAgent->timers_kernel.stop();
1313  thisAgent->timers_cpu.stop();
1314  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1315  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1316 #endif
1317 }
1318 
1319 void run_for_n_modifications_of_output (agent* thisAgent, int64_t n) {
1320  Bool was_output_phase;
1321  int64_t count = 0;
1322 
1323  if (n == -1) { run_forever(thisAgent); return; }
1324  if (n < -1) return;
1325 #ifndef NO_TIMING_STUFF
1326  thisAgent->timers_cpu.start();
1327  thisAgent->timers_kernel.start();
1328 #endif
1329  thisAgent->stop_soar = FALSE;
1330  thisAgent->reason_for_stopping = 0;
1331  while (!thisAgent->stop_soar && n) {
1332  was_output_phase = (thisAgent->current_phase==OUTPUT_PHASE);
1333  do_one_top_level_phase(thisAgent);
1334  if (was_output_phase) {
1335  if (thisAgent->output_link_changed) {
1336  n--;
1337  } else {
1338  count++;
1339  } }
1340  if (count >= thisAgent->sysparams[MAX_NIL_OUTPUT_CYCLES_SYSPARAM]) {
1341  break;
1342  //thisAgent->stop_soar = TRUE;
1343  //thisAgent->reason_for_stopping = "exceeded max_nil_output_cycles with no output";
1344  }
1345  }
1346 #ifndef NO_TIMING_STUFF
1347  thisAgent->timers_kernel.stop();
1348  thisAgent->timers_cpu.stop();
1349  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1350  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1351 #endif
1352 }
1353 
1354 void run_for_n_decision_cycles (agent* thisAgent, int64_t n) {
1355  int64_t d_cycles_at_start;
1356 
1357  if (n == -1) { run_forever(thisAgent); return; }
1358  if (n < -1) return;
1359 #ifndef NO_TIMING_STUFF
1360  thisAgent->timers_cpu.start();
1361  thisAgent->timers_kernel.start();
1362 #endif
1363  thisAgent->stop_soar = FALSE;
1364  thisAgent->reason_for_stopping = 0;
1365  d_cycles_at_start = thisAgent->d_cycle_count;
1366  /* need next line or runs only the input phase for "d 1" after init-soar */
1367  if (d_cycles_at_start == 0)
1368  d_cycles_at_start++;
1369  while (!thisAgent->stop_soar) {
1370  if (n == static_cast<int64_t>(thisAgent->d_cycle_count-d_cycles_at_start)) break;
1371  do_one_top_level_phase(thisAgent);
1372  }
1373 #ifndef NO_TIMING_STUFF
1374  thisAgent->timers_kernel.stop();
1375  thisAgent->timers_cpu.stop();
1376  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1377  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1378 #endif
1379 }
1380 
1382  if (thisAgent->bottom_goal->id.operator_slot->wmes)
1383  return thisAgent->operator_symbol;
1384  return thisAgent->state_symbol;
1385 }
1386 
1387 void run_for_n_selections_of_slot (agent* thisAgent, int64_t n, Symbol *attr_of_slot) {
1388  int64_t count;
1389  Bool was_decision_phase;
1390 
1391  if (n == -1) { run_forever(thisAgent); return; }
1392  if (n < -1) return;
1393 #ifndef NO_TIMING_STUFF
1394  thisAgent->timers_cpu.start();
1395  thisAgent->timers_kernel.start();
1396 #endif
1397  thisAgent->stop_soar = FALSE;
1398  thisAgent->reason_for_stopping = 0;
1399  count = 0;
1400  while (!thisAgent->stop_soar && (count < n)) {
1401  was_decision_phase = (thisAgent->current_phase==DECISION_PHASE);
1402  do_one_top_level_phase(thisAgent);
1403  if (was_decision_phase)
1404  if (attr_of_slot_just_decided(thisAgent)==attr_of_slot) count++;
1405  }
1406 #ifndef NO_TIMING_STUFF
1407  thisAgent->timers_kernel.stop();
1408  thisAgent->timers_cpu.stop();
1409  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1410  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1411 #endif
1412 }
1413 
1414 void run_for_n_selections_of_slot_at_level (agent* thisAgent, int64_t n,
1415  Symbol *attr_of_slot,
1416  goal_stack_level level) {
1417  int64_t count;
1418  Bool was_decision_phase;
1419 
1420  if (n == -1) { run_forever(thisAgent); return; }
1421  if (n < -1) return;
1422 #ifndef NO_TIMING_STUFF
1423  thisAgent->timers_cpu.start();
1424  thisAgent->timers_kernel.start();
1425 #endif
1426  thisAgent->stop_soar = FALSE;
1427  thisAgent->reason_for_stopping = 0;
1428  count = 0;
1429  while (!thisAgent->stop_soar && (count < n)) {
1430  was_decision_phase = (thisAgent->current_phase==DECISION_PHASE);
1431  do_one_top_level_phase(thisAgent);
1432  if (was_decision_phase) {
1433  if (thisAgent->bottom_goal->id.level < level) break;
1434  if (thisAgent->bottom_goal->id.level==level) {
1435  if (attr_of_slot_just_decided(thisAgent)==attr_of_slot) count++;
1436  }
1437  }
1438  }
1439 #ifndef NO_TIMING_STUFF
1440  thisAgent->timers_kernel.stop();
1441  thisAgent->timers_cpu.stop();
1442  thisAgent->timers_total_kernel_time.update(thisAgent->timers_kernel);
1443  thisAgent->timers_total_cpu_time.update(thisAgent->timers_cpu);
1444 #endif
1445 }
1446 
1447 /* ===================================================================
1448 
1449  Loading the Initialization File ".init.soar"
1450 
1451  This routine looks for a file ".init.soar" in either the current
1452  directory or $HOME, and if found, loads it.
1453 =================================================================== */
1454 
1455 extern char *getenv();
1456 
1457 /* AGR 536 Soar core dumped when it used filenames longer than 1000 chars
1458  but shorter than MAXPATHLEN (from sys/param.h). 4-May-94 */
1459 
1460 // KJC Nov 05: moved here from old interface.cpp, so could remove interface.* files
1461 void load_file (agent* thisAgent, char *file_name, FILE *already_open_file) {
1462 Bool old_print_prompt_flag;
1463 
1464  old_print_prompt_flag = thisAgent->print_prompt_flag;
1465  thisAgent->print_prompt_flag = FALSE;
1466 
1467  start_lex_from_file (thisAgent, file_name, already_open_file);
1468  //repeatedly_read_and_dispatch_commands (thisKernel, thisAgent);
1469  stop_lex_from_file (thisAgent);
1470 
1471  thisAgent->print_prompt_flag = old_print_prompt_flag;
1472 }
1473 
1474 /*
1475  RDF: 20020706 Added this for the gSKI project. This makes it so that
1476  created agents have a top state and the appropriate io
1477  header symbols and wme's even before the first decision
1478  cycle. This helps keep the gSKI interface a little saner.
1479 */
1480 
1481 void init_agent_memory(agent* thisAgent)
1482 {
1483 
1484  /* The following code was taken from the do_one_top_level_phase function
1485  near the top of this file */
1486  // If there is already a top goal this function should probably not be called
1487  assert( thisAgent->top_goal == 0 &&
1488  "There should be no top goal when init_agent_memory is called!");
1489  if ( thisAgent->top_goal) return;
1490 
1491  thisAgent->io_header = get_new_io_identifier (thisAgent, 'I');
1492  thisAgent->io_header_input = get_new_io_identifier (thisAgent, 'I');
1493  thisAgent->io_header_output = get_new_io_identifier (thisAgent, 'I');
1494 
1495  create_top_goal(thisAgent);
1497  {
1498  print_string (thisAgent, "\n");
1500  }
1501  thisAgent->current_phase = INPUT_PHASE;
1502  thisAgent->d_cycle_count++;
1503  thisAgent->wma_d_cycle_count++;
1504 
1505  /* The following code was taken from the do_input_cycle function of io.cpp */
1506  // Creating the io_header and adding the top state io header wme
1507  thisAgent->io_header_link = add_input_wme (thisAgent,
1508  thisAgent->top_state,
1509  thisAgent->io_symbol,
1510  thisAgent->io_header);
1511  // Creating the input and output header symbols and wmes
1512  // RPM 9/06 changed to use thisAgent->input/output_link_symbol
1513  // Note we don't have to save these wmes for later release since their parent
1514  // is already being saved (above), and when we release it they will automatically be released
1515  add_input_wme (thisAgent, thisAgent->io_header,
1516  thisAgent->input_link_symbol,
1517  thisAgent->io_header_input);
1518  add_input_wme (thisAgent, thisAgent->io_header,
1519  thisAgent->output_link_symbol,
1520  thisAgent->io_header_output);
1521 
1522  // KJC & RPM 10/06
1523  // A lot of stuff isn't initialized properly until the input and output cycles are run the first time.
1524  // Because of this, SW had to put in a hack to work around changes made to the output-link in the first
1525  // dc not being visible. (see comment near end of update_for_top_state_wme_addition). This change added
1526  // an item to the associated_output_links list.
1527  // But the ol->ids_in_tc is still not initialized until the first output phase, so if we exit before that,
1528  // remove_output_link_tc_info doesn't see it and doesn't clean up the associated_output_links list.
1529  // If we do run an output phase, though, the same item is added to the associated_output_links list twice.
1530  // ol->ids_in_tc gets initialized, so remove_output_link_tc_info -- but it only cleans up the first copy
1531  // of the item.
1532  // All of these problems come back to things not being initialized properly, so we run the input and output
1533  // phases here to force proper initialization (and have commented out SW's changes to
1534  // update_for_top_state_wme_addition). This will cause somecallbacks to be triggered, but we don't think
1535  // this is a problem for two reasons:
1536  // 1) these events are currently not exposed through SML, so no clients will see them
1537  // 2) even if these events were exposed, they are being fired during agent creation. Since the agent
1538  // hasn't been created yet, no client could have registered for the events anyway.
1539  // Note that this change replaces the do_buffered_wm_and_ownership_changes call which attempted to do some
1540  // initialization (including triggering SW's changes).
1541  do_input_cycle(thisAgent);
1542  do_output_cycle(thisAgent);
1543  //do_buffered_wm_and_ownership_changes(thisAgent);
1544 
1545  /* executing the IO cycles above, increments the timers, so reset */
1546  reset_timers(thisAgent);
1547  reset_max_stats(thisAgent);
1548 
1549  thisAgent->wma_timers->reset();
1550  thisAgent->epmem_timers->reset();
1551  thisAgent->smem_timers->reset();
1552 
1553  // This is an important part of the state of the agent for io purposes
1554  // (see io.cpp for details)
1555  thisAgent->prev_top_state = thisAgent->top_state;
1556 
1557 }