Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
production.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 /* -------------------------------------------------------------------
7  production.h
8 
9  Fields in a production:
10 
11  name: points to the name of the production (a symbol)
12 
13  documentation: points to a string (a memory_block_for_string) giving
14  user-provided documentation about the production, or NIL if the
15  user didn't give any documentation for it.
16 
17  reference_count: (see below)
18 
19  firing_count: the number of times this production has ever fired
20  since it was created. (Note that this is not reset by an init-soar.)
21 
22  next, prev: used for a doubly-linked list of productions of the same
23  type (see below). The list header is all_productions_of_type[].
24 
25  type: the type of the production: USER_PRODUCTION_TYPE,
26  DEFAULT_PRODUCTION_TYPE, CHUNK_PRODUCTION_TYPE, or
27  JUSTIFICATION_PRODUCTION_TYPE.
28 
29  declared_support: indicates whether the production was declared
30  :o-support or :i-support. This field is either UNDECLARED_SUPPORT,
31  DECLARED_O_SUPPORT, or DECLARED_I_SUPPORT.
32 
33  trace_firings: TRUE iff a (pwatch) has been set on this production.
34 
35  p_node: If the production is currently in the Rete, this points to
36  the corresponding p_node in the Rete. If the production is not in
37  the Rete, this field is NIL.
38 
39  action_list: singly-linked list of the RHS actions of the production.
40 
41  rhs_unbound_variables: A (consed) list of variables used on the RHS
42  that aren't bound on the LHS, in the order of their indices (for
43  rhs_values). For chunks, this is NIL, since we discard chunk
44  variable names.
45 
46  instantiations: header for a doubly-linked list of the instantiations
47  of this production that are currently in the match set (i.e.,
48  Rete-supported).
49 
50  OPERAND_which_assert_list: (need comment info from REW or RCHONG)
51 
52  Reference counts on productions:
53  +1 if it's in production memory (i.e., hasn't been excised)
54  +1 for each existing instantiation pointing to it
55  We deallocate a production if its reference_count goes to 0.
56 ------------------------------------------------------------------- */
57 
58 #ifndef PRODUCTION_H
59 #define PRODUCTION_H
60 
61 #ifdef __cplusplus
62 //extern "C"
63 //{
64 #endif
65 
66 #define UNDECLARED_SUPPORT 0
67 #define DECLARED_O_SUPPORT 1
68 #define DECLARED_I_SUPPORT 2
69 
70 /* RCHONG: begin 10.11 */
71 
72 #define PE_PRODS 0
73 #define IE_PRODS 1
74 #define NO_SAVED_PRODS -1
75 
76 /* RCHONG: end 10.11 */
77 
78 struct not_struct;
79 
80 typedef char Bool;
81 typedef char * test;
82 typedef char * rhs_value;
83 typedef unsigned char byte;
84 typedef uint64_t tc_number;
85 typedef struct action_struct action;
86 typedef struct condition_struct condition;
87 typedef struct cons_struct cons;
88 typedef struct agent_struct agent;
89 typedef cons list;
90 typedef union symbol_union Symbol;
91 
92 #include <map>
93 #include <set>
94 
95 typedef std::map< Symbol*, Symbol* > rl_symbol_map;
96 typedef std::set< rl_symbol_map > rl_symbol_map_set;
97 
98 typedef struct production_struct {
100  char *documentation; /* pointer to memory block, or NIL */
101  char *filename; /* name of source file, or NIL. kjh CUSP(b11) */
102  uint64_t reference_count;
103  uint64_t firing_count; /* how many times it's fired */
104  struct production_struct *next, *prev; /* used for dll */
107  Bool trace_firings; /* used by pwatch */
108  struct rete_node_struct *p_node; /* NIL if it's not in the rete */
109  action *action_list; /* RHS actions */
110  ::list *rhs_unbound_variables; /* RHS vars not bound on LHS */
111  struct instantiation_struct *instantiations; /* dll of inst's in MS */
112  int OPERAND_which_assert_list; /* RCHONG: 10.11 */
113  byte interrupt; /* SW: 7.31.03 */
114  bool already_fired; /* RPM test workaround for bug #139 */
115 
116  bool rl_rule; /* if true, is a Soar-RL rule */
117  double rl_update_count; /* number of (potentially fractional) updates to this rule */
118  unsigned int rl_ref_count; /* number of states referencing this rule in prev_op_rl_rules list */
119 
120  // Per-input memory parameters for delta bar delta algorithm
123 
124  double rl_ecr; // expected current reward (discounted reward)
125  double rl_efr; // expected future reward (discounted next state)
126 
129 } production;
130 
131 /* ========================================================================
132 
133  Various utility routines for manipulating productions and parts thereof.
134  Also includes the reorderer and compile-time o-support calculations.
135 
136  Init_production_utilities() should be called before anything else here.
137 ======================================================================== */
138 
139 /* This structure is used to break ties in favor of non-multi-attributes */
140 typedef struct multi_attributes_struct {
142  int64_t value;
145 
146 extern void init_production_utilities (agent* thisAgent);
147 
148 /* ------------------------------------------ */
149 /* Utilities for symbols and lists of symbols */
150 /* ------------------------------------------ */
151 
152 /* --- Looks at a symbol, returns appropriate first letter for a dummy
153  variable or identifier to follow it. Returns '*' if none found. --- */
154 extern char first_letter_from_symbol (Symbol *sym);
155 
156 /* --- Takes a list of symbols and returns a copy of the same list,
157  incrementing the reference count on each symbol in the list. --- */
159 
160 /* --- Frees a list of symbols, decrementing their reference counts. --- */
161 extern void deallocate_symbol_list_removing_references (agent* thisAgent, ::list *sym_list);
162 
163 /* ------------------- */
164 /* Utilities for tests */
165 /* ------------------- */
166 
167 extern void add_all_variables_in_action (agent* thisAgent, action *a, tc_number tc,
168  ::list **var_list);
169 extern void add_bound_variables_in_test (agent* thisAgent, test t, tc_number tc,
170  ::list **var_list);
171 extern void add_bound_variables_in_condition (agent* thisAgent, condition *c, tc_number tc,
172  ::list **var_list);
173 extern void unmark_variables_and_free_list (agent* thisAgent, ::list *var_list);
174 
175 /* --- Takes a test and returns a new copy of it. --- */
176 extern test copy_test (agent* thisAgent, test t);
177 
178 /* --- Same as copy_test(), only it doesn't include goal or impasse tests
179  in the new copy. The caller should initialize the two flags to FALSE
180  before calling this routine; it sets them to TRUE if it finds a goal
181  or impasse test. --- */
183  (agent* thisAgent, test t, Bool *removed_goal, Bool *removed_impasse);
184 
185 /* --- Deallocates a test. --- */
186 extern void deallocate_test (agent* thisAgent, test t);
187 
188 /* --- Destructively modifies the first test (t) by adding the second
189  one (add_me) to it (usually as a new conjunct). The first test
190  need not be a conjunctive test. --- */
191 extern void add_new_test_to_test (agent* thisAgent, test *t, test add_me);
192 
193 /* --- Same as above, only has no effect if the second test is already
194  included in the first one. --- */
195 extern void add_new_test_to_test_if_not_already_there (agent* thisAgent, test *t, test add_me, bool neg);
196 
197 /* --- Returns TRUE iff the two tests are identical.
198  If neg is true, ignores order of members in conjunctive tests
199  and assumes variables are all equal. --- */
200 extern Bool tests_are_equal (test t1, test t2, bool neg);
201 
202 /* --- Returns a hash value for the given test. --- */
203 extern uint32_t hash_test (agent* thisAgent, test t);
204 
205 /* --- Returns TRUE iff the test contains an equality test for the given
206  symbol. If sym==NIL, returns TRUE iff the test contains any equality
207  test. --- */
209 
210 /* --- Looks for goal or impasse tests (as directed by the two flag
211  parameters) in the given test, and returns TRUE if one is found. --- */
213  Bool look_for_goal,
214  Bool look_for_impasse);
215 
216 /* --- Looks through a test, and returns a new copy of the first equality
217  test it finds. Signals an error if there is no equality test in the
218  given test. --- */
219 extern test copy_of_equality_test_found_in_test (agent* thisAgent, test t);
220 
221 /* --- Looks through a test, returns appropriate first letter for a dummy
222  variable to follow it. Returns '*' if none found. --- */
223 extern char first_letter_from_test (test t);
224 
225 /* ------------------------ */
226 /* Utilities for conditions */
227 /* ------------------------ */
228 
229 /* --- Deallocates a condition list (including any NCC's and tests in it). */
230 extern void deallocate_condition_list (agent* thisAgent, condition *cond_list);
231 
232 /* --- Returns a new copy of the given condition. --- */
233 extern condition *copy_condition (agent* thisAgent, condition *cond);
234 
235 /* --- Copies the given condition list, returning pointers to the
236  top-most and bottom-most conditions in the new copy. --- */
237 extern void copy_condition_list (agent* thisAgent, condition *top_cond, condition **dest_top,
238  condition **dest_bottom);
239 
240 /* --- Returns TRUE iff the two conditions are identical. --- */
241 extern Bool conditions_are_equal (condition *c1, condition *c2);
242 
243 /* --- Returns a hash value for the given condition. --- */
244 extern uint32_t hash_condition (agent* thisAgent, condition *cond);
245 
246 /* ------------------------------------ */
247 /* Utilities for actions and RHS values */
248 /* ------------------------------------ */
249 
250 /* --- Deallocates the given rhs_value. --- */
251 extern void deallocate_rhs_value (agent* thisAgent, rhs_value rv);
252 
253 /* --- Returns a new copy of the given rhs_value. --- */
254 extern rhs_value copy_rhs_value (agent* thisAgent, rhs_value rv);
255 
256 /* --- Deallocates the given action (singly-linked) list. --- */
257 extern void deallocate_action_list (agent* thisAgent, action *actions);
258 
259 /* --- Looks through an rhs_value, returns appropriate first letter for a
260  dummy variable to follow it. Returns '*' if none found. --- */
261 extern char first_letter_from_rhs_value (rhs_value rv);
262 
263 /* ------------------ */
264 /* Utilities for nots */
265 /* ------------------ */
266 
267 /* --- Deallocates the given (singly-linked) list of Nots. --- */
268 extern void deallocate_list_of_nots (agent* thisAgent, not_struct *nots);
269 
270 /* --------------------------------------------------------------------
271  Transitive Closure Utilities
272  Marking, Unmarking, and Collecting Symbols
273 
274  Get_new_tc_number() is called from lots of places. Any time we need
275  to mark a set of identifiers and/or variables, we get a new tc_number
276  by calling this routine, then proceed to mark various ids or vars
277  by setting the sym->id.tc_num or sym->var.tc_num fields.
278 
279  Sometimes in addition to marking symbols using their tc_num fields,
280  we also want to build up a list of the symbols we've marked. So,
281  the routines here take an "id_list" or "var_list" argument. This
282  argument should be NIL if no such list is desired. If non-NIL, it
283  should point to the header of the linked list being built.
284 
285  Transitive Closure Calculations for Conditions and Actions
286 
287  Usage:
288  1. Set my_tc = get_new_tc_number() to start a new TC
289  2. (optional) If you want linked lists of symbols in the TC, initialize
290  id_list=NIL and var_list=NIL.
291  If you're not using id_list and/or var_list, give NIL for "&id_list"
292  and/or "&var_list" in the function calls below.
293  3. (optional) setup any id's or var's that you want to include in the
294  initial TC, by calling
295  add_symbol_to_tc (sym, my_tc, &id_list, &var_list)
296  (If not using id_list or var_list, you can just mark
297  sym->{id,var}.tc_num = my_tc instead.)
298  4. To do the work you want, use any of the following any number of times:
299  add_cond_to_tc (cond, my_tc, &id_list, &var_list);
300  add_action_to_tc (cond, my_tc, &id_list, &var_list);
301  result = cond_is_in_tc (cond, my_tc);
302  result = action_is_in_tc (action, my_tc);
303  5. When finished, free the cons cells in id_list and var_list (but
304  don't call symbol_remove_ref() on the symbols in them).
305 
306  Warning: actions must not contain reteloc's or rhs unbound variables here.
307 -------------------------------------------------------------------- */
308 
309 tc_number get_new_tc_number (agent* thisAgent);
310 
311 extern void add_symbol_to_tc (agent* thisAgent, Symbol *sym, tc_number tc,
312  ::list **id_list, ::list **var_list);
313 extern void add_cond_to_tc (agent* thisAgent, condition *c, tc_number tc,
314  ::list **id_list, ::list **var_list);
315 extern void add_action_to_tc (agent* thisAgent, action *a, tc_number tc,
316  ::list **id_list, ::list **var_list);
317 extern Bool cond_is_in_tc (agent* thisAgent, condition *cond, tc_number tc);
318 extern Bool action_is_in_tc (action *a, tc_number tc);
319 
320 /* --------------------------------------------------------------------
321  Variable Generator
322 
323  These routines are used for generating new variables. The variables
324  aren't necessarily "completely" new--they might occur in some existing
325  production. But we usually need to make sure the new variables don't
326  overlap with those already used in a *certain* production--for instance,
327  when variablizing a chunk, we don't want to introduce a new variable that
328  conincides with the name of a variable already in an NCC in the chunk.
329 
330  To use these routines, first call reset_variable_generator(), giving
331  it lists of conditions and actions whose variables should not be
332  used. Then call generate_new_variable() any number of times; each
333  time, you give it a string to use as the prefix for the new variable's
334  name. The prefix string should not include the opening "<".
335 -------------------------------------------------------------------- */
336 
337 extern void reset_variable_generator (agent* thisAgent,
338  condition *conds_with_vars_to_avoid,
339  action *actions_with_vars_to_avoid);
340 extern Symbol *generate_new_variable (agent* thisAgent, const char *prefix);
341 
342 /* -------------------------------------------------------------------
343  Production Management
344 
345  For each type of production, we maintain a doubly-linked list of
346  all productions of that type. The headers of these dll's are
347  stored in the array all_productions_of_type[]. Another array,
348  num_productions_of_type[], keeps counts of how many productions
349  there are of each type.
350 
351  Production_add_ref() and production_remove_ref() are macros for
352  incrementing and decrementing the reference count on a production.
353  Production_remove_ref() also deallocates the production if the
354  count goes to 0.
355 
356  Make_production() does reordering, compile-time o-support calc's,
357  and builds and returns a production structure for a new production.
358  It does not enter the production into the Rete net, however.
359  The "type" argument should be one of USER_PRODUCTION_TYPE, etc.
360  The flag "reorder_nccs" tells whether to recursively reorder
361  the subconditions of NCC's--this is not necessary for newly
362  built chunks, as their NCC's are copies of other NCC's in SP's that
363  have already been reordered. If any error occurs, make_production()
364  returns NIL.
365 
366  Deallocate_production() and excise_production() do just what they
367  say. Normally deallocate_production() should be invoked only via
368  the production_remove_ref() macro.
369 ------------------------------------------------------------------- */
370 
371 extern production *make_production (agent* thisAgent,
372  byte type,
373  Symbol *name,
374  condition **lhs_top,
375  condition **lhs_bottom,
376  action **rhs_top,
377  Bool reorder_nccs);
378 extern void deallocate_production (agent* thisAgent, production *prod);
379 extern void excise_production (agent* thisAgent, production *prod, Bool print_sharp_sign);
380 extern void excise_all_productions_of_type(agent* thisAgent,
381  byte type,
382  Bool print_sharp_sign);
383 extern void excise_all_productions(agent* thisAgent,
384  Bool print_sharp_sign);
385 
387 
388 #ifdef USE_MACROS
389 
390 #define production_add_ref(p) { (p)->reference_count++; }
391 #define production_remove_ref(thisAgent, p) { \
392  (p)->reference_count--; \
393  if ((p)->reference_count == 0) \
394  deallocate_production(thisAgent, p); }
395 
396 #else
397 
399 {
400  (p)->reference_count++;
401 }
402 
403 inline void production_remove_ref(agent* thisAgent, production * p)
404 {
405  (p)->reference_count--;
406  if ((p)->reference_count == 0)
407  deallocate_production(thisAgent, p);
408 }
409 
410 #endif /* USE_MACROS */
411 
412 #ifdef __cplusplus
413 //}
414 #endif
415 
416 #endif