Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Macros | Typedefs | Functions
decide.cpp File Reference
#include <portability.h>
#include "soar_rand.h"
#include "decide.h"
#include "gdatastructs.h"
#include "instantiations.h"
#include "mem.h"
#include "kernel.h"
#include "agent.h"
#include "symtab.h"
#include "wmem.h"
#include "init_soar.h"
#include "prefmem.h"
#include "production.h"
#include "print.h"
#include "trace.h"
#include "explain.h"
#include "tempmem.h"
#include "io_soar.h"
#include "xml.h"
#include "soar_TraceNames.h"
#include "soar_module.h"
#include "exploration.h"
#include "reinforcement_learning.h"
#include "decision_manipulation.h"
#include "wma.h"
#include "misc.h"
#include "episodic_memory.h"
#include "semantic_memory.h"
#include "assert.h"
#include <list>

Go to the source code of this file.

Macros

#define ALREADY_EXISTING_WME_DECIDER_FLAG   7
#define BEST_DECIDER_FLAG   4
#define CANDIDATE_DECIDER_FLAG   1
#define CONFLICTED_DECIDER_FLAG   2
#define FORMER_CANDIDATE_DECIDER_FLAG   3
#define NEW_PREFERENCES_SCHEME   1
#define NOTHING_DECIDER_FLAG   0 /* Warning: code relies in this being 0 */
#define promote_if_needed(thisAgent, sym)
#define UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG   9
#define UNARY_INDIFFERENT_DECIDER_FLAG   6
#define UNARY_PARALLEL_DECIDER_FLAG   8
#define WORST_DECIDER_FLAG   5

Typedefs

typedef std::list< Symbol
*, soar_module::soar_memory_pool_allocator
< Symbol * > > 
symbol_list

Functions

void add_impasse_wme (agent *thisAgent, Symbol *id, Symbol *attr, Symbol *value, preference *p)
void add_wme_to_gds (agent *agentPtr, goal_dependency_set *gds, wme *wme_to_add)
Symbolattribute_of_existing_impasse (agent *thisAgent, Symbol *goal)
void clear_goal_stack (agent *thisAgent)
Bool context_slot_is_decidable (slot *s)
void create_gds_for_goal (agent *thisAgent, Symbol *goal)
void create_new_attribute_impasse_for_slot (agent *thisAgent, slot *s, byte impasse_type)
void create_new_context (agent *thisAgent, Symbol *attr_of_impasse, byte impasse_type)
Symbolcreate_new_impasse (agent *thisAgent, Bool isa_goal, Symbol *object, Symbol *attr, byte impasse_type, goal_stack_level level)
void create_top_goal (agent *thisAgent)
Bool decide_context_slot (agent *thisAgent, Symbol *goal, slot *s, bool predict=false)
void decide_context_slots (agent *thisAgent, bool predict=false)
void decide_non_context_slot (agent *thisAgent, slot *s)
void decide_non_context_slots (agent *thisAgent)
void do_acceptable_preference_wme_changes_for_slot (agent *thisAgent, slot *s)
void do_buffered_acceptable_preference_wme_changes (agent *thisAgent)
void do_buffered_link_changes (agent *thisAgent)
void do_buffered_wm_and_ownership_changes (agent *thisAgent)
void do_decision_phase (agent *thisAgent, bool predict)
void do_demotion (agent *thisAgent)
void do_promotion (agent *thisAgent)
void do_working_memory_phase (agent *thisAgent)
void elaborate_gds (agent *thisAgent)
void free_parent_list (agent *thisAgent)
void garbage_collect_id (agent *thisAgent, Symbol *id)
void gds_invalid_so_remove_goal (agent *thisAgent, wme *w)
void init_decider (agent *thisAgent)
bool level_update_needed (agent *thisAgent, Symbol *sym)
preferencemake_fake_preference_for_goal_item (agent *thisAgent, Symbol *goal, preference *cand)
void mark_context_slot_as_acceptable_preference_changed (agent *thisAgent, slot *s)
void mark_id_and_tc_as_unknown_level (agent *thisAgent, Symbol *root)
bool mark_level_unknown_needed (agent *, Symbol *sym)
void post_link_addition (agent *thisAgent, Symbol *from, Symbol *to)
void post_link_removal (agent *thisAgent, Symbol *from, Symbol *to)
void print_candidates (agent *thisAgent, preference *candidates)
void print_lowest_slot_in_context_stack (agent *thisAgent)
void promote_id_and_tc (agent *thisAgent, Symbol *id, goal_stack_level new_level)
void remove_existing_attribute_impasse_for_slot (agent *thisAgent, slot *s)
void remove_existing_context_and_descendents (agent *thisAgent, Symbol *goal)
void remove_fake_preference_for_goal_item (agent *thisAgent, preference *pref)
void remove_wmes_for_context_slot (agent *thisAgent, slot *s)
byte require_preference_semantics (agent *thisAgent, slot *s, preference **result_candidates, bool consistency)
byte run_preference_semantics (agent *thisAgent, slot *s, preference **result_candidates, bool consistency=false, bool predict=false)
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)
void update_impasse_items (agent *thisAgent, Symbol *id, preference *items)
void walk_and_update_levels (agent *thisAgent, Symbol *root)

Macro Definition Documentation

#define ALREADY_EXISTING_WME_DECIDER_FLAG   7
#define BEST_DECIDER_FLAG   4

Definition at line 139 of file decide.cpp.

Referenced by run_preference_semantics().

#define CANDIDATE_DECIDER_FLAG   1
#define CONFLICTED_DECIDER_FLAG   2

Definition at line 137 of file decide.cpp.

Referenced by run_preference_semantics().

#define FORMER_CANDIDATE_DECIDER_FLAG   3

Definition at line 138 of file decide.cpp.

Referenced by run_preference_semantics().

#define NEW_PREFERENCES_SCHEME   1
#define NOTHING_DECIDER_FLAG   0 /* Warning: code relies in this being 0 */
#define promote_if_needed (   thisAgent,
  sym 
)
Value:
{ if ((sym)->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) \
promote_id_and_tc(thisAgent, sym,new_level); }

Definition at line 343 of file decide.cpp.

Referenced by promote_id_and_tc().

#define UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG   9

Definition at line 147 of file decide.cpp.

Referenced by run_preference_semantics().

#define UNARY_INDIFFERENT_DECIDER_FLAG   6

Definition at line 141 of file decide.cpp.

Referenced by run_preference_semantics().

#define UNARY_PARALLEL_DECIDER_FLAG   8

Definition at line 143 of file decide.cpp.

Referenced by run_preference_semantics().

#define WORST_DECIDER_FLAG   5

Definition at line 140 of file decide.cpp.

Referenced by run_preference_semantics().

Typedef Documentation

Definition at line 72 of file decide.cpp.

Function Documentation

void add_impasse_wme ( agent thisAgent,
Symbol id,
Symbol attr,
Symbol value,
preference p 
)

Definition at line 1424 of file decide.cpp.

References add_wme_to_wm(), FALSE, symbol_union::id, identifier_struct::impasse_wmes, insert_at_head_of_dll, make_wme(), and wme_struct::preference.

Referenced by create_new_context(), create_new_impasse(), and update_impasse_items().

{
wme *w;
w = make_wme (thisAgent, id, attr, value, FALSE);
insert_at_head_of_dll (id->id.impasse_wmes, w, next, prev);
w->preference = p;
add_wme_to_wm (thisAgent, w);
}
void add_wme_to_gds ( agent agentPtr,
goal_dependency_set gds,
wme wme_to_add 
)

Definition at line 2902 of file decide.cpp.

References wme_struct::gds, gds_struct::goal, insert_at_head_of_dll, print_string(), print_wme(), snprintf_with_symbols(), agent_struct::soar_verbose_flag, agent_struct::sysparams, TRACE_GDS_SYSPARAM, gds_struct::wmes_in_gds, xml_att_val(), xml_begin_tag(), and xml_end_tag().

Referenced by elaborate_gds().

{
/* Set the correct GDS for this wme (wme's point to their gds) */
wme_to_add->gds = gds;
insert_at_head_of_dll(gds->wmes_in_gds, wme_to_add, gds_next, gds_prev);
if (agentPtr->soar_verbose_flag || agentPtr->sysparams[TRACE_GDS_SYSPARAM])
{
// BADBAD: the XML code makes this all very ugly
char msgbuf[256];
memset(msgbuf, 0, 256);
snprintf_with_symbols(agentPtr, msgbuf, 255, "Adding to GDS for %y: ", wme_to_add->gds->goal);
print_string(agentPtr, msgbuf);
xml_begin_tag(agentPtr, kTagVerbose);
xml_att_val(agentPtr, kTypeString, msgbuf);
print_wme(agentPtr, wme_to_add); // prints XML, too
xml_end_tag(agentPtr, kTagVerbose);
}
}
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 */
}
Bool context_slot_is_decidable ( slot s)
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_new_attribute_impasse_for_slot ( agent thisAgent,
slot s,
byte  impasse_type 
)
void create_new_context ( agent thisAgent,
Symbol attr_of_impasse,
byte  impasse_type 
)

Definition at line 2300 of file decide.cpp.

References add_impasse_wme(), agent_struct::bottom_goal, CREATE_NEW_CONTEXT_CALLBACK, create_new_impasse(), rl_data_struct::eligibility_traces, identifier_struct::epmem_info, agent_struct::epmem_info_pool, EPMEM_MEMID_NONE, epmem_data_struct::epmem_wmes, agent_struct::epmem_wmes_pool, identifier_struct::higher_goal, symbol_union::id, identifier_struct::level, identifier_struct::lower_goal, make_slot(), MAX_GOAL_DEPTH, NIL, agent_struct::nil_symbol, NO_CHANGE_IMPASSE_TYPE, NONE_IMPASSE_TYPE, agent_struct::operator_symbol, rl_data_struct::prev_op_rl_rules, print(), agent_struct::quiescence_symbol, agent_struct::reason_for_stopping, agent_struct::rl_et_pool, identifier_struct::rl_info, agent_struct::rl_info_pool, agent_struct::rl_rule_pool, identifier_struct::smem_info, agent_struct::smem_info_pool, smem_data_struct::smem_wmes, agent_struct::smem_wmes_pool, soar_invoke_callbacks(), agent_struct::stop_soar, agent_struct::sysparams, agent_struct::system_halted, agent_struct::t_symbol, agent_struct::top_goal, TOP_GOAL_LEVEL, agent_struct::top_state, TRUE, and xml_generate_warning().

Referenced by create_top_goal(), and decide_context_slot().

{
Symbol *id;
if (thisAgent->bottom_goal)
{
/* Creating a sub-goal (or substate) */
id = create_new_impasse (thisAgent, TRUE, thisAgent->bottom_goal,
attr_of_impasse, impasse_type,
static_cast<goal_stack_level>(thisAgent->bottom_goal->id.level + 1));
id->id.higher_goal = thisAgent->bottom_goal;
thisAgent->bottom_goal->id.lower_goal = id;
thisAgent->bottom_goal = id;
add_impasse_wme (thisAgent, id, thisAgent->quiescence_symbol,
thisAgent->t_symbol, NIL);
if ((NO_CHANGE_IMPASSE_TYPE == impasse_type) &&
(thisAgent->sysparams[MAX_GOAL_DEPTH] < thisAgent->bottom_goal->id.level ))
{
// appear to be SNC'ing deep in goalstack, so interrupt and warn user
// KJC note: we actually halt, because there is no interrupt function in SoarKernel
// in the gSKI Agent code, if system_halted, MAX_GOAL_DEPTH is checked and if exceeded
// then the interrupt is generated and system_halted is set to FALSE so the user can recover.
print(thisAgent, "\nGoal stack depth exceeded %d on a no-change impasse.\n",thisAgent->sysparams[MAX_GOAL_DEPTH]);
print(thisAgent, "Soar appears to be in an infinite loop. \nContinuing to subgoal may cause Soar to \nexceed the program stack of your system.\n");
xml_generate_warning(thisAgent, "\nGoal stack depth exceeded on a no-change impasse.\n");
xml_generate_warning(thisAgent, "Soar appears to be in an infinite loop. \nContinuing to subgoal may cause Soar to \nexceed the program stack of your system.\n");
thisAgent->stop_soar = TRUE;
thisAgent->system_halted = TRUE;
thisAgent->reason_for_stopping = "Max Goal Depth exceeded.";
}
}
else
{
/* Creating the top state */
id = create_new_impasse (thisAgent, TRUE, thisAgent->nil_symbol,
thisAgent->top_goal = id;
thisAgent->bottom_goal = id;
thisAgent->top_state = thisAgent->top_goal;
id->id.lower_goal = NIL;
}
id->id.isa_goal = TRUE;
id->id.operator_slot = make_slot (thisAgent, id, thisAgent->operator_symbol);
id->id.allow_bottom_up_chunks = TRUE;
allocate_with_pool( thisAgent, &( thisAgent->rl_info_pool ), &( id->id.rl_info ) );
id->id.rl_info->previous_q = 0;
id->id.rl_info->reward = 0;
id->id.rl_info->gap_age = 0;
id->id.rl_info->hrl_age = 0;
allocate_with_pool( thisAgent, &( thisAgent->rl_et_pool ), &( id->id.rl_info->eligibility_traces ) );
#ifdef USE_MEM_POOL_ALLOCATORS
id->id.rl_info->eligibility_traces = new ( id->id.rl_info->eligibility_traces ) rl_et_map( std::less< production* >(), soar_module::soar_memory_pool_allocator< std::pair< production*, double > >( thisAgent ) );
#else
id->id.rl_info->eligibility_traces = new ( id->id.rl_info->eligibility_traces ) rl_et_map();
#endif
allocate_with_pool( thisAgent, &( thisAgent->rl_rule_pool ), &( id->id.rl_info->prev_op_rl_rules ) );
#ifdef USE_MEM_POOL_ALLOCATORS
id->id.rl_info->prev_op_rl_rules = new ( id->id.rl_info->prev_op_rl_rules ) rl_rule_list( soar_module::soar_memory_pool_allocator< production* >( thisAgent ) );
#else
id->id.rl_info->prev_op_rl_rules = new ( id->id.rl_info->prev_op_rl_rules ) rl_rule_list();
#endif
allocate_with_pool( thisAgent, &( thisAgent->epmem_info_pool ), &( id->id.epmem_info ) );
id->id.epmem_info->last_ol_time = 0;
id->id.epmem_info->last_cmd_time = 0;
id->id.epmem_info->last_cmd_count = 0;
id->id.epmem_info->last_memory = EPMEM_MEMID_NONE;
allocate_with_pool( thisAgent, &( thisAgent->epmem_wmes_pool ), &( id->id.epmem_info->epmem_wmes ) );
#ifdef USE_MEM_POOL_ALLOCATORS
id->id.epmem_info->epmem_wmes = new ( id->id.epmem_info->epmem_wmes ) epmem_wme_stack( soar_module::soar_memory_pool_allocator< preference* >( thisAgent ) );
#else
id->id.epmem_info->epmem_wmes = new ( id->id.epmem_info->epmem_wmes ) epmem_wme_stack();
#endif
allocate_with_pool( thisAgent, &( thisAgent->smem_info_pool ), &( id->id.smem_info ) );
id->id.smem_info->last_cmd_time[0] = 0;
id->id.smem_info->last_cmd_time[1] = 0;
id->id.smem_info->last_cmd_count[0] = 0;
id->id.smem_info->last_cmd_count[1] = 0;
allocate_with_pool( thisAgent, &( thisAgent->smem_wmes_pool ), &( id->id.smem_info->smem_wmes ) );
#ifdef USE_MEM_POOL_ALLOCATORS
id->id.smem_info->smem_wmes = new ( id->id.smem_info->smem_wmes ) smem_wme_stack( soar_module::soar_memory_pool_allocator< preference* >( thisAgent ) );
#else
id->id.smem_info->smem_wmes = new ( id->id.smem_info->smem_wmes ) smem_wme_stack();
#endif
/* --- invoke callback routine --- */
static_cast<soar_call_data>(id) );
}
Symbol* create_new_impasse ( agent thisAgent,
Bool  isa_goal,
Symbol object,
Symbol attr,
byte  impasse_type,
goal_stack_level  level 
)

Definition at line 1441 of file decide.cpp.

References add_impasse_wme(), soar_module::add_module_wme(), agent_struct::attribute_symbol, agent_struct::choices_symbol, CONFLICT_IMPASSE_TYPE, agent_struct::conflict_symbol, CONSTRAINT_FAILURE_IMPASSE_TYPE, agent_struct::constraint_failure_symbol, identifier_struct::epmem_cmd_header, identifier_struct::epmem_header, identifier_struct::epmem_result_header, agent_struct::epmem_stats, agent_struct::epmem_sym, agent_struct::epmem_sym_cmd, agent_struct::epmem_sym_present_id, agent_struct::epmem_sym_result, soar_module::primitive_stat< T >::get_value(), symbol_union::id, agent_struct::impasse_symbol, make_int_constant(), make_new_identifier(), agent_struct::multiple_symbol, NIL, NO_CHANGE_IMPASSE_TYPE, agent_struct::no_change_symbol, NONE_IMPASSE_TYPE, agent_struct::none_symbol, agent_struct::object_symbol, post_link_addition(), identifier_struct::reward_header, agent_struct::rl_sym_reward_link, identifier_struct::smem_cmd_header, identifier_struct::smem_header, identifier_struct::smem_result_header, agent_struct::smem_sym, agent_struct::smem_sym_cmd, agent_struct::smem_sym_result, agent_struct::state_symbol, agent_struct::superstate_symbol, symbol_remove_ref(), TIE_IMPASSE_TYPE, agent_struct::tie_symbol, epmem_stat_container::time, and agent_struct::type_symbol.

Referenced by create_new_attribute_impasse_for_slot(), and create_new_context().

{
Symbol *id;
id = make_new_identifier (thisAgent, (isa_goal ? 'S' : 'I'), level);
post_link_addition (thisAgent, NIL, id); /* add the special link */
add_impasse_wme (thisAgent, id, thisAgent->type_symbol, isa_goal ? thisAgent->state_symbol : thisAgent->impasse_symbol,
NIL);
if (isa_goal)
{
add_impasse_wme (thisAgent, id, thisAgent->superstate_symbol, object, NIL);
id->id.reward_header = make_new_identifier( thisAgent, 'R', level );
id->id.epmem_header = make_new_identifier( thisAgent, 'E', level );
soar_module::add_module_wme( thisAgent, id, thisAgent->epmem_sym, id->id.epmem_header );
id->id.epmem_cmd_header = make_new_identifier( thisAgent, 'C', level );
id->id.epmem_result_header = make_new_identifier( thisAgent, 'R', level );
{
int64_t my_time = static_cast<int64_t>( thisAgent->epmem_stats->time->get_value() );
if ( my_time == 0 )
{
// special case: pre-initialization
my_time = 1;
}
Symbol* my_time_sym = make_int_constant( thisAgent, my_time );
id->id.epmem_time_wme = soar_module::add_module_wme( thisAgent, id->id.epmem_header, thisAgent->epmem_sym_present_id, my_time_sym );
symbol_remove_ref( thisAgent, my_time_sym );
}
id->id.smem_header = make_new_identifier( thisAgent, 'S', level );
soar_module::add_module_wme( thisAgent, id, thisAgent->smem_sym, id->id.smem_header );
id->id.smem_cmd_header = make_new_identifier( thisAgent, 'C', level );
id->id.smem_result_header = make_new_identifier( thisAgent, 'R', level );
}
else
add_impasse_wme (thisAgent, id, thisAgent->object_symbol, object, NIL);
if (attr) add_impasse_wme (thisAgent, id, thisAgent->attribute_symbol, attr, NIL);
switch (impasse_type) {
break; /* this happens only when creating the top goal */
add_impasse_wme (thisAgent, id, thisAgent->impasse_symbol, thisAgent->constraint_failure_symbol, NIL);
add_impasse_wme (thisAgent, id, thisAgent->choices_symbol, thisAgent->none_symbol, NIL);
break;
add_impasse_wme (thisAgent, id, thisAgent->impasse_symbol, thisAgent->conflict_symbol, NIL);
add_impasse_wme (thisAgent, id, thisAgent->choices_symbol, thisAgent->multiple_symbol, NIL);
break;
add_impasse_wme (thisAgent, id, thisAgent->impasse_symbol, thisAgent->tie_symbol, NIL);
add_impasse_wme (thisAgent, id, thisAgent->choices_symbol, thisAgent->multiple_symbol, NIL);
break;
add_impasse_wme (thisAgent, id, thisAgent->impasse_symbol, thisAgent->no_change_symbol, NIL);
add_impasse_wme (thisAgent, id, thisAgent->choices_symbol, thisAgent->none_symbol, NIL);
break;
}
return id;
}
void create_top_goal ( agent thisAgent)
Bool decide_context_slot ( agent thisAgent,
Symbol goal,
slot s,
bool  predict = false 
)

Definition at line 2455 of file decide.cpp.

References abort_with_fatal_error(), add_wme_to_wm(), slot_struct::attr, attribute_of_existing_impasse(), BUFFER_MSG_SIZE, slot_struct::changed, CONFLICT_IMPASSE_TYPE, CONSTRAINT_FAILURE_IMPASSE_TYPE, context_slot_is_decidable(), create_new_context(), FALSE, symbol_union::id, slot_struct::id, IDENTIFIER_SYMBOL_TYPE, insert_at_head_of_dll, identifier_struct::lower_goal, make_wme(), identifier_struct::name_letter, identifier_struct::name_number, preference_struct::next_candidate, NIL, NO_CHANGE_IMPASSE_TYPE, NONE_IMPASSE_TYPE, identifier_struct::operator_slot, predict_set(), wme_struct::preference, preference_add_ref(), preference_remove_ref(), print_with_symbols(), remove_existing_context_and_descendents(), remove_wmes_for_context_slot(), rl_enabled(), rl_store_data(), run_preference_semantics(), agent_struct::soar_verbose_flag, agent_struct::state_symbol, agent_struct::sysparams, TIE_IMPASSE_TYPE, TRACE_WM_CHANGES_SYSPARAM, TRUE, type_of_existing_impasse(), update_impasse_items(), preference_struct::value, agent_struct::waitsnc, agent_struct::waitsnc_detect, and slot_struct::wmes.

Referenced by decide_context_slots().

{
byte impasse_type;
Symbol *attribute_of_impasse;
wme *w;
preference *candidates;
preference *temp;
{
/* --- the only time we decide a slot that's not "decidable" is when it's
the last slot in the entire context stack, in which case we have a
no-change impasse there --- */
impasse_type = NO_CHANGE_IMPASSE_TYPE;
candidates = NIL; /* we don't want any impasse ^item's later */
if ( predict )
{
predict_set( thisAgent, "none" );
return TRUE;
}
}
else
{
/* --- the slot is decidable, so run preference semantics on it --- */
impasse_type = run_preference_semantics (thisAgent, s, &candidates);
if ( predict )
{
switch ( impasse_type )
{
predict_set( thisAgent, "constraint" );
break;
predict_set( thisAgent, "conflict" );
break;
predict_set( thisAgent, "tie" );
break;
predict_set( thisAgent, "none" );
break;
default:
if ( !candidates || ( candidates->value->common.symbol_type != IDENTIFIER_SYMBOL_TYPE ) )
predict_set( thisAgent, "none" );
else
{
std::string temp = "";
// get first letter of id
temp += candidates->value->id.name_letter;
// get number
std::string temp2;
to_string( candidates->value->id.name_number, temp2 );
temp += temp2;
predict_set( thisAgent, temp.c_str() );
}
break;
}
return TRUE;
}
remove_wmes_for_context_slot (thisAgent, s); /* must remove old wme before adding
the new one (if any) */
if (impasse_type == NONE_IMPASSE_TYPE)
{
if (!candidates)
{
/* --- no winner ==> no-change impasse on the previous slot --- */
impasse_type = NO_CHANGE_IMPASSE_TYPE;
}
else if (candidates->next_candidate)
{
/* --- more than one winner ==> internal error --- */
char msg[BUFFER_MSG_SIZE];
strncpy (msg,"decide.c: Internal error: more than one winner for context slot\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
}
} /* end if !context_slot_is_decidable */
/* --- mark the slot as not changed --- */
s->changed = NIL;
/* --- determine the attribute of the impasse (if there is no impasse,
* this doesn't matter) --- */
if (impasse_type == NO_CHANGE_IMPASSE_TYPE)
{
if (s->wmes)
{
attribute_of_impasse = s->attr;
}
else
{
attribute_of_impasse = thisAgent->state_symbol;
}
}
else
{
/* --- for all other kinds of impasses --- */
attribute_of_impasse = s->attr;
}
/* --- remove wme's for lower slots of this context --- */
if (attribute_of_impasse == thisAgent->state_symbol)
{
}
/* --- if we have a winner, remove any existing impasse and install the
new value for the current slot --- */
if (impasse_type == NONE_IMPASSE_TYPE)
{
for(temp = candidates; temp; temp = temp->next_candidate)
if (goal->id.lower_goal)
{
if ( thisAgent->soar_verbose_flag || thisAgent->sysparams[TRACE_WM_CHANGES_SYSPARAM] )
print_with_symbols(thisAgent, "Removing state %y because of a decision.\n", goal->id.lower_goal);
}
w = make_wme (thisAgent, s->id, s->attr, candidates->value, FALSE);
insert_at_head_of_dll (s->wmes, w, next, prev);
w->preference = candidates;
/* JC Adding an operator to working memory in the current state */
add_wme_to_wm (thisAgent, w);
for(temp = candidates; temp; temp = temp->next_candidate)
preference_remove_ref(thisAgent, temp);
if ( rl_enabled( thisAgent ) )
rl_store_data( thisAgent, goal, candidates );
return TRUE;
}
/* --- no winner; if an impasse of the right type already existed, just
update the ^item set on it --- */
if ((impasse_type == type_of_existing_impasse(thisAgent, goal)) &&
(attribute_of_impasse == attribute_of_existing_impasse(thisAgent, goal)))
{
update_impasse_items (thisAgent, goal->id.lower_goal, candidates);
return FALSE;
}
/* --- no impasse already existed, or an impasse of the wrong type
already existed --- */
for(temp = candidates; temp; temp = temp->next_candidate)
if (goal->id.lower_goal)
{
if ( thisAgent->soar_verbose_flag || thisAgent->sysparams[TRACE_WM_CHANGES_SYSPARAM] )
print_with_symbols(thisAgent, "Removing state %y because it's the wrong type of impasse.\n", goal->id.lower_goal);
}
/* REW: begin 10.24.97 */
if (thisAgent->waitsnc && (impasse_type == NO_CHANGE_IMPASSE_TYPE) && (attribute_of_impasse == thisAgent->state_symbol))
{
thisAgent->waitsnc_detect = TRUE;
}
else
{
/* REW: end 10.24.97 */
create_new_context (thisAgent, attribute_of_impasse, impasse_type);
update_impasse_items (thisAgent, goal->id.lower_goal, candidates);
}
for(temp = candidates; temp; temp = temp->next_candidate)
preference_remove_ref(thisAgent, temp);
return TRUE;
}
void decide_context_slots ( agent thisAgent,
bool  predict = false 
)

Definition at line 2653 of file decide.cpp.

References agent_struct::bottom_goal, context_slot_is_decidable(), decide_context_slot(), agent_struct::highest_goal_whose_context_changed, symbol_union::id, identifier_struct::lower_goal, NIL, identifier_struct::operator_slot, TRUE, and slot_struct::wmes.

Referenced by do_decision_phase().

{
Symbol *goal;
slot *s;
{
}
else
/* no context changed, so jump right to the bottom */
goal = thisAgent->bottom_goal;
s = goal->id.operator_slot;
/* --- loop down context stack --- */
while (TRUE)
{
/* --- find next slot to decide --- */
while (TRUE)
{
break;
if ((s == goal->id.operator_slot) || (! s->wmes))
{
/* --- no more slots to look at for this goal; have we reached
the last slot in whole stack? --- */
if (! goal->id.lower_goal)
break;
/* --- no, go down one level --- */
goal = goal->id.lower_goal;
s = goal->id.operator_slot;
}
} /* end of while (TRUE) find next slot to decide */
/* --- now go and decide that slot --- */
if (decide_context_slot (thisAgent, goal, s, predict))
break;
} /* end of while (TRUE) loop down context stack */
if ( !predict )
}
void decide_non_context_slot ( agent thisAgent,
slot s 
)

Definition at line 1782 of file decide.cpp.

References abort_with_fatal_error(), add_wme_to_wm(), ALREADY_EXISTING_WME_DECIDER_FLAG, preference_struct::attr, CANDIDATE_DECIDER_FLAG, create_gds_for_goal(), create_new_attribute_impasse_for_slot(), agent_struct::current_phase, elaborate_gds(), FALSE, free_parent_list(), wme_struct::gds, identifier_struct::gds, instantiation_struct::GDS_evaluated_already, gds_invalid_so_remove_goal(), gds_struct::goal, preference_struct::id, symbol_union::id, slot_struct::impasse_id, slot_struct::impasse_type, insert_at_head_of_dll, preference_struct::inst, identifier_struct::level, make_wme(), instantiation_struct::match_goal, instantiation_struct::match_goal_level, production_struct::name, wme_struct::next, preference_struct::next, preference_struct::next_candidate, NIL, NONE_IMPASSE_TYPE, NOTHING_DECIDER_FLAG, preference_struct::o_supported, agent_struct::parent_list_head, wme_struct::preference, print(), print_preference(), print_with_symbols(), instantiation_struct::prod, remove_existing_attribute_impasse_for_slot(), remove_from_dll, remove_wme_from_wm(), remove_wme_list_from_wm(), run_preference_semantics(), agent_struct::system_halted, TRUE, uniquely_add_to_head_of_dll(), update_impasse_items(), wme_struct::value, preference_struct::value, wma_activate_wme(), wma_enabled(), agent_struct::wma_slot_refs_pool, slot_struct::wma_val_references, and slot_struct::wmes.

Referenced by decide_non_context_slots().

{
byte impasse_type;
wme *w, *next_w;
preference *candidates, *cand, *pref;
impasse_type = run_preference_semantics (thisAgent, s, &candidates);
if (impasse_type==NONE_IMPASSE_TYPE)
{
/* --- no impasse, so remove any existing one and update the wmes --- */
/* --- reset marks on existing wme values to "NOTHING" --- */
for (w=s->wmes; w!=NIL; w=w->next)
w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
/* --- set marks on desired values to "CANDIDATES" --- */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
/* --- for each existing wme, if we want it there, mark it as
ALREADY_EXISTING; otherwise remove it --- */
w = s->wmes;
while (w)
{
next_w = w->next;
if (w->value->common.decider_flag == CANDIDATE_DECIDER_FLAG)
{
w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
w->value->common.a.decider_wme = w; /* so we can set the pref later */
}
else
{
remove_from_dll (s->wmes, w, next, prev);
/* REW: begin 09.15.96 */
if (w->gds)
{
if (w->gds->goal != NIL)
{
/* If the goal pointer is non-NIL, then goal is in the stack */
}
}
/* REW: end 09.15.96 */
remove_wme_from_wm (thisAgent, w);
}
w = next_w;
} /* end while (W) */
/* --- for each desired value, if it's not already there, add it --- */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
{
if (cand->value->common.decider_flag==ALREADY_EXISTING_WME_DECIDER_FLAG)
{
/* REW: begin 11.22.97 */
/* print(thisAgent, "\n This WME was marked as already existing...."); print_wme(cand->value->common.a.decider_wme); */
/* REW: end 11.22.97 */
cand->value->common.a.decider_wme->preference = cand;
}
else
{
w = make_wme (thisAgent, cand->id, cand->attr, cand->value, FALSE);
insert_at_head_of_dll (s->wmes, w, next, prev);
w->preference = cand;
if ( ( s->wma_val_references != NIL ) && wma_enabled( thisAgent ) )
{
wma_sym_reference_map::iterator it = s->wma_val_references->find( w->value );
if ( it != s->wma_val_references->end() )
{
// should only activate at this point if WME is o-supported
wma_activate_wme( thisAgent, w, it->second, NULL, true );
s->wma_val_references->erase( it );
if ( s->wma_val_references->empty() )
{
s->wma_val_references->~wma_sym_reference_map();
free_with_pool( &( thisAgent->wma_slot_refs_pool ), s->wma_val_references );
}
}
}
/* REW: begin 09.15.96 */
/* Whenever we add a WME to WM, we also want to check and see if
this new WME is o-supported. If so, then we want to add the
supergoal dependencies of the new, o-supported element to the
goal in which the element was created (as long as the o_supported
element was not created in the top state -- the top goal has
no gds). */
/* REW: begin 11.25.96 */
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
thisAgent->timers_gds.start();
#endif
#endif
/* REW: end 11.25.96 */
thisAgent->parent_list_head = NIL;
/* If the working memory element being added is going to have
o_supported preferences and the instantion that created it
is not in the top_level_goal (where there is no GDS), then
loop over the preferences for this WME and determine which
WMEs should be added to the goal's GDS (the goal here being the
goal to which the added memory is attached). */
{
{
/* If there is no GDS yet for this goal,
* then we need to create one */
{
/*
* NLD: BUG when the system has already halted and this code is reached, Soar will
* report a memory leak because the elaborate_gds call below will not execute (notice the
* check for system_halted), and hence the gds for this goal will not be populated,
* leading to the gds struct not being freed on quit.
*
* I'm not sure if this situation will come up anymore (after r12593), so not doing
* anything about it. However, if it does, this can lead to a memory leak. I know
* it can add up between calls to init-soar, but I'm not sure if it can increase
* more frequently than that.
*/
/* REW: BUG When chunks and result instantiations both create
* preferences for the same WME, then we only want to create
* the GDS for the highest goal. Right now I ensure that we
* elaborate the correct GDS with the tests in the loop just
* below this code, but the GDS creation above assumes that
* the chunk will be first on the GDS list. This order
* appears to be always true, although I am not 100% certain
* (I think it occurs this way because the chunk is
* necessarily added to the instantiaton list after the
* original instantiation and lists get built such older items
* appear further from the head of the list) . If not true,
* then we need to keep track of any GDS's that get created
* here to remove them later if we find a higher match goal
* for the WME. For now, the program just exits in this
* situation; otherwise, we would build a GDS for the wrong
* level and never elaborate it (resulting in a memory
* leak).
*/
}
else
{
// If this happens, we better be halted, see chunk.cpp:chunk_instantiation
// This can happen if a chunk can't be created, because then the match level
// of the preference instantiation can map back to the original matching
// production which can be at a different level than the id wme.
// Normally, there would be a chunk or justification firing at the higher
// goal with a match level equal to the id level.
// See more comments in chunk_instantiation.
if (!thisAgent->system_halted)
{
abort_with_fatal_error(thisAgent, "**** Wanted to create a GDS for a WME level different from the instantiation level.....Big problems....exiting....****\n\n");
}
}
} /* end if no GDS yet for goal... */
/* Loop over all the preferences for this WME:
* If the instantiation that lead to the preference has not
* been already explored; OR
* If the instantiation is not an subgoal instantiation
* for a chunk instantiation we are already exploring
* Then
* Add the instantiation to a list of instantiations that
* will be explored in elaborate_gds().
*/
// Added halt test because chunk_instantiation can cause problems,
// see comment a few lines above and in chunk_instantiation.
if (!thisAgent->system_halted)
{
for (pref=w->preference; pref!=NIL; pref=pref->next)
{
#ifdef DEBUG_GDS_HIGH
print(thisAgent, thisAgent, "\n\n "); print_preference(pref);
print(thisAgent, " Goal level of preference: %d\n",
pref->id->id.level);
#endif
{
#ifdef DEBUG_GDS_HIGH
print_with_symbols(thisAgent, " Match goal lev of instantiation %y ",
pref->inst->prod->name);
print(thisAgent, "is %d\n", pref->inst->match_goal_level);
#endif
if (pref->inst->match_goal_level > pref->id->id.level)
{
#ifdef DEBUG_GDS_HIGH
print_with_symbols(thisAgent, " %y is simply the instantiation that led to a chunk.\n Not adding it the current instantiations.\n", pref->inst->prod->name);
#endif
}
else
{
#ifdef DEBUG_GDS_HIGH
print_with_symbols(thisAgent, "\n Adding %y to list of parent instantiations\n", pref->inst->prod->name);
#endif
uniquely_add_to_head_of_dll(thisAgent, pref->inst);
}
} /* end if GDS_evaluated_already is FALSE */
#ifdef DEBUG_GDS_HIGH
else
print_with_symbols(thisAgent, "\n Instantiation %y was already explored; skipping it\n", pref->inst->prod->name);
#endif
} /* end of forloop over preferences for this wme */
#ifdef DEBUG_GDS_HIGH
print(thisAgent, "\n CALLING ELABORATE GDS....\n");
#endif
elaborate_gds(thisAgent);
/* technically, the list should be empty at this point ??? */
free_parent_list(thisAgent);
#ifdef DEBUG_GDS_HIGH
print(thisAgent, " FINISHED ELABORATING GDS.\n\n");
#endif
} /* end if not halted */
} /* end if w->preference->o_supported == TRUE ... */
/* 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 */
/* REW: end 09.15.96 */
add_wme_to_wm (thisAgent, w);
}
}
return;
} /* end of if impasse type == NONE */
/* --- impasse type != NONE --- */
if (s->wmes)
{
/* --- remove any existing wmes --- */
remove_wme_list_from_wm (thisAgent, s->wmes);
s->wmes = NIL;
}
/* --- create and/or update impasse structure --- */
{
if (s->impasse_type != impasse_type)
{
create_new_attribute_impasse_for_slot (thisAgent, s, impasse_type);
}
update_impasse_items (thisAgent, s->impasse_id, candidates);
}
else
{
create_new_attribute_impasse_for_slot (thisAgent, s, impasse_type);
update_impasse_items (thisAgent, s->impasse_id, candidates);
}
}
void decide_non_context_slots ( agent thisAgent)

Definition at line 2064 of file decide.cpp.

References slot_struct::changed, agent_struct::changed_slots, decide_non_context_slot(), agent_struct::dl_cons_pool, dl_cons_struct::item, dl_cons_struct::next, and NIL.

Referenced by do_decision_phase(), and do_working_memory_phase().

{
dl_cons *dc;
slot *s;
while (thisAgent->changed_slots)
{
dc = thisAgent->changed_slots;
thisAgent->changed_slots = thisAgent->changed_slots->next;
s = static_cast<slot_struct *>(dc->item);
decide_non_context_slot (thisAgent, s);
s->changed = NIL;
free_with_pool (&thisAgent->dl_cons_pool, dc);
}
}
void do_acceptable_preference_wme_changes_for_slot ( agent thisAgent,
slot s 
)

Definition at line 173 of file decide.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, slot_struct::acceptable_preference_wmes, add_wme_to_wm(), ALREADY_EXISTING_WME_DECIDER_FLAG, preference_struct::attr, CANDIDATE_DECIDER_FLAG, preference_struct::id, insert_at_head_of_dll, make_wme(), wme_struct::next, preference_struct::next, NIL, NOTHING_DECIDER_FLAG, wme_struct::preference, slot_struct::preferences, remove_from_dll, remove_operator_if_necessary(), remove_wme_from_wm(), REQUIRE_PREFERENCE_TYPE, TRUE, wme_struct::value, and preference_struct::value.

Referenced by do_buffered_acceptable_preference_wme_changes().

{
wme *w, *next_w;
/* --- first, reset marks to "NOTHING" --- */
for (w=s->acceptable_preference_wmes; w!=NIL; w=w->next)
w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
/* --- now mark values for which we WANT a wme as "CANDIDATE" values --- */
p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
/* --- remove any existing wme's that aren't CANDIDATEs; mark the
rest as ALREADY_EXISTING --- */
while (w)
{
next_w = w->next;
if (w->value->common.decider_flag==CANDIDATE_DECIDER_FLAG) {
w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
w->value->common.a.decider_wme = w;
w->preference = NIL; /* we'll update this later */
} else {
/* REW: begin 09.15.96 */
/* IF we lose an acceptable preference for an operator, then that
operator comes out of the slot immediately in OPERAND2.
However, if the lost acceptable preference is not for item
in the slot, then we don;t need to do anything special until
mini-quiescence. */
/* REW: end 09.15.96 */
remove_wme_from_wm (thisAgent, w);
}
w = next_w;
}
/* --- add the necessary wme's that don't ALREADY_EXIST --- */
for (p=s->preferences[REQUIRE_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
if (p->value->common.decider_flag==ALREADY_EXISTING_WME_DECIDER_FLAG) {
/* --- found existing wme, so just update its trace --- */
w = p->value->common.a.decider_wme;
if (! w->preference) w->preference = p;
} else {
w = make_wme (thisAgent, p->id, p->attr, p->value, TRUE);
w->preference = p;
add_wme_to_wm (thisAgent, w);
p->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
p->value->common.a.decider_wme = w;
}
}
if (p->value->common.decider_flag==ALREADY_EXISTING_WME_DECIDER_FLAG) {
/* --- found existing wme, so just update its trace --- */
w = p->value->common.a.decider_wme;
if (! w->preference) w->preference = p;
} else {
w = make_wme (thisAgent, p->id, p->attr, p->value, TRUE);
w->preference = p;
add_wme_to_wm (thisAgent, w);
p->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
p->value->common.a.decider_wme = w;
}
}
}
void do_buffered_acceptable_preference_wme_changes ( agent thisAgent)
void do_buffered_link_changes ( agent thisAgent)

Definition at line 834 of file decide.cpp.

References agent_struct::current_phase, agent_struct::disconnected_ids, do_demotion(), do_promotion(), agent_struct::ids_with_unknown_level, agent_struct::promoted_ids, agent_struct::sysparams, and TIMERS_ENABLED.

Referenced by do_buffered_wm_and_ownership_changes().

{
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
soar_process_timer local_timer;
local_timer.set_enabled( &( thisAgent->sysparams[ TIMERS_ENABLED ] ) );
#endif
#endif
/* --- if no promotions or demotions are buffered, do nothing --- */
if (! (thisAgent->promoted_ids ||
thisAgent->ids_with_unknown_level ||
thisAgent->disconnected_ids)) return;
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
local_timer.start();
#endif
#endif
do_promotion (thisAgent);
do_demotion (thisAgent);
#ifndef NO_TIMING_STUFF
#ifdef DETAILED_TIMING_STATS
local_timer.stop();
thisAgent->timers_ownership_cpu_time[thisAgent->current_phase].update(local_timer);
#endif
#endif
}
void do_buffered_wm_and_ownership_changes ( agent thisAgent)
void do_decision_phase ( agent thisAgent,
bool  predict 
)

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_demotion ( agent thisAgent)

Definition at line 755 of file decide.cpp.

References agent_struct::disconnected_ids, agent_struct::dl_cons_pool, garbage_collect_id(), get_new_tc_number(), agent_struct::highest_level_anything_could_fall_from, symbol_union::id, agent_struct::ids_with_unknown_level, insert_at_head_of_dll, dl_cons_struct::item, JUST_UPDATE_COUNT, identifier_struct::level, agent_struct::level_at_which_marking_started, identifier_struct::link_count, agent_struct::link_update_mode, identifier_struct::lower_goal, agent_struct::lowest_level_anything_could_fall_to, LOWEST_POSSIBLE_GOAL_LEVEL, mark_id_and_tc_as_unknown_level(), agent_struct::mark_tc_number, dl_cons_struct::next, NIL, remove_from_dll, symbol_remove_ref(), agent_struct::top_goal, TRUE, UPDATE_DISCONNECTED_IDS_LIST, UPDATE_LINKS_NORMALLY, walk_and_update_levels(), agent_struct::walk_level, and agent_struct::walk_tc_number.

Referenced by do_buffered_link_changes().

{
Symbol *g, *id;
dl_cons *dc, *next_dc;
/* --- scan through ids_with_unknown_level, move the ones with link_count==0
* over to disconnected_ids --- */
for (dc=thisAgent->ids_with_unknown_level; dc!=NIL; dc=next_dc) {
next_dc = dc->next;
id = static_cast<symbol_union *>(dc->item);
if (id->id.link_count==0) {
remove_from_dll (thisAgent->ids_with_unknown_level, dc, next, prev);
insert_at_head_of_dll (thisAgent->disconnected_ids, dc, next, prev);
}
}
/* --- keep garbage collecting ids until nothing left to gc --- */
while (thisAgent->disconnected_ids) {
dc = thisAgent->disconnected_ids;
thisAgent->disconnected_ids = thisAgent->disconnected_ids->next;
id = static_cast<symbol_union *>(dc->item);
free_with_pool (&thisAgent->dl_cons_pool, dc);
id->id.unknown_level = NIL;
garbage_collect_id (thisAgent, id);
symbol_remove_ref (thisAgent, id);
}
/* --- if nothing's left with an unknown level, we're done --- */
if (! thisAgent->ids_with_unknown_level) return;
/* --- do the mark --- */
thisAgent->mark_tc_number = get_new_tc_number(thisAgent);
for (dc=thisAgent->ids_with_unknown_level; dc!=NIL; dc=dc->next) {
id = static_cast<symbol_union *>(dc->item);
thisAgent->level_at_which_marking_started = id->id.level;
}
/* --- do the walk --- */
g = thisAgent->top_goal;
while (TRUE) {
if (!g) break;
if (g->id.level > thisAgent->lowest_level_anything_could_fall_to) break;
thisAgent->walk_level = g->id.level;
thisAgent->walk_tc_number = get_new_tc_number(thisAgent);
walk_and_update_levels (thisAgent, g);
}
g = g->id.lower_goal;
}
/* --- GC anything left with an unknown level after the walk --- */
while (thisAgent->ids_with_unknown_level) {
dc = thisAgent->ids_with_unknown_level;
id = static_cast<symbol_union *>(dc->item);
free_with_pool (&thisAgent->dl_cons_pool, dc);
id->id.unknown_level = NIL; /* AGR 640: GAP set to NIL because */
/* symbol may still have pointers to it */
garbage_collect_id (thisAgent, id);
symbol_remove_ref (thisAgent, id);
}
}
void do_promotion ( agent thisAgent)

Definition at line 389 of file decide.cpp.

References cons_struct::first, free_cons(), symbol_union::id, promote_id_and_tc(), agent_struct::promoted_ids, identifier_struct::promotion_level, cons_struct::rest, and symbol_remove_ref().

Referenced by do_buffered_link_changes().

{
cons *c;
Symbol *to;
while (thisAgent->promoted_ids) {
c = thisAgent->promoted_ids;
to = static_cast<symbol_union *>(c->first);
thisAgent->promoted_ids = thisAgent->promoted_ids->rest;
free_cons (thisAgent, c);
promote_id_and_tc (thisAgent, to, to->id.promotion_level);
symbol_remove_ref (thisAgent, to);
}
}
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 garbage_collect_id ( agent thisAgent,
Symbol id 
)

Definition at line 497 of file decide.cpp.

References preference_struct::all_of_slot_next, slot_struct::all_preferences, symbol_union::id, slot_struct::impasse_type, identifier_struct::input_wmes, mark_slot_for_possible_removal(), slot_struct::next, NIL, NONE_IMPASSE_TYPE, print_with_symbols(), remove_existing_attribute_impasse_for_slot(), remove_preference_from_tm(), remove_wme_list_from_wm(), identifier_struct::slots, and slot_struct::wmes.

Referenced by do_demotion().

{
slot *s;
preference *pref, *next_pref;
#ifdef DEBUG_LINKS
print_with_symbols (thisAgent, "\n*** Garbage collecting id: %y",id);
#endif
/* Note--for goal/impasse id's, this does not remove the impasse wme's.
This is handled by remove_existing_such-and-such... */
/* --- remove any input wmes from the id --- */
remove_wme_list_from_wm (thisAgent, id->id.input_wmes, true);
id->id.input_wmes = NIL;
for (s = id->id.slots; s != NIL; s = s->next)
{
/* --- remove any existing attribute impasse for the slot --- */
/* --- remove all wme's from the slot --- */
remove_wme_list_from_wm (thisAgent, s->wmes);
s->wmes = NIL;
/* --- remove all preferences for the slot --- */
pref = s->all_preferences;
while (pref)
{
next_pref = pref->all_of_slot_next;
remove_preference_from_tm (thisAgent, pref);
/* Note: the call to remove_preference_from_slot handles the removal
of acceptable_preference_wmes */
pref = next_pref;
}
} /* end of for slots loop */
}
void gds_invalid_so_remove_goal ( agent thisAgent,
wme w 
)

Definition at line 3386 of file decide.cpp.

References agent_struct::current_phase, wme_struct::gds, gds_struct::goal, identifier_struct::higher_goal, agent_struct::highest_goal_whose_context_changed, symbol_union::id, identifier_struct::level, slot_struct::next, print_string(), print_with_symbols(), print_wme(), remove_existing_context_and_descendents(), identifier_struct::slots, snprintf_with_symbols(), agent_struct::soar_verbose_flag, agent_struct::sysparams, TRACE_GDS_SYSPARAM, TRACE_OPERAND2_REMOVALS_SYSPARAM, xml_att_val(), xml_begin_tag(), and xml_end_tag().

Referenced by decide_non_context_slot(), remove_input_wme(), and soar_module::remove_module_wme().

{
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 */
}
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");
}
bool level_update_needed ( agent thisAgent,
Symbol sym 
)
inline

Definition at line 664 of file decide.cpp.

References symbol_union::id, IDENTIFIER_SYMBOL_TYPE, identifier_struct::tc_num, and agent_struct::walk_tc_number.

Referenced by walk_and_update_levels().

{
return ( ( sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE ) && ( sym->id.tc_num != thisAgent->walk_tc_number ) );
}
preference* make_fake_preference_for_goal_item ( agent thisAgent,
Symbol goal,
preference cand 
)

Definition at line 1577 of file decide.cpp.

References abort_with_fatal_error(), ACCEPTABLE_PREFERENCE_TYPE, slot_struct::acceptable_preference_wmes, wme_struct::attr, preference_struct::attr, three_field_tests_struct::attr_test, instantiation_struct::backtrace_number, instantiation_struct::bottom_of_instantiated_conditions, condition_struct::bt, BUFFER_MSG_SIZE, agent_struct::condition_pool, condition_struct::data, FALSE, wme_struct::id, preference_struct::id, symbol_union::id, three_field_tests_struct::id_test, instantiation_struct::in_ms, insert_at_head_of_dll, preference_struct::inst, preference_struct::inst_next, preference_struct::inst_prev, agent_struct::instantiation_pool, agent_struct::item_symbol, identifier_struct::level, bt_info_struct::level, make_equality_test(), make_preference(), instantiation_struct::match_goal, instantiation_struct::match_goal_level, instantiation_struct::next, wme_struct::next, condition_struct::next, NIL, instantiation_struct::nots, preference_struct::on_goal_list, POSITIVE_CONDITION, preference_add_ref(), identifier_struct::preferences_from_goal, instantiation_struct::preferences_generated, instantiation_struct::prev, condition_struct::prev, instantiation_struct::prod, bt_info_struct::prohibits, instantiation_struct::reliable, instantiation_struct::rete_token, instantiation_struct::rete_wme, preference_struct::slot, symbol_add_ref(), condition_struct::test_for_acceptable_preference, condition_struct::condition_main_data_union::tests, TOP_GOAL_LEVEL, instantiation_struct::top_of_instantiated_conditions, bt_info_struct::trace, TRUE, condition_struct::type, wme_struct::value, preference_struct::value, three_field_tests_struct::value_test, bt_info_struct::wme_, and wme_add_ref().

Referenced by update_impasse_items().

{
slot *s;
wme *ap_wme;
preference *pref;
condition *cond;
/* --- find the acceptable preference wme we want to backtrace to --- */
s = cand->slot;
for (ap_wme=s->acceptable_preference_wmes; ap_wme!=NIL; ap_wme=ap_wme->next)
if (ap_wme->value==cand->value) break;
if (!ap_wme) {
char msg[BUFFER_MSG_SIZE];
strncpy (msg,
"decide.c: Internal error: couldn't find acceptable pref wme\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
/* --- make the fake preference --- */
/* kjc: here's where we changed REQUIRE to ACCEPTABLE */
pref = make_preference (thisAgent, ACCEPTABLE_PREFERENCE_TYPE, goal, thisAgent->item_symbol,
cand->value, NIL);
symbol_add_ref (pref->id);
all_of_goal_next, all_of_goal_prev);
pref->on_goal_list = TRUE;
/* --- make the fake instantiation --- */
allocate_with_pool (thisAgent, &thisAgent->instantiation_pool, &inst);
pref->inst = inst;
pref->inst_next = pref->inst_prev = NIL;
inst->preferences_generated = pref;
inst->prod = NIL;
inst->next = inst->prev = NIL;
inst->rete_token = NIL;
inst->rete_wme = NIL;
inst->match_goal = goal;
inst->match_goal_level = goal->id.level;
inst->reliable = true;
inst->backtrace_number = 0;
inst->in_ms = FALSE;
/* --- make the fake condition --- */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &cond);
cond->next = cond->prev = NIL;
inst->nots = NIL;
cond->data.tests.id_test = make_equality_test (ap_wme->id);
cond->bt.wme_ = ap_wme;
#ifdef DO_TOP_LEVEL_REF_CTS
wme_add_ref (ap_wme);
#else
#endif
cond->bt.level = ap_wme->id->id.level;
cond->bt.trace = NIL;
cond->bt.prohibits = NIL;
/* --- return the fake preference --- */
return pref;
}
void mark_context_slot_as_acceptable_preference_changed ( agent thisAgent,
slot s 
)
void mark_id_and_tc_as_unknown_level ( agent thisAgent,
Symbol root 
)

Definition at line 563 of file decide.cpp.

References preference_struct::all_of_slot_next, slot_struct::all_preferences, identifier_struct::could_be_a_link_from_below, agent_struct::dl_cons_pool, agent_struct::highest_level_anything_could_fall_from, symbol_union::id, agent_struct::ids_with_unknown_level, slot_struct::impasse_id, identifier_struct::input_wmes, insert_at_head_of_dll, dl_cons_struct::item, identifier_struct::level, agent_struct::level_at_which_marking_started, agent_struct::lowest_level_anything_could_fall_to, LOWEST_POSSIBLE_GOAL_LEVEL, mark_level_unknown_needed(), agent_struct::mark_tc_number, wme_struct::next, slot_struct::next, NIL, preference_is_binary(), preference_struct::referent, identifier_struct::slots, symbol_add_ref(), identifier_struct::tc_num, preference_struct::type, identifier_struct::unknown_level, wme_struct::value, preference_struct::value, and slot_struct::wmes.

Referenced by do_demotion().

{
slot *s;
preference *pref;
wme *w;
dl_cons *dc;
Symbol *id;
#ifdef USE_MEM_POOL_ALLOCATORS
#else
symbol_list ids_to_walk;
#endif
ids_to_walk.push_back( root );
while ( !ids_to_walk.empty() )
{
id = ids_to_walk.back();
ids_to_walk.pop_back();
/* --- if id is already marked, do nothing --- */
if (id->id.tc_num==thisAgent->mark_tc_number) continue;
/* --- don't mark anything higher up as disconnected--in order to be higher
up, it must have a link to it up there --- */
if (id->id.level < thisAgent->level_at_which_marking_started) continue;
/* --- mark id, so we won't do it again later --- */
id->id.tc_num = thisAgent->mark_tc_number;
/* --- update range of goal stack levels we'll need to walk --- */
thisAgent->highest_level_anything_could_fall_from = id->id.level;
thisAgent->lowest_level_anything_could_fall_to = id->id.level;
/* --- add id to the set of ids with unknown level --- */
if (! id->id.unknown_level) {
allocate_with_pool (thisAgent, &thisAgent->dl_cons_pool, &dc);
dc->item = id;
id->id.unknown_level = dc;
insert_at_head_of_dll (thisAgent->ids_with_unknown_level, dc, next, prev);
}
/* -- scan through all preferences and wmes for all slots for this id -- */
for (w=id->id.input_wmes; w!=NIL; w=w->next)
{
if ( mark_level_unknown_needed( thisAgent, w->value ) )
{
ids_to_walk.push_back( w->value );
}
}
for (s=id->id.slots; s!=NIL; s=s->next)
{
for (pref=s->all_preferences; pref!=NIL; pref=pref->all_of_slot_next)
{
if ( mark_level_unknown_needed( thisAgent, pref->value ) )
{
ids_to_walk.push_back( pref->value );
}
{
if ( mark_level_unknown_needed( thisAgent, pref->referent ) )
{
ids_to_walk.push_back( pref->referent );
}
}
}
if(s->impasse_id)
{
if ( mark_level_unknown_needed( thisAgent, s->impasse_id ) )
{
ids_to_walk.push_back( s->impasse_id );
}
}
for (w=s->wmes; w!=NIL; w=w->next)
{
if ( mark_level_unknown_needed( thisAgent, w->value ) )
{
ids_to_walk.push_back( w->value );
}
}
} /* end of for slots loop */
}
}
bool mark_level_unknown_needed ( agent ,
Symbol sym 
)
inline

Definition at line 558 of file decide.cpp.

References IDENTIFIER_SYMBOL_TYPE.

Referenced by mark_id_and_tc_as_unknown_level().

{
return ( sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE );
}
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_candidates ( agent thisAgent,
preference candidates 
)

Definition at line 80 of file decide.cpp.

References preference_struct::attr, preference_struct::id, preference_struct::next_candidate, NIL, print(), print_with_symbols(), and preference_struct::value.

{
preference *cand = 0;
int max_count = 0;
for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
max_count++;
print(thisAgent, "\n Candidate %d", cand);
print_with_symbols(thisAgent, "\n %y %y %y", cand->id, cand->attr, cand->value);
if (max_count > 10)
break;
}
}
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 promote_id_and_tc ( agent thisAgent,
Symbol id,
goal_stack_level  new_level 
)

Definition at line 347 of file decide.cpp.

References abort_with_fatal_error(), preference_struct::all_of_slot_next, slot_struct::all_preferences, BUFFER_MSG_SIZE, wme_struct::id, symbol_union::id, identifier_struct::input_wmes, identifier_struct::isa_goal, identifier_struct::isa_impasse, identifier_struct::level, wme_struct::next, slot_struct::next, NIL, preference_is_binary(), promote_if_needed, identifier_struct::promotion_level, preference_struct::referent, identifier_struct::slots, TRUE, preference_struct::type, wme_struct::value, preference_struct::value, and slot_struct::wmes.

Referenced by do_promotion().

{
slot *s;
preference *pref;
wme *w;
/* --- if it's already that high, or is going to be soon, don't bother -- */
if (id->id.level <= new_level) return;
if (id->id.promotion_level < new_level) return;
/* --- update its level, etc. --- */
id->id.level = new_level;
id->id.promotion_level = new_level;
id->id.could_be_a_link_from_below = TRUE;
/* --- sanity check --- */
if (id->id.isa_goal || id->id.isa_impasse) {
char msg[BUFFER_MSG_SIZE];
strncpy (msg, "decide.c: Internal error: tried to promote a goal or impasse id\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
/* Note--since we can't promote a goal, we don't have to worry about
slot->acceptable_preference_wmes below */
}
/* --- scan through all preferences and wmes for all slots for this id -- */
for (w=id->id.input_wmes; w!=NIL; w=w->next)
promote_if_needed (thisAgent, w->value);
for (s=id->id.slots; s!=NIL; s=s->next) {
for (pref=s->all_preferences; pref!=NIL; pref=pref->all_of_slot_next) {
promote_if_needed (thisAgent, pref->value);
promote_if_needed (thisAgent, pref->referent);
}
for (w=s->wmes; w!=NIL; w=w->next)
promote_if_needed (thisAgent, w->value);
} /* end of for slots loop */
}
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_fake_preference_for_goal_item ( agent thisAgent,
preference pref 
)

Definition at line 1646 of file decide.cpp.

References preference_remove_ref().

Referenced by update_impasse_items().

{
preference_remove_ref (thisAgent, pref); /* everything else happens automatically */
}
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 require_preference_semantics ( agent thisAgent,
slot s,
preference **  result_candidates,
bool  consistency 
)

Definition at line 895 of file decide.cpp.

References CANDIDATE_DECIDER_FLAG, CONSTRAINT_FAILURE_IMPASSE_TYPE, exploration_compute_value_of_candidate(), slot_struct::id, preference_struct::next, preference_struct::next_candidate, NIL, NONE_IMPASSE_TYPE, NOTHING_DECIDER_FLAG, preference_struct::numeric_value, slot_struct::preferences, PROHIBIT_PREFERENCE_TYPE, REQUIRE_PREFERENCE_TYPE, preference_struct::rl_contribution, rl_enabled(), rl_perform_update(), rl_tabulate_reward_values(), and preference_struct::value.

Referenced by run_preference_semantics().

{
preference *candidates;
Symbol *value;
/* --- collect set of required items into candidates list --- */
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
candidates = NIL;
for (p=s->preferences[REQUIRE_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
if (p->value->common.decider_flag == NOTHING_DECIDER_FLAG) {
p->next_candidate = candidates;
candidates = p;
/* --- unmark it, in order to prevent it from being added twice --- */
p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
}
}
*result_candidates = candidates;
/* --- if more than one required item, we have a constraint failure --- */
/* --- just one require, check for require-prohibit impasse --- */
value = candidates->value;
if (p->value == value) return CONSTRAINT_FAILURE_IMPASSE_TYPE;
/* --- the lone require is the winner --- */
if ( !consistency && candidates && rl_enabled( thisAgent ) )
{
exploration_compute_value_of_candidate( thisAgent, candidates, s, 0 );
rl_perform_update( thisAgent, candidates->numeric_value, candidates->rl_contribution, s->id );
}
}
byte run_preference_semantics ( agent thisAgent,
slot s,
preference **  result_candidates,
bool  consistency = false,
bool  predict = false 
)

Definition at line 933 of file decide.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, slot_struct::all_preferences, BEST_DECIDER_FLAG, BEST_PREFERENCE_TYPE, BETTER_PREFERENCE_TYPE, BINARY_INDIFFERENT_PREFERENCE_TYPE, BINARY_PARALLEL_PREFERENCE_TYPE, CANDIDATE_DECIDER_FLAG, float_constant_struct::common_symbol_info, CONFLICT_IMPASSE_TYPE, CONFLICTED_DECIDER_FLAG, exploration_choose_according_to_policy(), exploration_compute_value_of_candidate(), FALSE, symbol_union::fc, FLOAT_CONSTANT_SYMBOL_TYPE, FORMER_CANDIDATE_DECIDER_FLAG, slot_struct::id, INT_CONSTANT_SYMBOL_TYPE, slot_struct::isa_context_slot, mark_slot_for_possible_removal(), preference_struct::next, preference_struct::next_candidate, NIL, NONE_IMPASSE_TYPE, NOTHING_DECIDER_FLAG, NUMERIC_INDIFFERENT_PREFERENCE_TYPE, preference_struct::numeric_value, slot_struct::preferences, PROHIBIT_PREFERENCE_TYPE, preference_struct::referent, REJECT_PREFERENCE_TYPE, require_preference_semantics(), REQUIRE_PREFERENCE_TYPE, preference_struct::rl_contribution, rl_enabled(), rl_perform_update(), rl_tabulate_reward_values(), select_force(), select_get_operator(), symbol_common_data_struct::symbol_type, TIE_IMPASSE_TYPE, TRUE, UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG, UNARY_INDIFFERENT_DECIDER_FLAG, UNARY_INDIFFERENT_PREFERENCE_TYPE, UNARY_PARALLEL_DECIDER_FLAG, UNARY_PARALLEL_PREFERENCE_TYPE, preference_struct::value, WORSE_PREFERENCE_TYPE, WORST_DECIDER_FLAG, and WORST_PREFERENCE_TYPE.

Referenced by decide_context_slot(), decide_non_context_slot(), and run_preference_semantics_for_consistency_check().

{
preference *p, *p2, *cand, *prev_cand;
Bool match_found, not_all_indifferent, not_all_parallel;
preference *candidates;
/* --- if the slot has no preferences at all, things are trivial --- */
if (!s->all_preferences)
{
*result_candidates = NIL;
}
// if this is the true decision slot and selection has been made, attempt force selection
if ( s->isa_context_slot && !consistency)
{
if ( select_get_operator( thisAgent ) != NULL )
{
preference *force_result = select_force( thisAgent, s->preferences[ACCEPTABLE_PREFERENCE_TYPE], !predict );
if ( force_result )
{
force_result->next_candidate = NIL;
*result_candidates = force_result;
if ( !predict && rl_enabled( thisAgent ) )
{
exploration_compute_value_of_candidate( thisAgent, force_result, s, 0 );
rl_perform_update( thisAgent, force_result->numeric_value, force_result->rl_contribution, s->id );
}
}
}
}
/* === Requires === */
return require_preference_semantics (thisAgent, s, result_candidates, consistency);
}
/* === Acceptables, Prohibits, Rejects === */
/* --- mark everything that's acceptable, then unmark the prohibited
and rejected items --- */
p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
/* --- now scan through acceptables and build the list of candidates --- */
candidates = NIL;
if (p->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
p->next_candidate = candidates;
candidates = p;
/* --- unmark it, in order to prevent it from being added twice --- */
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
}
}
if (!s->isa_context_slot) {
*result_candidates = candidates;
}
/* === If there are only 0 or 1 candidates, we're done === */
if ((!candidates) || (! candidates->next_candidate)) {
*result_candidates = candidates;
if ( !consistency && rl_enabled( thisAgent ) && candidates )
{
// perform update here for just one candidate
exploration_compute_value_of_candidate( thisAgent, candidates, s, 0 );
rl_perform_update( thisAgent, candidates->numeric_value, candidates->rl_contribution, s->id );
}
}
/* === Better/Worse === */
#define NEW_PREFERENCES_SCHEME 1 // bug 234
#if(NEW_PREFERENCES_SCHEME == 1)
// new algorithm:
// for each j > k:
// if j is (candidate or conflicted) and k is (candidate or conflicted):
// if one of (j, k) is candidate:
// candidate -= k, if not already true
// conflicted += k, if not already true
// for each j < k:
// if j is (candidate or conflicted) and k is (candidate or conflicted):
// if one of (j, k) is candidate:
// candidate -= j, if not already true
// conflicted += j, if not already true
// if no remaning candidates:
// conflict impasse using conflicted as candidates
// else
// pass on candidates to next filter
{
Symbol *j, *k;
// initialize
for (p=s->preferences[BETTER_PREFERENCE_TYPE]; p!=NIL; p=p->next)
{
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
}
for (p=s->preferences[WORSE_PREFERENCE_TYPE]; p!=NIL; p=p->next)
{
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
}
for (cand=candidates; cand!=NIL; cand=cand->next_candidate) {
cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
}
for (p=s->preferences[BETTER_PREFERENCE_TYPE]; p!=NIL; p=p->next)
{
j = p->value;
k = p->referent;
if (j==k)
continue;
if (j->common.decider_flag && k->common.decider_flag)
{
if (j->common.decider_flag == CANDIDATE_DECIDER_FLAG || k->common.decider_flag == CANDIDATE_DECIDER_FLAG)
k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
}
}
for (p=s->preferences[WORSE_PREFERENCE_TYPE]; p!=NIL; p=p->next)
{
j = p->value;
k = p->referent;
if (j==k)
continue;
if (j->common.decider_flag && k->common.decider_flag)
{
if (j->common.decider_flag == CANDIDATE_DECIDER_FLAG || k->common.decider_flag == CANDIDATE_DECIDER_FLAG)
j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
}
}
/* --- now scan through candidates list, look for remaining candidates --- */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
{
if (cand->value->common.decider_flag==CANDIDATE_DECIDER_FLAG)
break;
}
if (!cand) {
/* --- collect conflicted candidates into new candidates list --- */
prev_cand = NIL;
cand = candidates;
while (cand)
{
if (cand->value->common.decider_flag != CONFLICTED_DECIDER_FLAG)
{
if (prev_cand)
prev_cand->next_candidate = cand->next_candidate;
else
candidates = cand->next_candidate;
}
else
{
prev_cand = cand;
}
cand = cand->next_candidate;
}
*result_candidates = candidates;
}
/* --- non-conflict candidates found, remove conflicts from candidates --- */
prev_cand = NIL;
cand = candidates;
while (cand)
{
if (cand->value->common.decider_flag == CONFLICTED_DECIDER_FLAG)
{
if (prev_cand)
prev_cand->next_candidate = cand->next_candidate;
else
candidates = cand->next_candidate;
}
else
{
prev_cand = cand;
}
cand = cand->next_candidate;
}
}
#else // !NEW_PREFERENCES_SCHEME
Symbol *j, *k;
/* -------------------- Algorithm to find conflicted set:
conflicted = {}
for each (j > k):
if j is (candidate or conflicted)
and k is (candidate or conflicted)
and at least one of j,k is a candidate
then if (k > j) or (j < k) then
conflicted += j, if not already true
conflicted += k, if not already true
candidate -= j, if not already true
candidate -= k, if not already true
for each (j < k):
if j is (candidate or conflicted)
and k is (candidate or conflicted)
and at least one of j,k is a candidate
then if (k < j)
then
conflicted += j, if not already true
conflicted += k, if not already true
candidate -= j, if not already true
candidate -= k, if not already true
----------------------- */
for (p=s->preferences[BETTER_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
}
for (p=s->preferences[WORSE_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
}
for (cand=candidates; cand!=NIL; cand=cand->next_candidate) {
cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
}
for (p=s->preferences[BETTER_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
j = p->value;
k = p->referent;
if (j==k) continue;
if (j->common.decider_flag && k->common.decider_flag) {
if(k->common.decider_flag != CONFLICTED_DECIDER_FLAG)
k->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
if ((j->common.decider_flag!=CONFLICTED_DECIDER_FLAG) ||
(k->common.decider_flag!=CONFLICTED_DECIDER_FLAG)) {
for (p2=s->preferences[BETTER_PREFERENCE_TYPE]; p2; p2=p2->next)
if ((p2->value==k)&&(p2->referent==j)) {
j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
break;
}
for (p2=s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2=p2->next)
if ((p2->value==j)&&(p2->referent==k)) {
j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
break;
}
}
}
}
for (p=s->preferences[WORSE_PREFERENCE_TYPE]; p!=NIL; p=p->next) {
j = p->value;
k = p->referent;
if (j==k) continue;
if (j->common.decider_flag && k->common.decider_flag) {
if(j->common.decider_flag != CONFLICTED_DECIDER_FLAG)
j->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
if ((j->common.decider_flag!=CONFLICTED_DECIDER_FLAG) ||
(k->common.decider_flag!=CONFLICTED_DECIDER_FLAG)) {
for (p2=s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2=p2->next)
if ((p2->value==k)&&(p2->referent==j)) {
j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
break;
}
}
}
}
/* --- now scan through candidates list, look for conflicted stuff --- */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
if (cand->value->common.decider_flag==CONFLICTED_DECIDER_FLAG) break;
if (cand) {
/* --- collect conflicted candidates into new candidates list --- */
prev_cand = NIL;
cand = candidates;
while (cand) {
if (cand->value->common.decider_flag != CONFLICTED_DECIDER_FLAG) {
if (prev_cand)
prev_cand->next_candidate = cand->next_candidate;
else
candidates = cand->next_candidate;
} else {
prev_cand = cand;
}
cand = cand->next_candidate;
}
*result_candidates = candidates;
}
/* --- no conflicts found, remove former_candidates from candidates --- */
prev_cand = NIL;
cand = candidates;
while (cand) {
if (cand->value->common.decider_flag == FORMER_CANDIDATE_DECIDER_FLAG) {
if (prev_cand)
prev_cand->next_candidate = cand->next_candidate;
else
candidates = cand->next_candidate;
} else {
prev_cand = cand;
}
cand = cand->next_candidate;
}
}
#endif // !NEW_PREFERENCES_SCHEME
/* === Bests === */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
for (p=s->preferences[BEST_PREFERENCE_TYPE]; p!=NIL; p=p->next)
p->value->common.decider_flag = BEST_DECIDER_FLAG;
prev_cand = NIL;
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
if (cand->value->common.decider_flag == BEST_DECIDER_FLAG) {
if (prev_cand)
prev_cand->next_candidate = cand;
else
candidates = cand;
prev_cand = cand;
}
if (prev_cand) prev_cand->next_candidate = NIL;
}
/* === Worsts === */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
for (p=s->preferences[WORST_PREFERENCE_TYPE]; p!=NIL; p=p->next)
p->value->common.decider_flag = WORST_DECIDER_FLAG;
prev_cand = NIL;
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
if (cand->value->common.decider_flag != WORST_DECIDER_FLAG) {
if (prev_cand)
prev_cand->next_candidate = cand;
else
candidates = cand;
prev_cand = cand;
}
if (prev_cand) prev_cand->next_candidate = NIL;
}
/* === If there are only 0 or 1 candidates, we're done === */
if ( !candidates || !candidates->next_candidate )
{
*result_candidates = candidates;
if ( !consistency && rl_enabled( thisAgent ) && candidates )
{
// perform update here for just one candidate
exploration_compute_value_of_candidate( thisAgent, candidates, s, 0 );
rl_perform_update( thisAgent, candidates->numeric_value, candidates->rl_contribution, s->id );
}
}
/* === Indifferents === */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->value->common.decider_flag = UNARY_INDIFFERENT_DECIDER_FLAG;
not_all_indifferent = FALSE;
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
{
if (cand->value->common.decider_flag==UNARY_INDIFFERENT_DECIDER_FLAG)
continue;
else if ( cand->value->common.decider_flag==UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG )
continue;
/* --- check whether cand is binary indifferent to each other one --- */
for (p=candidates; p!=NIL; p=p->next_candidate) {
if (p==cand) continue;
match_found = FALSE;
p2=p2->next)
if ( ((p2->value==cand->value)&&(p2->referent==p->value)) ||
((p2->value==p->value)&&(p2->referent==cand->value)) ) {
match_found = TRUE;
break;
}
if (!match_found) {
not_all_indifferent = TRUE;
break;
}
} /* end of for p loop */
if (not_all_indifferent) break;
} /* end of for cand loop */
if ( !not_all_indifferent )
{
if ( !consistency )
{
(*result_candidates) = exploration_choose_according_to_policy( thisAgent, s, candidates );
(*result_candidates)->next_candidate = NIL;
}
else
*result_candidates = candidates;
}
/* --- items not all indifferent; for context slots this gives a tie --- */
if (s->isa_context_slot) {
*result_candidates = candidates;
}
/* === Parallels === */
for (cand=candidates; cand!=NIL; cand=cand->next_candidate)
cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
p->value->common.decider_flag = UNARY_PARALLEL_DECIDER_FLAG;
not_all_parallel = FALSE;
for (cand=candidates; cand!=NIL; cand=cand->next_candidate) {
/* --- if cand is unary parallel, it's fine --- */
if (cand->value->common.decider_flag==UNARY_PARALLEL_DECIDER_FLAG)
continue;
/* --- check whether cand is binary parallel to each other candidate --- */
for (p=candidates; p!=NIL; p=p->next_candidate) {
if (p==cand) continue;
match_found = FALSE;
p2=p2->next)
if ( ((p2->value==cand->value)&&(p2->referent==p->value)) ||
((p2->value==p->value)&&(p2->referent==cand->value)) ) {
match_found = TRUE;
break;
}
if (!match_found) {
not_all_parallel = TRUE;
break;
}
} /* end of for p loop */
if (not_all_parallel) break;
} /* end of for cand loop */
*result_candidates = candidates;
if (! not_all_parallel) {
/* --- items are all parallel, so return them all --- */
}
/* --- otherwise we have a tie --- */
}
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
}
void update_impasse_items ( agent thisAgent,
Symbol id,
preference items 
)

Definition at line 1662 of file decide.cpp.

References add_impasse_wme(), ALREADY_EXISTING_WME_DECIDER_FLAG, wme_struct::attr, CANDIDATE_DECIDER_FLAG, wme_struct::id, symbol_union::id, identifier_struct::impasse_wmes, identifier_struct::isa_goal, agent_struct::item_count_symbol, agent_struct::item_symbol, make_fake_preference_for_goal_item(), make_int_constant(), wme_struct::next, preference_struct::next, preference_struct::next_candidate, NIL, agent_struct::non_numeric_count_symbol, agent_struct::non_numeric_symbol, NOTHING_DECIDER_FLAG, NUMERIC_INDIFFERENT_PREFERENCE_TYPE, wme_struct::preference, slot_struct::preferences, remove_fake_preference_for_goal_item(), remove_from_dll, remove_wme_from_wm(), preference_struct::slot, symbol_remove_ref(), wme_struct::value, and preference_struct::value.

Referenced by decide_context_slot(), decide_non_context_slot(), and remove_existing_context_and_descendents().

{
enum item_types { regular, numeric };
wme *w, *next_w;
preference *cand;
preference *bt_pref;
unsigned int item_count;
Symbol* loop_sym = NULL;
Symbol* loop_count_sym = NULL;
Symbol* count_sym = NULL;
for ( int it=regular; it<=numeric; it++ )
{
if ( it == regular )
{
loop_sym = thisAgent->item_symbol;
loop_count_sym = thisAgent->item_count_symbol;
}
else
{
loop_sym = thisAgent->non_numeric_symbol;
loop_count_sym = thisAgent->non_numeric_count_symbol;
}
// reset flags on existing items to NOTHING
for ( w=id->id.impasse_wmes; w!=NIL; w=w->next )
if ( w->attr == loop_sym )
w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
// reset flags on all items as CANDIDATEs
for ( cand=items; cand!=NIL; cand=cand->next_candidate )
cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
// if numeric, block out candidates with numeric
if ( ( it == numeric ) && items )
{
for ( cand=items->slot->preferences[NUMERIC_INDIFFERENT_PREFERENCE_TYPE]; cand; cand=cand->next )
cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
}
// count up candidates (used for count WME)
item_count = 0;
for ( cand=items; cand!=NIL; cand=cand->next_candidate )
if ( cand->value->common.decider_flag == CANDIDATE_DECIDER_FLAG )
item_count++;
// for each existing item: if supposed to be there, ALREADY EXISTING; otherwise remove
w = id->id.impasse_wmes;
while ( w )
{
next_w = w->next;
if ( w->attr == loop_sym )
{
if ( w->value->common.decider_flag==CANDIDATE_DECIDER_FLAG )
{
w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
w->value->common.a.decider_wme = w; // so we can update the pref later
}
else
{
remove_from_dll( id->id.impasse_wmes, w, next, prev );
if ( id->id.isa_goal )
remove_wme_from_wm( thisAgent, w );
}
}
else if ( w->attr == loop_count_sym )
{
remove_from_dll( id->id.impasse_wmes, w, next, prev );
remove_wme_from_wm( thisAgent, w );
}
w = next_w;
}
// for each desired item: if doesn't ALREADY_EXIST, add it
for ( cand=items; cand!=NIL; cand=cand->next_candidate )
{
// takes care of numerics
if ( cand->value->common.decider_flag == NOTHING_DECIDER_FLAG )
continue;
if (id->id.isa_goal)
bt_pref = make_fake_preference_for_goal_item( thisAgent, id, cand );
else
bt_pref = cand;
if ( cand->value->common.decider_flag == ALREADY_EXISTING_WME_DECIDER_FLAG )
{
if ( id->id.isa_goal )
remove_fake_preference_for_goal_item( thisAgent, cand->value->common.a.decider_wme->preference );
cand->value->common.a.decider_wme->preference = bt_pref;
}
else
{
add_impasse_wme( thisAgent, id, loop_sym, cand->value, bt_pref );
}
}
if ( item_count > 0 )
{
count_sym = make_int_constant( thisAgent, static_cast< int64_t >( item_count ) );
add_impasse_wme( thisAgent, id, loop_count_sym, count_sym, NIL );
symbol_remove_ref( thisAgent, count_sym );
}
}
}
void walk_and_update_levels ( agent thisAgent,
Symbol root 
)

Definition at line 669 of file decide.cpp.

References preference_struct::all_of_slot_next, slot_struct::all_preferences, agent_struct::dl_cons_pool, symbol_union::id, agent_struct::ids_with_unknown_level, slot_struct::impasse_id, identifier_struct::input_wmes, identifier_struct::level, level_update_needed(), wme_struct::next, slot_struct::next, NIL, preference_is_binary(), preference_struct::referent, remove_from_dll, identifier_struct::slots, symbol_remove_ref(), preference_struct::type, identifier_struct::unknown_level, wme_struct::value, preference_struct::value, agent_struct::walk_level, agent_struct::walk_tc_number, and slot_struct::wmes.

Referenced by do_demotion().

{
slot *s;
preference *pref;
wme *w;
dl_cons *dc;
Symbol *id;
#ifdef USE_MEM_POOL_ALLOCATORS
#else
symbol_list ids_to_walk;
#endif
ids_to_walk.push_back( root );
while ( !ids_to_walk.empty() )
{
id = ids_to_walk.back();
ids_to_walk.pop_back();
/* --- mark id so we don't walk it twice --- */
id->id.tc_num = thisAgent->walk_tc_number;
/* --- if we already know its level, and it's higher up, then exit --- */
if ((! id->id.unknown_level) && (id->id.level < thisAgent->walk_level)) continue;
/* --- if we didn't know its level before, we do now --- */
if (id->id.unknown_level) {
dc = id->id.unknown_level;
remove_from_dll (thisAgent->ids_with_unknown_level, dc, next, prev);
free_with_pool (&thisAgent->dl_cons_pool, dc);
symbol_remove_ref (thisAgent, id);
id->id.unknown_level = NIL;
id->id.level = thisAgent->walk_level;
id->id.promotion_level = thisAgent->walk_level;
}
/* -- scan through all preferences and wmes for all slots for this id -- */
for (w=id->id.input_wmes; w!=NIL; w=w->next)
{
if ( level_update_needed( thisAgent, w->value ) )
{
ids_to_walk.push_back( w->value );
}
}
for ( s=id->id.slots; s!=NIL; s=s->next )
{
for ( pref=s->all_preferences; pref!=NIL; pref=pref->all_of_slot_next )
{
if ( level_update_needed( thisAgent, pref->value ) )
{
ids_to_walk.push_back( pref->value );
if ( preference_is_binary( pref->type ) )
{
if ( level_update_needed( thisAgent, pref->referent ) )
{
ids_to_walk.push_back( pref->referent );
}
}
}
}
if ( s->impasse_id )
{
if ( level_update_needed( thisAgent, s->impasse_id ) )
{
ids_to_walk.push_back( s->impasse_id );
}
}
for ( w=s->wmes; w!=NIL; w=w->next )
{
if ( level_update_needed( thisAgent, w->value ) )
{
ids_to_walk.push_back( w->value );
}
}
}
}
}