Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
gdatastructs.h
Go to the documentation of this file.
1 /*************************************************************************
2  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
3  * FOR LICENSE AND COPYRIGHT INFORMATION.
4  *************************************************************************/
5 
6 /* gdatastructs.h */
7 
8 /* ========================================================================= */
9 /* */
10 /* Global Data Structures */
11 /* */
12 /* ========================================================================= */
13 
14 #ifndef GDATASTRUCTS_H
15 #define GDATASTRUCTS_H
16 
17 #include "symtab.h" /* needed for definition of symbol_union */
18 #include "kernel.h" /* needed for definition of NIL */
19 #include "soar_module.h" /* needed for definition of memory pool allocator */
20 
21 #include <set>
22 
23 #ifdef __cplusplus
24 //extern "C"
25 //{
26 #endif
27 
28 typedef char Bool;
29 typedef unsigned char byte;
30 typedef uint64_t tc_number;
31 typedef signed short goal_stack_level;
33 typedef struct cons_struct cons;
34 typedef struct dl_cons_struct dl_cons;
35 typedef struct wme_struct wme;
36 typedef union symbol_union Symbol;
37 typedef cons list;
38 
39 #ifdef USE_MEM_POOL_ALLOCATORS
40 template <class T>
41 class SoarMemoryPoolAllocator;
42 
43 typedef std::set< wme*, std::less< wme* >, soar_module::soar_memory_pool_allocator< wme* > > wma_pooled_wme_set;
44 typedef std::map< Symbol*, uint64_t, std::less< Symbol* >, soar_module::soar_memory_pool_allocator< std::pair< Symbol*, uint64_t > > > wma_sym_reference_map;
45 #else
46 typedef std::set< wme* > wma_pooled_wme_set;
47 typedef std::map< Symbol*, uint64_t > wma_sym_reference_map;
48 #endif
49 
50 /* REW: begin 09.15.96 */
51 
52 /* ------------------------------------------------------------------------
53  Goal Dependency Set
54 
55  The Goal Dependency Set is a data strcuture used in Operand2 to maintain
56  the integrity of a subgoal with respect to changes in supergoal WMEs.
57  Whenever a WME in the goal's dependency set changes, the goal is immediately
58  removed. The routines for maintaining the GDS and determining if a goal
59  should be retracted are in decide.c
60 
61  Fields in a goal dependency set:
62 
63  goal: points to the goal for which this dependency set was created.
64  The goal also has a pointer back to the GDS.
65 
66  wmes_in_gds: A DLL of WMEs in the goal dependency set
67 
68  The GDS is created only when necessary; that is, when an o-suppported WME
69  is created in some subgoal and that subgoal has no GDS already. The
70  instantiations that led to the creation of the o-supported WME are
71  examined; any supergoal WMEs in these instantiations are added to the
72  wmes_in_gds DLL. The GDS for each goal is examined for every WM change;
73  if a WME changes that is on a GDS, the goal that the GDS points to is
74  immediately removed.
75 
76  When a goal is removed, the GDS is not immediately removed. Instead,
77  whenever a WME is removed (or when it is added to another GDS), we check
78  to also make certain that its GDS has other WMEs on the wmes_in_gds DLL.
79  If not, then we remove the GDS then. This delay avoids having to scan
80  over all the WMEs in the GDS in addition to removing the goal (i.e., the
81  maintenance cost is amortized over a number of WM phases).
82 
83  */
84 
85 typedef struct gds_struct {
86  Symbol *goal; /* pointer to the goal for the dependency set */
87  wme *wmes_in_gds; /* pointer to the dll of WMEs in GDS of goal */
89 /* REW: end 09.15.96 */
90 
91 /* ------------------------------------------------------------------------
92  Preferences
93 
94  Fields in a preference:
95 
96  type: indicates the type of the preference. This is one of the
97  types defined below: ACCEPTABLE_PREFERENCE_TYPE, etc.
98 
99  o_supported: TRUE iff the preference has o-support
100 
101  in_tm: TRUE iff the preference is currently in temporary memory
102 
103  on_goal_list: TRUE iff the preference is on the list of preferences
104  supported by its match goal (see all_of_goal_next below)
105 
106  reference_count: (see below)
107 
108  id, attr, value, referent: points to the symbols. Referent is only
109  used for binary preferences.
110 
111  slot: points to the slot this preference is for. (NIL if the
112  preference is not in TM.)
113 
114  next, prev: used for a doubly-linked list of preferences of the
115  same type in that particular slot
116 
117  all_of_slot_next, all_of_slot_prev: used for a doubly-linked list
118  of all preferences (of any type) in that particular slot
119 
120  all_of_goal_next, all_of_goal_prev: used for a doubly-linked list
121  of all preferences supported by this particular match goal.
122  This is needed in order to remove all o-support from a particular
123  goal when that goal is removed from the context stack.
124 
125  next_clone, prev_clone: used for a doubly-linked list of all "clones"
126  of this preference. When a result is returned from a subgoal and a
127  chunk is built, we get two copies of the "same" preference, one from
128  the subgoal's production firing, and one from the chunk instantiation.
129  If results are returned more than one level, or the same result is
130  returned simultaneously by multiple production firings, we can get
131  lots of copies of the "same" preference. These clone preferences
132  are kept on a list so that we can find the right one to backtrace
133  through, given a wme supported by "all the clones."
134 
135  inst: points to the instantiation that generated this preference
136 
137  inst_next, inst_prev: used for a doubly-linked list of all
138  existing preferences that were generated by that instantiation
139 
140  next_candidate: used by the decider for lists of candidate values
141  for a certain slot
142 
143  next_result: used by the chunker for a list of result preferences
144 
145  Reference counts on preferences:
146  +1 if the preference is currently in TM
147  +1 for each instantiation condition that points to it (bt.trace)
148  +1 if it supports an installed context WME
149 
150  We deallocate a preference if:
151  (1) reference_count==0 and all its clones have reference_count==0
152  (hence it couldn't possibly be needed anymore)
153  or (2) its match goal is removed from the context stack
154  (hence there's no way we'll ever want to BT through it)
155 ------------------------------------------------------------------------ */
156 
157 /* WARNING: preference types must be numbered 0..(NUM_PREFERENCE_TYPES-1),
158  because the slot structure contains an array using these indices. */
159 
160 #define ACCEPTABLE_PREFERENCE_TYPE 0
161 #define REQUIRE_PREFERENCE_TYPE 1
162 #define REJECT_PREFERENCE_TYPE 2
163 #define PROHIBIT_PREFERENCE_TYPE 3
164 #define RECONSIDER_PREFERENCE_TYPE 4
165 #define UNARY_INDIFFERENT_PREFERENCE_TYPE 5
166 #define UNARY_PARALLEL_PREFERENCE_TYPE 6
167 #define BEST_PREFERENCE_TYPE 7
168 #define WORST_PREFERENCE_TYPE 8
169 #define BINARY_INDIFFERENT_PREFERENCE_TYPE 9
170 #define BINARY_PARALLEL_PREFERENCE_TYPE 10
171 #define BETTER_PREFERENCE_TYPE 11
172 #define WORSE_PREFERENCE_TYPE 12
173 #define NUMERIC_INDIFFERENT_PREFERENCE_TYPE 13
174 #define NUM_PREFERENCE_TYPES 14
175 
176 #ifdef USE_MACROS
177 
178 #define preference_is_unary(p) ((p)<9)
179 #define preference_is_binary(p) ((p)>8)
180 
181 #else
182 
184 {
185  return (p < 9);
186 }
187 
189 {
190  return (p > 8);
191 }
192 
193 #endif /* USE_MACROS */
194 
195 #ifdef __cplusplus
196 //extern "C" {
197 #endif
198 
199  extern const char * preference_name[NUM_PREFERENCE_TYPES];
200 
201 #ifdef __cplusplus
202 //}
203 #endif
204 
205 typedef struct preference_struct {
206  byte type; /* acceptable, better, etc. */
207  Bool o_supported; /* is the preference o-supported? */
208  Bool in_tm; /* is this currently in TM? */
209  Bool on_goal_list; /* is this pref on the list for its match goal */
210  uint64_t reference_count;
215  struct slot_struct *slot;
216 
217  /* dll of pref's of same type in same slot */
219 
220  /* dll of all pref's in same slot */
222 
223  /* dll of all pref's from the same match goal */
225 
226  /* dll (without header) of cloned preferences (created when chunking) */
228 
233 
237 
239 
240 } preference;
241 
242 /* Decl'd in prefmem.cpp and needed in decide.cpp */
243 extern Bool remove_preference_from_clones (agent* thisAgent, preference *pref);
244 
245 /* ------------------------------------------------------------------------
246 
247  Impasse Types
248 
249 ------------------------------------------------------------------------ */
250 
251 #define NONE_IMPASSE_TYPE 0 /* no impasse */
252 #define CONSTRAINT_FAILURE_IMPASSE_TYPE 1
253 #define CONFLICT_IMPASSE_TYPE 2
254 #define TIE_IMPASSE_TYPE 3
255 #define NO_CHANGE_IMPASSE_TYPE 4
256 
257 /* ------------------------------------------------------------------------
258  Slots
259 
260  Fields in a slot:
261 
262  next, prev: used for a doubly-linked list of all slots for a certain
263  identifier.
264 
265  id, attr: identifier and attribute of the slot
266 
267  wmes: header of a doubly-linked list of all wmes in the slot
268 
269  acceptable_preference_wmes: header of doubly-linked list of all
270  acceptable preference wmes in the slot. (This is only used for
271  context slots.)
272 
273  all_preferences: header of a doubly-linked list of all preferences
274  currently in the slot
275 
276  preferences[NUM_PREFERENCE_TYPES]: array of headers of doubly-linked
277  lists, one for each possible type of preference. These store
278  all the preferences, sorted into lists according to their types.
279  Within each list, the preferences are sorted according to their
280  match goal, with the pref. supported by the highest goal at the
281  head of the list.
282 
283  impasse_id: points to the identifier of the attribute impasse object
284  for this slot. (NIL if the slot isn't impassed.)
285 
286  isa_context_slot: TRUE iff this is a context slot
287 
288  impasse_type: indicates the type of the impasse for this slot. This
289  is one of NONE_IMPASSE_TYPE, CONSTRAINT_FAILURE_IMPASSE_TYPE, etc.
290 
291  marked_for_possible_removal: TRUE iff this slot is on the list of
292  slots that might be deallocated at the end of the current top-level
293  phase.
294 
295  changed: indicates whether the preferences for this slot have changed.
296  For non-context slots, this is either NIL or a pointer to the
297  corresponding dl_cons in changed_slots (see decide.c); for context
298  slots, it's just a zero/nonzero flag.
299 
300  acceptable_preference_changed: for context slots only; this is zero
301  if no acceptable or require preference in this slot has changed;
302  if one has changed, it points to a dl_cons.
303 ------------------------------------------------------------------------ */
304 
305 typedef struct slot_struct {
306  struct slot_struct *next, *prev; /* dll of slots for this id */
307  Symbol *id; /* id, attr of the slot */
309  wme *wmes; /* dll of wmes in the slot */
310  wme *acceptable_preference_wmes; /* dll of acceptable pref. wmes */
311  preference *all_preferences; /* dll of all pref's in the slot */
312  preference *preferences[NUM_PREFERENCE_TYPES]; /* dlls for each type */
313  Symbol *impasse_id; /* NIL if slot is not impassed */
317  dl_cons *changed; /* for non-context slots: points to the corresponding
318  dl_cons in changed_slots; for context slots: just
319  zero/nonzero flag indicating slot changed */
320  dl_cons *acceptable_preference_changed; /* for context slots: either zero,
321  or points to dl_cons if the slot
322  has changed + or ! pref's */
323 
325 
326 } slot;
327 
328 /* -------------------------------------------------------------------
329  Tests
330 
331  Tests in conditions can be blank (null) tests, tests for equality
332  with a variable or constant, or more complicated tests (such as
333  not-equal tests, conjunctive tests, etc.). We use some bit twiddling
334  here to minimize space. We use just a pointer to represent any kind
335  of test. For blank tests, this is the NIL pointer. For equality tests,
336  it points to the symbol referent of the test. For other kinds of tests,
337  bit 0 of the pointer is set to 1, and the pointer (minus 1) points to
338  a complex_test structure. (A field in the complex_test structure
339  further indicates the type of the test.)
340 ------------------------------------------------------------------- */
341 
342 typedef char * test;
343 
344 #ifdef USE_MACROS
345 
346 #define test_is_blank_test(t) ((t)==NIL)
347 #define test_is_complex_test(t) (((uint64_t)(t)) & 1)
348 #define test_is_blank_or_equality_test(t) (! test_is_complex_test(t))
349 
350 #define make_blank_test() ((test)NIL)
351 #define make_equality_test(sym) ((sym)->common.reference_count++, (test)(sym)) // what's this???
352 #define make_equality_test_without_adding_reference(sym) ((test)(sym))
353 #define make_blank_or_equality_test(sym_or_nil) \
354  ((sym_or_nil) ? make_equality_test(sym_or_nil) : make_blank_test() )
355 #define make_test_from_complex_test(ct) ((test) (((char *)(ct))+1))
356 
357 #define referent_of_equality_test(t) ((Symbol *) (t))
358 #define complex_test_from_test(t) ((complex_test *) (((char *)(t))-1))
359 
360 #else
361 
363 {
364  return (t == NIL);
365 }
366 
369 //#ifdef _MSC_VER
370 //#pragma warning (disable : 4311)
371 //#endif
372 
374 {
375  return (char)(
376  reinterpret_cast<uint64_t>(t)
377  & 1);
378 }
379 
380 #ifdef _MSC_VER
381 #pragma warning (default : 4311)
382 #endif
383 
385 {
386  return (!test_is_complex_test(t));
387 }
388 
390 {
391  return static_cast<test>(NIL);
392 }
393 
394 inline test make_equality_test(Symbol * sym) // is this equivalent to the macro above??
395 {
396  (sym)->common.reference_count++;
397 #ifdef DEBUG_SYMBOL_REFCOUNTS
398  char buf[64];
399  OutputDebugString(symbol_to_string(0, (sym), FALSE, buf, 64));
400  OutputDebugString(":+ ");
401  OutputDebugString(_itoa((sym)->common.reference_count, buf, 10));
402  OutputDebugString("\n");
403 #endif // DEBUG_SYMBOL_REFCOUNTS
404  return reinterpret_cast<test>(sym);
405 }
406 
408 {
409  return reinterpret_cast<test>(sym);
410 }
411 
413 {
414  return ((sym_or_nil) ? (make_equality_test(sym_or_nil)) : make_blank_test());
415 }
416 
418 {
419  return reinterpret_cast<test>(ct) + 1;
420 }
421 
423 {
424  return reinterpret_cast<Symbol *>(t);
425 }
426 
428 {
429  return reinterpret_cast<complex_test *>(t - 1);
430 }
431 
432 #endif /* USE_MACROS */
433 
434 typedef struct complex_test_struct {
435  byte type; /* see definitions below */
437  Symbol *referent; /* for relational tests */
438  ::list *disjunction_list; /* for disjunction tests */
439  ::list *conjunct_list; /* for conjunctive tests */
440  } data;
441 } complex_test;
442 
443 /* types of the complex_test's */
444 /* WARNING -- none of these can be 254 or 255 -- see rete.cpp */
445 //#define NOT_EQUAL_TEST 1 /* various relational tests */
446 //#define LESS_TEST 2
447 //#define GREATER_TEST 3
448 //#define LESS_OR_EQUAL_TEST 4
449 //#define GREATER_OR_EQUAL_TEST 5
450 //#define SAME_TYPE_TEST 6
451 //#define DISJUNCTION_TEST 7 /* item must be one of a list of constants */
452 //#define CONJUNCTIVE_TEST 8 /* item must pass each of a list of tests */
453 //#define GOAL_ID_TEST 9 /* item must be a goal identifier */
454 //#define IMPASSE_ID_TEST 10 /* item must be an impasse identifier */
456  NOT_EQUAL_TEST = 1, /* various relational tests */
462  DISJUNCTION_TEST = 7, /* item must be one of a list of constants */
463  CONJUNCTIVE_TEST = 8, /* item must pass each of a list of tests */
464  GOAL_ID_TEST = 9, /* item must be a goal identifier */
465  IMPASSE_ID_TEST = 10 /* item must be an impasse identifier */
466 };
467 
468 #define NUM_TEST_TYPES 10
469 
470 //
471 // Symbol types.
472 //
473 #define VARIABLE_SYMBOL_TYPE 0
474 #define IDENTIFIER_SYMBOL_TYPE 1
475 #define SYM_CONSTANT_SYMBOL_TYPE 2
476 #define INT_CONSTANT_SYMBOL_TYPE 3
477 #define FLOAT_CONSTANT_SYMBOL_TYPE 4
478 #define NUM_SYMBOL_TYPES 5
479 #define NUM_PRODUCTION_TYPES 5
480 
481 
482 /* -------------------------------------------------------------------
483  Conditions
484 
485  Conditions are used for two things: (1) to represent the LHS of newly
486  entered productions (new SP's or chunks); and (2) to represent the
487  instantiated LHS in production instantiations.
488 
489  Fields in a condition:
490 
491  type: indicates the type of condition: either POSITIVE_CONDITION,
492  NEGATIVE_CONDITION, or CONJUNCTIVE_NEGATION_CONDITION.
493 
494  already_in_tc: (reserved for use by the cond_is_in_tc() stuff in
495  production.c)
496 
497  next, prev: used for a doubly-linked list of all conditions on the
498  LHS, or all subconditions of an NCC.
499 
500  data.tests.id_test, data.tests.attr_test, data.tests.value_test:
501  for positive and negative conditions, these are the three wme
502  field tests for the condition.
503 
504  test_for_acceptable_preference: for positive and negative conditions,
505  this is TRUE iff the condition tests for acceptable preference wmes.
506 
507  data.ncc.top, data.ncc.bottom: for NCC's, these point to the top and
508  bottom of the subconditions likned list.
509 
510  bt: for top-level positive conditions in production instantiations,
511  this structure gives information for that will be used in backtracing.
512 
513  reorder: (reserved for use by the reorderer)
514 ------------------------------------------------------------------- */
515 
516 /* --- types of conditions --- */
517 #define POSITIVE_CONDITION 0
518 #define NEGATIVE_CONDITION 1
519 #define CONJUNCTIVE_NEGATION_CONDITION 2
520 
521 /* --- info on conditions used for backtracing (and by the rete) --- */
522 typedef struct bt_info_struct {
523  wme * wme_; /* the actual wme that was matched */
524  goal_stack_level level; /* level (at firing time) of the id of the wme */
525  preference *trace; /* preference for BT, or NIL */
526 
527  /* mvp 5-17-94 */
528  ::list *prohibits; /* list of prohibit prefs to backtrace through */
529 } bt_info;
530 
531 /* --- info on conditions used only by the reorderer --- */
532 typedef struct reorder_info_struct {
533  ::list *vars_requiring_bindings; /* used only during reordering */
534  struct condition_struct *next_min_cost; /* used only during reordering */
535 } reorder_info;
536 
537 /* --- info on positive and negative conditions only --- */
538 typedef struct three_field_tests_struct {
543 
544 /* --- info on negated conjunctive conditions only --- */
545 typedef struct ncc_info_struct {
548 } ncc_info;
549 
550 /* --- finally, the structure of a condition --- */
551 typedef struct condition_struct {
553  Bool already_in_tc; /* used only by cond_is_in_tc stuff */
554  Bool test_for_acceptable_preference; /* for pos, neg cond's only */
557  three_field_tests tests; /* for pos, neg cond's only */
558  ncc_info ncc; /* for ncc's only */
559  } data;
560  bt_info bt; /* for top-level positive cond's: used for BT and by the rete */
561  reorder_info reorder; /* used only during reordering */
562 } condition;
563 
564 #ifdef __cplusplus
565 //}
566 #endif
567 
568 #endif