Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Typedefs | Functions
decide.h File Reference

Go to the source code of this file.

Typedefs

typedef struct agent_struct agent
typedef char Bool
typedef unsigned char byte
typedef struct instantiation_struct instantiation
typedef struct preference_struct preference
typedef struct slot_struct slot
typedef union symbol_union Symbol
typedef struct wme_struct wme

Functions

Symbolattribute_of_existing_impasse (agent *thisAgent, Symbol *goal)
void clear_goal_stack (agent *thisAgent)
unsigned int count_candidates (preference *candidates)
void create_gds_for_goal (agent *thisAgent, Symbol *goal)
void create_top_goal (agent *thisAgent)
void do_buffered_wm_and_ownership_changes (agent *thisAgent)
void do_decision_phase (agent *thisAgent, bool predict=false)
void do_working_memory_phase (agent *thisAgent)
void elaborate_gds (agent *thisAgent)
void free_parent_list (agent *thisAgent)
void gds_invalid_so_remove_goal (agent *thisAgent, wme *w)
int GDS_PrintCmd (int clientData, void *interp, int argc, char *argv[])
void init_decider (agent *thisAgent)
void mark_context_slot_as_acceptable_preference_changed (agent *thisAgent, slot *s)
void post_link_addition (agent *thisAgent, Symbol *from, Symbol *to)
void post_link_removal (agent *thisAgent, Symbol *from, Symbol *to)
void print_lowest_slot_in_context_stack (agent *thisAgent)
void remove_existing_attribute_impasse_for_slot (agent *thisAgent, slot *s)
void remove_existing_context_and_descendents (agent *thisAgent, Symbol *goal)
void remove_operator_if_necessary (agent *thisAgent, slot *s, wme *w)
void remove_wmes_for_context_slot (agent *thisAgent, slot *s)
byte run_preference_semantics_for_consistency_check (agent *thisAgent, slot *s, preference **result_candidates)
byte type_of_existing_impasse (agent *thisAgent, Symbol *goal)
void uniquely_add_to_head_of_dll (agent *thisAgent, instantiation *inst)

Typedef Documentation

typedef struct agent_struct agent

Definition at line 42 of file decide.h.

typedef char Bool

Definition at line 35 of file decide.h.

typedef unsigned char byte

Definition at line 36 of file decide.h.

Definition at line 40 of file decide.h.

typedef struct preference_struct preference

Definition at line 41 of file decide.h.

typedef struct slot_struct slot

Definition at line 39 of file decide.h.

typedef union symbol_union Symbol

Definition at line 37 of file decide.h.

typedef struct wme_struct wme

Definition at line 38 of file decide.h.

Function Documentation

Symbol* attribute_of_existing_impasse ( agent thisAgent,
Symbol goal 
)

Definition at line 2432 of file decide.cpp.

References abort_with_fatal_error(), wme_struct::attr, agent_struct::attribute_symbol, BUFFER_MSG_SIZE, symbol_union::id, identifier_struct::impasse_wmes, identifier_struct::lower_goal, wme_struct::next, NIL, and wme_struct::value.

Referenced by decide_context_slot(), and decision_consistent_with_current_preferences().

{
wme *w;
if (! goal->id.lower_goal) return NIL;
for (w=goal->id.lower_goal->id.impasse_wmes; w!=NIL; w=w->next)
if (w->attr==thisAgent->attribute_symbol) return w->value;
{ char msg[BUFFER_MSG_SIZE];
strncpy (msg, "decide.c: Internal error: couldn't find attribute of existing impasse.\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
return NIL; /* unreachable, but without it, gcc -Wall warns here */
}
void clear_goal_stack ( agent thisAgent)

Definition at line 2791 of file decide.cpp.

References agent_struct::active_goal, do_buffered_wm_and_ownership_changes(), do_input_cycle(), do_output_cycle(), agent_struct::highest_goal_whose_context_changed, NIL, remove_existing_context_and_descendents(), agent_struct::top_goal, and agent_struct::top_state.

Referenced by reinitialize_soar().

{
if (!thisAgent->top_goal)
return;
thisAgent->highest_goal_whose_context_changed = NIL; /* nothing changed yet */
thisAgent->top_state = NIL;
thisAgent->active_goal = NIL;
do_input_cycle(thisAgent); /* tell input functions that the top state is gone */
do_output_cycle(thisAgent); /* tell output functions that output commands are gone */
}
unsigned int count_candidates ( preference candidates)
void create_gds_for_goal ( agent thisAgent,
Symbol goal 
)

Definition at line 3489 of file decide.cpp.

References identifier_struct::gds, agent_struct::gds_pool, gds_struct::goal, symbol_union::id, NIL, print_with_symbols(), and gds_struct::wmes_in_gds.

Referenced by decide_non_context_slot().

{
allocate_with_pool( thisAgent, &( thisAgent->gds_pool ), &gds );
gds->goal = goal;
gds->wmes_in_gds = NIL;
goal->id.gds = gds;
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\nCreated GDS for goal [%y].\n", gds->goal);
#endif
}
void create_top_goal ( agent thisAgent)
void do_buffered_wm_and_ownership_changes ( agent thisAgent)
void do_decision_phase ( agent thisAgent,
bool  predict = false 
)

Definition at line 2761 of file decide.cpp.

References decide_context_slots(), decide_non_context_slots(), do_buffered_wm_and_ownership_changes(), exploration_update_parameters(), and predict_srand_restore_snapshot().

Referenced by do_one_top_level_phase(), and predict_get().

{
predict_srand_restore_snapshot( thisAgent, !predict );
/* phase printing moved to init_soar: do_one_top_level_phase */
decide_context_slots (thisAgent, predict);
if ( !predict )
{
/*
* Bob provided a solution to fix WME's hanging around unsupported
* for an elaboration cycle.
*/
}
}
void do_working_memory_phase ( agent thisAgent)

Definition at line 2737 of file decide.cpp.

References APPLY_PHASE, agent_struct::current_phase, decide_non_context_slots(), do_buffered_wm_and_ownership_changes(), agent_struct::FIRING_TYPE, IE_PRODS, PE_PRODS, print(), agent_struct::sysparams, TRACE_PHASES_SYSPARAM, xml_att_val(), xml_begin_tag(), and xml_end_tag().

Referenced by do_one_top_level_phase(), epmem_respond_to_cmd(), smem_respond_to_cmd(), and wma_go().

{
if (thisAgent->sysparams[TRACE_PHASES_SYSPARAM]) {
if (thisAgent->current_phase == APPLY_PHASE) { /* it's always IE for PROPOSE */
xml_begin_tag(thisAgent, kTagSubphase);
xml_att_val(thisAgent, kPhase_Name, kSubphaseName_ChangingWorkingMemory);
switch (thisAgent->FIRING_TYPE) {
case PE_PRODS:
print (thisAgent, "\t--- Change Working Memory (PE) ---\n",0);
xml_att_val(thisAgent, kPhase_FiringType, kPhaseFiringType_PE);
break;
case IE_PRODS:
print (thisAgent, "\t--- Change Working Memory (IE) ---\n",0);
xml_att_val(thisAgent, kPhase_FiringType, kPhaseFiringType_IE);
break;
}
xml_end_tag(thisAgent, kTagSubphase);
}
}
}
void elaborate_gds ( agent thisAgent)

Definition at line 2928 of file decide.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, add_wme_to_gds(), preference_struct::attr, condition_struct::bt, elaborate_gds(), FALSE, fast_remove_from_dll, find_slot(), free_parent_list(), wme_struct::gds, identifier_struct::gds, instantiation_struct::GDS_evaluated_already, agent_struct::gds_pool, wme_struct::gds_prev, gds_struct::goal, preference_struct::id, symbol_union::id, pi_struct::inst, preference_struct::inst, identifier_struct::level, bt_info_struct::level, instantiation_struct::match_goal, instantiation_struct::match_goal_level, production_struct::name, pi_struct::next, preference_struct::next, condition_struct::next, NIL, preference_struct::o_supported, agent_struct::parent_list_head, POSITIVE_CONDITION, wme_struct::preference, slot_struct::preferences, pi_struct::prev, print(), print_instantiation_with_wmes(), print_preference(), print_with_symbols(), print_wme(), instantiation_struct::prod, TIMETAG_WME_TRACE, instantiation_struct::top_of_instantiated_conditions, TRUE, condition_struct::type, uniquely_add_to_head_of_dll(), wme_struct::value, preference_struct::value, bt_info_struct::wme_, and gds_struct::wmes_in_gds.

Referenced by decide_non_context_slot(), and elaborate_gds().

{
wme *wme_matching_this_cond;
goal_stack_level wme_goal_level;
preference *pref_for_this_wme, *pref;
condition *cond;
parent_inst *curr_pi, *temp_pi;
slot *s;
for (curr_pi=thisAgent->parent_list_head; curr_pi; curr_pi=temp_pi) {
inst = curr_pi->inst;
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\n EXPLORING INSTANTIATION: %y\n",curr_pi->inst->prod->name);
print(thisAgent, " ");
#endif
for (cond=inst->top_of_instantiated_conditions; cond!=NIL; cond=cond->next)
{
if (cond->type != POSITIVE_CONDITION)
continue;
/* We'll deal with negative instantiations after we get the
* positive ones figured out */
wme_matching_this_cond = cond->bt.wme_;
wme_goal_level = cond->bt.level;
pref_for_this_wme = wme_matching_this_cond->preference;
#ifdef DEBUG_GDS
print(thisAgent, "\n wme_matching_this_cond at goal_level = %d : ",
wme_goal_level);
print_wme(thisAgent, wme_matching_this_cond);
if (pref_for_this_wme) {
print(thisAgent, " pref_for_this_wme : ");
print_preference(thisAgent, pref_for_this_wme);
}
#endif
/* WME is in a supergoal or is arch-supported WME
* (except for fake instantiations, which do have prefs, so
* they get handled under "wme is local and i-supported")
*/
if ((pref_for_this_wme == NIL) ||
(wme_goal_level < inst->match_goal_level))
{
#ifdef DEBUG_GDS
if (pref_for_this_wme == NIL)
{
print(thisAgent, " this wme has no preferences (it's an arch-created wme)\n");
}
else if (wme_goal_level < inst->match_goal_level)
{
print(thisAgent, " this wme is in the supergoal\n");
}
print_with_symbols(thisAgent, "inst->match_goal [%y]\n" , inst->match_goal);
#endif
if (wme_matching_this_cond->gds != NIL)
{
/* Then we want to check and see if the old GDS value
* should be changed */
if (wme_matching_this_cond->gds->goal == NIL)
{
/* The goal is NIL: meaning that the goal for the GDS
* is no longer around */
fast_remove_from_dll(wme_matching_this_cond->gds->wmes_in_gds, \
wme_matching_this_cond, wme,
gds_next, gds_prev);
/* We have to check for GDS removal anytime we take a
* WME off the GDS wme list, not just when a WME is
* removed from memory. */
if (!wme_matching_this_cond->gds->wmes_in_gds)
{
if (wme_matching_this_cond->gds->goal) wme_matching_this_cond->gds->goal->id.gds = NIL;
free_with_pool( &( thisAgent->gds_pool ), wme_matching_this_cond->gds );
#ifdef DEBUG_GDS
print(thisAgent, "\n REMOVING GDS FROM MEMORY.");
#endif
}
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, wme_matching_this_cond);
// wme_matching_this_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
// wme_matching_this_cond, gds_next,
// gds_prev);
#ifdef DEBUG_GDS
print(thisAgent, "\n .....GDS' goal is NIL so switching from old to new GDS list....\n");
#endif
}
else if (wme_matching_this_cond->gds->goal->id.level >
{
/* if the WME currently belongs to the GDS of a goal below
* the current one */
/* 1. Take WME off old (current) GDS list
* 2. Check to see if old GDS WME list is empty. If so,
* remove(free) it.
* 3. Add WME to new GDS list
* 4. Update WME pointer to new GDS list
*/
if (inst->match_goal_level == 1)
print(thisAgent, "\n\n\n HELLO! HELLO! The inst->match_goal_level is 1");
fast_remove_from_dll(wme_matching_this_cond->gds->wmes_in_gds, \
wme_matching_this_cond, wme,
gds_next, gds_prev);
if (!wme_matching_this_cond->gds->wmes_in_gds) {
if (wme_matching_this_cond->gds->goal) wme_matching_this_cond->gds->goal->id.gds = NIL;
free_with_pool( &( thisAgent->gds_pool ), wme_matching_this_cond->gds );
#ifdef DEBUG_GDS
print(thisAgent, "\n REMOVING GDS FROM MEMORY.");
#endif
}
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, wme_matching_this_cond);
// wme_matching_this_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
// wme_matching_this_cond, gds_next,
// gds_prev);
#ifdef DEBUG_GDS
print(thisAgent, "\n ....switching from old to new GDS list....\n");
#endif
wme_matching_this_cond->gds = inst->match_goal->id.gds;
}
}
else
{
/* We know that the WME should be in the GDS of the current
* goal if the WME's GDS does not already exist.
* (i.e., if NIL GDS) */
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, wme_matching_this_cond);
// wme_matching_this_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
// wme_matching_this_cond, gds_next, gds_prev);
if (wme_matching_this_cond->gds->wmes_in_gds->gds_prev)
print(thisAgent, "\nDEBUG DEBUG : The new header should never have a prev value.\n");
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\n ......WME did not have defined GDS. Now adding to goal [%y].\n", wme_matching_this_cond->gds->goal);
#endif
} /* end else clause for "if wme_matching_this_cond->gds != NIL" */
#ifdef DEBUG_GDS
print(thisAgent, " Added WME to GDS for goal = %d",
wme_matching_this_cond->gds->goal->id.level);
print_with_symbols(thisAgent, " [%y]\n", wme_matching_this_cond->gds->goal);
#endif
} /* end "wme in supergoal or arch-supported" */
else
{
/* wme must be local */
/* if wme's pref is o-supported, then just ignore it and
* move to next condition */
if (pref_for_this_wme->o_supported == TRUE) {
#ifdef DEBUG_GDS
print(thisAgent, " this wme is local and o-supported\n");
#endif
continue;
}
else {
/* wme's pref is i-supported, so remember it's instantiation
* for later examination */
/* this test avoids "backtracing" through the top state */
if (inst->match_goal_level == 1) {
#ifdef DEBUG_GDS
print(thisAgent, " don't back up through top state\n");
if (inst->prod)
if (inst->prod->name)
print_with_symbols(thisAgent, " don't back up through top state for instantiation %y\n", inst->prod->name);
#endif
continue;
}
else { /* (inst->match_goal_level != 1) */
#ifdef DEBUG_GDS
print(thisAgent, " this wme is local and i-supported\n");
#endif
s = find_slot (pref_for_this_wme->id, pref_for_this_wme->attr);
if (s == NIL)
{
/* this must be an arch-wme from a fake instantiation */
#ifdef DEBUG_GDS
print(thisAgent, "here's the wme with no slot:\t");
print_wme(thisAgent, pref_for_this_wme->inst->top_of_instantiated_conditions->bt.wme_);
#endif
/* this is the same code as above, just using the
* differently-named pointer. it probably should
* be a subroutine */
{
wme *fake_inst_wme_cond;
fake_inst_wme_cond = pref_for_this_wme->inst->top_of_instantiated_conditions->bt.wme_;
if (fake_inst_wme_cond->gds != NIL)
{
/* Then we want to check and see if the old GDS
* value should be changed */
if (fake_inst_wme_cond->gds->goal == NIL)
{
/* The goal is NIL: meaning that the goal for
* the GDS is no longer around */
fast_remove_from_dll(fake_inst_wme_cond->gds->wmes_in_gds,
fake_inst_wme_cond, wme,
gds_next, gds_prev);
/* We have to check for GDS removal anytime we take
* a WME off the GDS wme list, not just when a WME
* is removed from memory. */
if (!fake_inst_wme_cond->gds->wmes_in_gds)
{
if (fake_inst_wme_cond->gds->goal) fake_inst_wme_cond->gds->goal->id.gds = NIL;
free_with_pool( &( thisAgent->gds_pool ), fake_inst_wme_cond->gds );
#ifdef DEBUG_GDS
print(thisAgent, "\n REMOVING GDS FROM MEMORY.");
#endif
}
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, fake_inst_wme_cond);
// fake_inst_wme_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
// fake_inst_wme_cond, gds_next, gds_prev);
#ifdef DEBUG_GDS
print(thisAgent, "\n .....GDS' goal is NIL so switching from old to new GDS list....\n");
#endif
}
else if (fake_inst_wme_cond->gds->goal->id.level > inst->match_goal_level)
{
/* if the WME currently belongs to the GDS of a
*goal below the current one */
/* 1. Take WME off old (current) GDS list
* 2. Check to see if old GDS WME list is empty.
* If so, remove(free) it.
* 3. Add WME to new GDS list
* 4. Update WME pointer to new GDS list
*/
if (inst->match_goal_level == 1)
print(thisAgent, "\n\n\n\n\n HELLO! HELLO! The inst->match_goal_level is 1");
fast_remove_from_dll(fake_inst_wme_cond->gds->wmes_in_gds, \
fake_inst_wme_cond, wme,
gds_next, gds_prev);
if (!fake_inst_wme_cond->gds->wmes_in_gds)
{
if (fake_inst_wme_cond->gds->goal) fake_inst_wme_cond->gds->goal->id.gds = NIL;
free_with_pool( &( thisAgent->gds_pool ), fake_inst_wme_cond->gds );
#ifdef DEBUG_GDS
print(thisAgent, "\n REMOVING GDS FROM MEMORY.");
#endif
}
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, fake_inst_wme_cond);
// fake_inst_wme_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
// fake_inst_wme_cond, gds_next,
// gds_prev);
#ifdef DEBUG_GDS
print(thisAgent, "\n .....switching from old to new GDS list....\n");
#endif
fake_inst_wme_cond->gds = inst->match_goal->id.gds;
}
}
else
{
/* We know that the WME should be in the GDS of
* the current goal if the WME's GDS does not
* already exist. (i.e., if NIL GDS) */
/* JC ADDED: Separate adding wme to GDS as a function */
add_wme_to_gds(thisAgent, inst->match_goal->id.gds, fake_inst_wme_cond);
// fake_inst_wme_cond->gds = inst->match_goal->id.gds;
// insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
// fake_inst_wme_cond,
// gds_next, gds_prev);
if (fake_inst_wme_cond->gds->wmes_in_gds->gds_prev)
print(thisAgent, "\nDEBUG DEBUG : The new header should never have a prev value.\n");
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\n ......WME did not have defined GDS. Now adding to goal [%y].\n", fake_inst_wme_cond->gds->goal);
#endif
}
#ifdef DEBUG_GDS
print(thisAgent, " Added WME to GDS for goal = %d", fake_inst_wme_cond->gds->goal->id.level);
print_with_symbols(thisAgent, " [%y]\n",
fake_inst_wme_cond->gds->goal);
#endif
} /* matches { wme *fake_inst_wme_cond */
}
else
{
/* this was the original "local & i-supported" action */
pref; pref=pref->next)
{
#ifdef DEBUG_GDS
print(thisAgent, " looking at pref for the wme: ");
print_preference(thisAgent, pref);
#endif
/* REW: 2004-05-27: Bug fix
We must check that the value with acceptable pref for the slot
is the same as the value for the wme in the condition, since
operators can have acceptable preferences for values other than
the WME value. We dont want to backtrack thru acceptable prefs
for other operators */
if (pref->value == wme_matching_this_cond->value) {
/* REW BUG: may have to go over all insts regardless
* of this visited_already flag... */
{
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\n adding inst that produced the pref to GDS: %y\n",pref->inst->prod->name);
#endif
/* REW: 2003-12-07 */
/* If the preference comes from a lower level inst, then
ignore it. */
/* Preferences from lower levels must come from result
instantiations;
we just want to use the justification/chunk
instantiations at the match goal level*/
if (pref->inst->match_goal_level <= inst->match_goal_level)
{
uniquely_add_to_head_of_dll(thisAgent, pref->inst);
}
#ifdef DEBUG_GDS
else
{
print_with_symbols(thisAgent, "\n ignoring inst %y because it is at a lower level than the GDS\n",pref->inst->prod->name);
}
#endif
/* REW: 2003-12-07 */
}
#ifdef DEBUG_GDS
else
{
print(thisAgent, " the inst producing this pref was already explored; skipping it\n");
}
#endif
}
#ifdef DEBUG_GDS
else
{
print(thisAgent, " this inst is for a pref with a differnt value than the condition WME; skippint it\n");
}
#endif
} /* for pref = s->pref[ACCEPTABLE_PREF ...*/
}
}
}
}
} /* for (cond = inst->top_of_instantiated_cond ... *;*/
/* remove just used instantiation from list */
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "\n removing instantiation: %y\n",
curr_pi->inst->prod->name);
#endif
if (curr_pi->next != NIL)
curr_pi->next->prev = curr_pi->prev;
if (curr_pi->prev != NIL)
curr_pi->prev->next = curr_pi->next;
if (thisAgent->parent_list_head == curr_pi)
thisAgent->parent_list_head = curr_pi->next;
temp_pi = curr_pi->next;
free(curr_pi);
} /* end of "for (curr_pi = thisAgent->parent_list_head ... */
if (thisAgent->parent_list_head != NIL)
{
#ifdef DEBUG_GDS
print(thisAgent, "\n RECURSING using these parents:\n");
for (curr_pi = thisAgent->parent_list_head;
curr_pi;
curr_pi = curr_pi->next) {
print_with_symbols(thisAgent, " %y\n",curr_pi->inst->prod->name);
}
#endif
/* recursively explore the parents of all the instantiations */
elaborate_gds(thisAgent);
/* free the parent instantiation list. technically, the list
* should be empty at this point ??? */
free_parent_list(thisAgent);
}
} /* end of elaborate_gds */
void free_parent_list ( agent thisAgent)

Definition at line 3477 of file decide.cpp.

References pi_struct::next, NIL, and agent_struct::parent_list_head.

Referenced by decide_non_context_slot(), and elaborate_gds().

{
parent_inst *curr_pi;
for (curr_pi = thisAgent->parent_list_head;
curr_pi;
curr_pi = curr_pi->next)
free(curr_pi);
thisAgent->parent_list_head = NIL;
}
void gds_invalid_so_remove_goal ( agent thisAgent,
wme w 
)

Definition at line 3386 of file decide.cpp.

{
if (thisAgent->soar_verbose_flag || thisAgent->sysparams[TRACE_GDS_SYSPARAM]) {
// BADBAD: the XML code makes this all very ugly
char msgbuf[256];
memset(msgbuf, 0, 256);
snprintf_with_symbols(thisAgent, msgbuf, 255, "Removing state %y because element in GDS changed. WME: ", w->gds->goal);
print_string(thisAgent, msgbuf);
xml_begin_tag(thisAgent, soar_TraceNames::kTagVerbose);
xml_att_val(thisAgent, soar_TraceNames::kTypeString, msgbuf);
print_wme(thisAgent, w); // prints XML, too
xml_end_tag(thisAgent, soar_TraceNames::kTagVerbose);
}
/* REW: begin 11.25.96 */
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
thisAgent->timers_gds.start();
#endif
#endif
/* REW: end 11.25.96 */
/* This call to GDS_PrintCmd will have to be uncommented later. -ajc */
//if (thisAgent->soar_verbose_flag) {} //GDS_PrintCmd();
/* REW: BUG. I have no idea right now if this is a terrible hack or
* actually what we want to do. The idea here is that the context of
* the immediately higher goal above a retraction should be marked as
* having its context changed in order that the architecture doesn't
* look below this level for context changes. I think it's a hack b/c
* it seems like there should aready be mechanisms for doing this in
* the architecture but I couldn't find any.
*/
/* Note: the inner 'if' is correct -- we only want to change
* highest_goal_whose_context_changed if the pointer is currently at
* or below (greater than) the goal which we are going to retract.
* However, I'm not so sure about the outer 'else.' If we don't set
* this to the goal above the retraction, even if the current value
* is NIL, we still seg fault in certain cases. But setting it as we do
* in the inner 'if' seems to clear up the difficulty.
*/
{
{
}
}
else
{
/* If nothing has yet changed (highest_ ... = NIL) then set
* the goal automatically */
// Tell those slots they are changed so that the impasses can be regenerated
// bug 1011
for ( slot* s = thisAgent->highest_goal_whose_context_changed->id.slots; s != 0; s = s->next )
{
if (s->isa_context_slot && !s->changed)
s->changed = reinterpret_cast<dl_cons*>(1); // use non-zero value to indicate change, see definition of slot::changed
}
}
{
print_with_symbols(thisAgent, "\n REMOVING GOAL [%y] due to change in GDS WME ", w->gds->goal);
print_wme(thisAgent, w);
}
/* BUG: Need to reset highest_goal here ???*/
/* usually, we'd call do_buffered_wm_and_ownership_changes() here, but
* we don't need to because it will be done at the end of the working
* memory phase; cf. the end of do_working_memory_phase().
*/
/* REW: begin 11.25.96 */
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
thisAgent->timers_gds.stop();
thisAgent->timers_gds_cpu_time[thisAgent->current_phase].update(thisAgent->timers_gds);
#endif
#endif
/* REW: end 11.25.96 */
}
int GDS_PrintCmd ( int  clientData,
void *  interp,
int  argc,
char *  argv[] 
)
Parameters
clientDataClientData*
interpTcl_Interp*
void init_decider ( agent thisAgent)

Definition at line 2721 of file decide.cpp.

References init_memory_pool(), agent_struct::preference_pool, agent_struct::slot_pool, and agent_struct::wme_pool.

Referenced by init_soar_agent().

{
init_memory_pool (thisAgent, &thisAgent->slot_pool, sizeof(slot), "slot");
init_memory_pool (thisAgent, &thisAgent->wme_pool, sizeof(wme), "wme");
init_memory_pool (thisAgent, &thisAgent->preference_pool,
sizeof(preference), "preference");
}
void mark_context_slot_as_acceptable_preference_changed ( agent thisAgent,
slot s 
)
void post_link_addition ( agent thisAgent,
Symbol from,
Symbol to 
)

Definition at line 302 of file decide.cpp.

References identifier_struct::could_be_a_link_from_below, symbol_union::id, identifier_struct::isa_goal, identifier_struct::isa_impasse, identifier_struct::link_count, print(), print_with_symbols(), agent_struct::promoted_ids, identifier_struct::promotion_level, push(), symbol_add_ref(), and TRUE.

Referenced by add_preference_to_tm(), add_wme_to_wm(), and create_new_impasse().

{
/* --- don't add links to goals/impasses, except the special one
(NIL,goal) --- */
if ((to->id.isa_goal || to->id.isa_impasse) && from)
return;
to->id.link_count++;
#ifdef DEBUG_LINKS
if (from)
print_with_symbols (thisAgent, "\nAdding link from %y to %y", from, to);
else
print_with_symbols (thisAgent, "\nAdding special link to %y", to);
print (" (count=%lu)", to->id.link_count);
#endif
if (!from)
return; /* if adding a special link, we're done */
/* --- if adding link from same level, ignore it --- */
if (from->id.promotion_level == to->id.promotion_level)
return;
/* --- if adding link from lower to higher, mark higher accordingly --- */
if (from->id.promotion_level > to->id.promotion_level) {
return;
}
/* --- otherwise buffer it for later --- */
push (thisAgent, to, thisAgent->promoted_ids);
}
void post_link_removal ( agent thisAgent,
Symbol from,
Symbol to 
)

Definition at line 438 of file decide.cpp.

References agent_struct::disconnected_ids, agent_struct::dl_cons_pool, symbol_union::id, agent_struct::ids_with_unknown_level, insert_at_head_of_dll, identifier_struct::isa_goal, identifier_struct::isa_impasse, dl_cons_struct::item, JUST_UPDATE_COUNT, identifier_struct::level, identifier_struct::link_count, agent_struct::link_update_mode, print(), print_with_symbols(), remove_from_dll, symbol_add_ref(), identifier_struct::unknown_level, and UPDATE_DISCONNECTED_IDS_LIST.

Referenced by remove_existing_attribute_impasse_for_slot(), remove_existing_context_and_descendents(), remove_preference_from_tm(), and remove_wme_from_wm().

{
dl_cons *dc;
/* --- don't remove links to goals/impasses, except the special one
(NIL,goal) --- */
if ((to->id.isa_goal || to->id.isa_impasse) && from) return;
to->id.link_count--;
#ifdef DEBUG_LINKS
if (from) {
print_with_symbols (thisAgent, "\nRemoving link from %y to %y", from, to);
print (" (%d to %d)", from->id.level, to->id.level);
} else {
print_with_symbols (thisAgent, S"\nRemoving special link to %y ", to);
print (" (%d)", to->id.level);
}
print (" (count=%lu)", to->id.link_count);
#endif
/* --- if a gc is in progress, handle differently --- */
if (thisAgent->link_update_mode==JUST_UPDATE_COUNT) return;
(to->id.link_count==0)) {
if (to->id.unknown_level) {
dc = to->id.unknown_level;
remove_from_dll (thisAgent->ids_with_unknown_level, dc, next, prev);
insert_at_head_of_dll (thisAgent->disconnected_ids, dc, next, prev);
} else {
allocate_with_pool (thisAgent, &thisAgent->dl_cons_pool, &dc);
dc->item = to;
to->id.unknown_level = dc;
insert_at_head_of_dll (thisAgent->disconnected_ids, dc, next, prev);
}
return;
}
/* --- if removing a link from a different level, there must be some other
link at the same level, so we can ignore this change --- */
if (from && (from->id.level != to->id.level)) return;
if (! to->id.unknown_level) {
allocate_with_pool (thisAgent, &thisAgent->dl_cons_pool, &dc);
dc->item = to;
to->id.unknown_level = dc;
insert_at_head_of_dll (thisAgent->ids_with_unknown_level, dc, next, prev);
}
}
void print_lowest_slot_in_context_stack ( agent thisAgent)

Definition at line 2805 of file decide.cpp.

References agent_struct::bottom_goal, agent_struct::d_cycle_count, FOR_OPERATORS_TF, FOR_STATES_TF, identifier_struct::higher_goal, symbol_union::id, identifier_struct::operator_slot, print_stack_trace(), TRUE, wme_struct::value, and slot_struct::wmes.

Referenced by do_one_top_level_phase(), and init_agent_memory().

{
/* REW: begin 10.24.97 */
/* This doesn't work yet so for now just print the last selection */
/* if (thisAgent->waitsnc &&
* thisAgent->waitsnc_detect) {
* thisAgent->waitsnc_detect = FALSE;
* print_stack_trace (thisAgent->wait_symbol,
* thisAgent->bottom_goal, FOR_OPERATORS_TF, TRUE);
* print(thisAgent, "\n waiting");
* return;
* }
*/
/* REW: end 10.24.97 */
if (thisAgent->bottom_goal->id.operator_slot->wmes)
/* RCHONG: begin 10.11 */
/*
this coded is needed just so that when an ONC is created in OPERAND
(i.e. if the previous goal's operator slot is not empty), it's stack
trace line doesn't get a number. this is done because in OPERAND,
ONCs are detected for "free".
*/
else {
if (thisAgent->d_cycle_count == 0)
print_stack_trace (thisAgent, thisAgent->bottom_goal,
else {
if (thisAgent->bottom_goal->id.higher_goal &&
print_stack_trace (thisAgent, thisAgent->bottom_goal,
thisAgent->bottom_goal,
}
else {
print_stack_trace (thisAgent, thisAgent->bottom_goal,
thisAgent->bottom_goal,
}
}
}
/* RCHONG: end 10.11 */
}
void remove_existing_attribute_impasse_for_slot ( agent thisAgent,
slot s 
)
void remove_existing_context_and_descendents ( agent thisAgent,
Symbol goal 
)

Definition at line 2134 of file decide.cpp.

References preference_struct::all_of_goal_next, preference_struct::all_of_goal_prev, agent_struct::bottom_goal, agent_struct::chunk_free_problem_spaces, agent_struct::chunky_problem_spaces, cons_equality_fn(), rl_data_struct::eligibility_traces, identifier_struct::epmem_cmd_header, identifier_struct::epmem_header, identifier_struct::epmem_info, agent_struct::epmem_info_pool, epmem_reset(), identifier_struct::epmem_result_header, epmem_data_struct::epmem_wmes, agent_struct::epmem_wmes_pool, extract_list_elements(), FALSE, free_list(), identifier_struct::gds, gds_struct::goal, ms_change_struct::goal, identifier_struct::higher_goal, symbol_union::id, identifier_struct::impasse_wmes, preference_struct::in_tm, identifier_struct::level, identifier_struct::lower_goal, identifier_struct::ms_retractions, ms_change_struct::next_in_level, NIL, agent_struct::nil_goal_retractions, preference_struct::on_goal_list, identifier_struct::operator_slot, POP_CONTEXT_STACK_CALLBACK, post_link_removal(), identifier_struct::preferences_from_goal, ms_change_struct::prev_in_level, rl_data_struct::prev_op_rl_rules, agent_struct::reason_for_stopping, remove_existing_context_and_descendents(), remove_from_dll, remove_preference_from_clones(), remove_preference_from_tm(), remove_wme_list_from_wm(), remove_wmes_for_context_slot(), identifier_struct::reward_header, rl_clear_refs(), rl_enabled(), agent_struct::rl_et_pool, identifier_struct::rl_info, agent_struct::rl_info_pool, rl_perform_update(), agent_struct::rl_rule_pool, rl_tabulate_reward_value_for_goal(), identifier_struct::smem_cmd_header, identifier_struct::smem_header, identifier_struct::smem_info, agent_struct::smem_info_pool, smem_reset(), identifier_struct::smem_result_header, smem_data_struct::smem_wmes, agent_struct::smem_wmes_pool, soar_invoke_callbacks(), agent_struct::stop_soar, agent_struct::substate_break_level, symbol_remove_ref(), agent_struct::top_goal, and update_impasse_items().

Referenced by clear_goal_stack(), decide_context_slot(), gds_invalid_so_remove_goal(), remove_current_decision(), remove_existing_context_and_descendents(), and remove_operator_if_necessary().

{
ms_change *head, *tail; /* REW: 08.20.97 */
/* --- remove descendents of this goal --- */
// BUGBUG this recursion causes a stack overflow if the goal depth is large
if (goal->id.lower_goal)
/* --- invoke callback routine --- */
static_cast<soar_call_data>(goal) );
if ( ( goal != thisAgent->top_goal ) && rl_enabled( thisAgent ) )
{
rl_perform_update( thisAgent, 0, true, goal, false ); // this update only sees reward - there is no next state
rl_clear_refs( goal );
}
/* --- disconnect this goal from the goal stack --- */
if (goal == thisAgent->top_goal) {
thisAgent->top_goal = NIL;
thisAgent->bottom_goal = NIL;
} else {
thisAgent->bottom_goal = goal->id.higher_goal;
thisAgent->bottom_goal->id.lower_goal = NIL;
}
/* --- remove any preferences supported by this goal --- */
#ifdef DO_TOP_LEVEL_REF_CTS
while (goal->id.preferences_from_goal) {
all_of_goal_next, all_of_goal_prev);
if (! remove_preference_from_clones (thisAgent, p))
if (p->in_tm) remove_preference_from_tm (thisAgent, p);
}
#else
/* KJC Aug 05: this seems to cure a potential for exceeding callstack
* when popping soar's goal stack and not doing DO_TOP_LEVEL_REF_CTS
* Probably should make this change for all cases, but needs testing. */
/* Prefs are added to head of dll, so try removing from tail */
while (p) {
preference* p_next = p->all_of_goal_prev; // RPM 10/06 we need to save this because p may be freed by the end of the loop
all_of_goal_next, all_of_goal_prev);
if (! remove_preference_from_clones (thisAgent, p))
if (p->in_tm) remove_preference_from_tm (thisAgent, p);
p = p_next;
}
}
#endif
/* --- remove wmes for this goal, and garbage collect --- */
update_impasse_items (thisAgent, goal, NIL); /* causes items & fake pref's to go away */
epmem_reset( thisAgent, goal );
smem_reset( thisAgent, goal );
goal->id.impasse_wmes = NIL;
/* REW: begin 09.15.96 */
/* If there was a GDS for this goal, we want to set the pointer for the
goal to NIL to indicate it no longer exists.
BUG: We probably also need to make certain that the GDS doesn't need
to be free'd here as well. */
if (goal->id.gds != NIL) goal->id.gds->goal = NIL;
/* REW: end 09.15.96 */
/* REW: begin 08.20.97 */
/* If we remove a goal WME, then we have to transfer any already existing
retractions to the nil-goal list on the current agent. We should be
able to do this more efficiently but the most obvious way (below) still
requires scanning over the whole list (to set the goal pointer of each
msc to NIL); therefore this solution should be acceptably efficient. */
if (goal->id.ms_retractions) { /* There's something on the retraction list */
head = goal->id.ms_retractions;
tail = head;
/* find the tail of this list */
while (tail->next_in_level) {
tail->goal = NIL; /* force the goal to be NIL */
tail = tail->next_in_level;
}
tail->goal = NIL;
if (thisAgent->nil_goal_retractions) {
/* There are already retractions on the list */
/* Append this list to front of NIL goal list */
thisAgent->nil_goal_retractions->prev_in_level = tail;
tail->next_in_level = thisAgent->nil_goal_retractions;
thisAgent->nil_goal_retractions = head;
} else { /* If no retractions, make this list the NIL goal list */
thisAgent->nil_goal_retractions = head;
}
}
goal->id.rl_info->eligibility_traces->~rl_et_map();
free_with_pool( &( thisAgent->rl_et_pool ),goal->id.rl_info->eligibility_traces );
goal->id.rl_info->prev_op_rl_rules->~rl_rule_list();
free_with_pool( &( thisAgent->rl_rule_pool ),goal->id.rl_info->prev_op_rl_rules );
symbol_remove_ref( thisAgent, goal->id.reward_header );
free_with_pool( &( thisAgent->rl_info_pool ), goal->id.rl_info );
goal->id.epmem_info->epmem_wmes->~epmem_wme_stack();
free_with_pool( &( thisAgent->epmem_wmes_pool ), goal->id.epmem_info->epmem_wmes );
symbol_remove_ref( thisAgent, goal->id.epmem_cmd_header );
symbol_remove_ref( thisAgent, goal->id.epmem_header );
free_with_pool( &( thisAgent->epmem_info_pool ), goal->id.epmem_info );
goal->id.smem_info->smem_wmes->~smem_wme_stack();
free_with_pool( &( thisAgent->smem_wmes_pool ), goal->id.smem_info->smem_wmes );
symbol_remove_ref( thisAgent, goal->id.smem_cmd_header );
symbol_remove_ref( thisAgent, goal->id.smem_result_header );
symbol_remove_ref( thisAgent, goal->id.smem_header );
free_with_pool( &( thisAgent->smem_info_pool ), goal->id.smem_info );
/* REW: BUG
* Tentative assertions can exist for removed goals. However, it looks
* like the removal forces a tentative retraction, which then leads to
* the deletion of the tentative assertion. However, I have not tested
* such cases exhaustively -- I would guess that some processing may be
* necessary for the assertions here at some point?
*/
/* REW: end 08.20.97 */
/* We have to remove this state from the list of states to learn in (NLD: and free cons)
* jzxu April 24, 2009 */
free_list( thisAgent, extract_list_elements(thisAgent, &thisAgent->chunky_problem_spaces, cons_equality_fn, reinterpret_cast<void*>(goal)) );
free_list( thisAgent, extract_list_elements(thisAgent, &thisAgent->chunk_free_problem_spaces, cons_equality_fn, reinterpret_cast<void*>(goal)) );
post_link_removal (thisAgent, NIL, goal); /* remove the special link */
symbol_remove_ref (thisAgent, goal);
if (goal->id.level <= thisAgent->substate_break_level) {
thisAgent->stop_soar++;
thisAgent->substate_break_level = 0;
thisAgent->reason_for_stopping = "Stopped due to substate (goal) retraction.";
}
}
void remove_operator_if_necessary ( agent thisAgent,
slot s,
wme w 
)

Definition at line 41 of file consistency.cpp.

References agent_struct::current_phase, symbol_union::id, slot_struct::id, identifier_struct::lower_goal, print(), print_with_symbols(), print_wme(), remove_existing_context_and_descendents(), remove_wmes_for_context_slot(), agent_struct::soar_verbose_flag, agent_struct::sysparams, TRACE_OPERAND2_REMOVALS_SYSPARAM, TRACE_WM_CHANGES_SYSPARAM, wme_struct::value, and slot_struct::wmes.

Referenced by do_acceptable_preference_wme_changes_for_slot().

{
/* REW: begin 11.25.96 */
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
thisAgent->timers_gds.start();
#endif
#endif
/* REW: end 11.25.96 */
/* printf("Examining slot (next)\n");
for (next = s; next; next=next->next){
print_with_symbols("Slot ID: [%y]\n", next->id);
print_with_symbols("Slot Attr: [%y]\n", next->attr);
}
printf("Examining slot (prev)\n");
for (prev = s->prev; prev; prev=prev->prev){
print_with_symbols("Slot ID: [%y]\n", prev->id);
print_with_symbols("Slot Attr: [%y]\n", prev->attr);
}
printf("Examining slot WMEs\n");
for (slot_wmes=s->wmes; slot_wmes; slot_wmes=slot_wmes->next){
print_wme(thisAgent, slot_wmes);
}
printf("Examining acceptable preference WMEs\n");
for (slot_wmes=s->acceptable_preference_wmes; slot_wmes; slot_wmes=slot_wmes->next){
print_wme(thisAgent, slot_wmes);
}
if (thisAgent->highest_goal_whose_context_changed) print_with_symbols("Highest goal with changed context: [%y]\n", thisAgent->highest_goal_whose_context_changed);
print_with_symbols("Slot ID: [%y]\n", s->id);
print_with_symbols("Slot Attr: [%y]\n", s->attr);
if (s->isa_context_slot) printf("this is a context slot.\n");
if (s->impasse_id) print_with_symbols("Impasse: [%y]\n", s->impasse_id);
if (s->acceptable_preference_changed) printf("Acceptable pref changed\n");
print_with_symbols("WME ID: [%y]\n", w->id);
print_with_symbols("WME Attr: [%y]\n", w->attr);
print_with_symbols("WME Value: [%y]\n", w->value);
if (w->value->id.isa_operator) printf("This is an operator\n");
print_with_symbols("s->id->id.operator_slot->id: [%y]\n", s->id->id.operator_slot->id); */
if (s->wmes) { /* If there is something in the context slot */
if (s->wmes->value == w->value) { /* The WME in the context slot is WME whose pref changed */
print(thisAgent, "\n REMOVING: Operator from context slot (proposal no longer matches): ");
print_wme(thisAgent, w);
}
if (s->id->id.lower_goal)
{
if ( thisAgent->soar_verbose_flag || thisAgent->sysparams[TRACE_WM_CHANGES_SYSPARAM] )
print_with_symbols(thisAgent, "Removing state %y because of an operator removal.\n", s->id->id.lower_goal);
}
}
}
/* REW: begin 11.25.96 */
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
thisAgent->timers_gds.stop();
thisAgent->timers_gds_cpu_time[thisAgent->current_phase].update(thisAgent->timers_gds);
#endif
#endif
/* REW: end 11.25.96 */
}
void remove_wmes_for_context_slot ( agent thisAgent,
slot s 
)

Definition at line 2114 of file decide.cpp.

References NIL, wme_struct::preference, preference_remove_ref(), remove_wme_from_wm(), and slot_struct::wmes.

Referenced by decide_context_slot(), remove_current_decision(), remove_existing_context_and_descendents(), and remove_operator_if_necessary().

{
wme *w;
if (!s->wmes) return;
/* Note that we only need to handle one wme--context slots never have
more than one wme in them */
w = s->wmes;
remove_wme_from_wm (thisAgent, w);
s->wmes = NIL;
}
byte run_preference_semantics_for_consistency_check ( agent thisAgent,
slot s,
preference **  result_candidates 
)

Definition at line 1404 of file decide.cpp.

References run_preference_semantics().

Referenced by decision_consistent_with_current_preferences().

{
return run_preference_semantics( thisAgent, s, result_candidates, true );
}
byte type_of_existing_impasse ( agent thisAgent,
Symbol goal 
)

Definition at line 2405 of file decide.cpp.

References abort_with_fatal_error(), wme_struct::attr, BUFFER_MSG_SIZE, CONFLICT_IMPASSE_TYPE, agent_struct::conflict_symbol, CONSTRAINT_FAILURE_IMPASSE_TYPE, agent_struct::constraint_failure_symbol, symbol_union::id, agent_struct::impasse_symbol, identifier_struct::impasse_wmes, identifier_struct::lower_goal, wme_struct::next, NIL, NO_CHANGE_IMPASSE_TYPE, agent_struct::no_change_symbol, NONE_IMPASSE_TYPE, agent_struct::none_symbol, TIE_IMPASSE_TYPE, agent_struct::tie_symbol, and wme_struct::value.

Referenced by decide_context_slot(), decision_consistent_with_current_preferences(), and generate_chunk_name_sym_constant().

{
wme *w;
char msg[BUFFER_MSG_SIZE];
if (! goal->id.lower_goal) return NONE_IMPASSE_TYPE;
for (w=goal->id.lower_goal->id.impasse_wmes; w!=NIL; w=w->next)
if (w->attr==thisAgent->impasse_symbol) {
if (w->value==thisAgent->no_change_symbol)
if (w->value==thisAgent->tie_symbol)
if (w->value==thisAgent->constraint_failure_symbol)
if (w->value==thisAgent->conflict_symbol)
if (w->value==thisAgent->none_symbol)
strncpy (msg,"decide.c: Internal error: bad type of existing impasse.\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
strncpy (msg,"decide.c: Internal error: couldn't find type of existing impasse.\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
return 0; /* unreachable, but without it, gcc -Wall warns here */
}
void uniquely_add_to_head_of_dll ( agent thisAgent,
instantiation inst 
)

Definition at line 2862 of file decide.cpp.

References pi_struct::inst, production_struct::name, pi_struct::next, NIL, agent_struct::parent_list_head, pi_struct::prev, print_with_symbols(), and instantiation_struct::prod.

Referenced by decide_non_context_slot(), and elaborate_gds().

{
parent_inst *new_pi, *curr_pi;
/* print(thisAgent, "UNIQUE DLL: scanning parent list...\n"); */
for (curr_pi = thisAgent->parent_list_head;
curr_pi;
curr_pi = curr_pi->next) {
if (curr_pi->inst == inst) {
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "UNIQUE DLL: %y is already in parent list\n",curr_pi->inst->prod->name);
#endif
return;
}
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "UNIQUE DLL: %y\n",curr_pi->inst->prod->name);
#endif
} /* end for loop */
new_pi = static_cast<parent_inst *>(malloc(sizeof(parent_inst)));
new_pi->next = NIL;
new_pi->prev = NIL;
new_pi->inst = inst;
new_pi->next = thisAgent->parent_list_head;
if (thisAgent->parent_list_head != NIL)
thisAgent->parent_list_head->prev = new_pi;
thisAgent->parent_list_head = new_pi;
#ifdef DEBUG_GDS
print_with_symbols(thisAgent, "UNIQUE DLL: added: %y\n",inst->prod->name);
#endif
}