void rl_add_goal_or_impasse_tests_to_conds( agent *my_agent, condition *all_conds ) { // mark each id as we add a test for it, so we don't add a test for the same id in two different places Symbol *id; test t; complex_test *ct; tc_number tc = get_new_tc_number( my_agent ); for ( condition *cond = all_conds; cond != NIL; cond = cond->next ) { if ( cond->type != POSITIVE_CONDITION ) continue; id = referent_of_equality_test( cond->data.tests.id_test ); if ( ( id->id.isa_goal || id->id.isa_impasse ) && ( id->id.tc_num != tc ) ) { allocate_with_pool( my_agent, &my_agent->complex_test_pool, &ct ); ct->type = static_cast<byte>( ( id->id.isa_goal )?( GOAL_ID_TEST ):( IMPASSE_ID_TEST ) ); t = make_test_from_complex_test( ct ); add_new_test_to_test( my_agent, &( cond->data.tests.id_test ), t ); id->id.tc_num = tc; } } }
inline void wma_forgetting_add_to_p_queue( agent* my_agent, wma_decay_element* decay_el, wma_d_cycle new_cycle ) { if ( decay_el ) { decay_el->forget_cycle = new_cycle; wma_forget_p_queue::iterator pq_p = my_agent->wma_forget_pq->find( new_cycle ); if ( pq_p == my_agent->wma_forget_pq->end() ) { wma_decay_set* newbie; allocate_with_pool( my_agent, &( my_agent->wma_decay_set_pool ), &newbie ); #ifdef USE_MEM_POOL_ALLOCATORS newbie = new (newbie) wma_decay_set( std::less< wma_decay_element* >(), soar_module::soar_memory_pool_allocator< wma_decay_element* >( my_agent ) ); #else newbie = new (newbie) wma_decay_set(); #endif newbie->insert( decay_el ); my_agent->wma_forget_pq->insert( std::make_pair( new_cycle, newbie ) ); } else { pq_p->second->insert( decay_el ); } } }
// creates an action for a template instantiation action *rl_make_simple_action( agent *my_agent, Symbol *id_sym, Symbol *attr_sym, Symbol *val_sym, Symbol *ref_sym ) { action *rhs; Symbol *temp; allocate_with_pool( my_agent, &my_agent->action_pool, &rhs ); rhs->next = NIL; rhs->type = MAKE_ACTION; // id temp = id_sym; symbol_add_ref( temp ); variablize_symbol( my_agent, &temp ); rhs->id = symbol_to_rhs_value( temp ); // attribute temp = attr_sym; symbol_add_ref( temp ); variablize_symbol( my_agent, &temp ); rhs->attr = symbol_to_rhs_value( temp ); // value temp = val_sym; symbol_add_ref( temp ); variablize_symbol( my_agent, &temp ); rhs->value = symbol_to_rhs_value( temp ); // referent temp = ref_sym; symbol_add_ref( temp ); variablize_symbol( my_agent, &temp ); rhs->referent = symbol_to_rhs_value( temp ); return rhs; }
void mark_slot_as_changed(agent* thisAgent, slot* s) { dl_cons* dc; if (s->isa_context_slot) { if (thisAgent->highest_goal_whose_context_changed) { if (s->id->id->level < thisAgent->highest_goal_whose_context_changed->id->level) { thisAgent->highest_goal_whose_context_changed = s->id; } } else { thisAgent->highest_goal_whose_context_changed = s->id; } s->changed = reinterpret_cast<dl_cons*>(s); /* just make it nonzero */ } else { if (! s->changed) { allocate_with_pool(thisAgent, &thisAgent->dl_cons_pool, &dc); dc->item = s; s->changed = dc; insert_at_head_of_dll(thisAgent->changed_slots, dc, next, prev); } } }
slot* make_slot(agent* thisAgent, Symbol* id, Symbol* attr) { slot* s; int i; /* JC: Search for a slot first. If it exists * for the given symbol, then just return it */ for (s = id->id->slots; s != NIL; s = s->next) { if (s->attr == attr) { return s; } } /* JC: need to create a new slot */ allocate_with_pool(thisAgent, &thisAgent->slot_pool, &s); insert_at_head_of_dll(id->id->slots, s, next, prev); /* Context slots are goals and operators; operator slots get * created with a goal (see create_new_context). */ if ((id->id->isa_goal) && (attr == thisAgent->operator_symbol)) { s->isa_context_slot = true; } else { s->isa_context_slot = false; } s->changed = NIL; s->acceptable_preference_changed = NIL; s->id = id; s->attr = attr; symbol_add_ref(thisAgent, id); symbol_add_ref(thisAgent, attr); s->wmes = NIL; s->all_preferences = NIL; s->CDPS = NIL; /* JC: This is the same as all_preferences * except they are indexed by type. */ for (i = 0; i < NUM_PREFERENCE_TYPES; i++) { s->preferences[i] = NIL; } s->impasse_type = NONE_IMPASSE_TYPE; s->impasse_id = NIL; s->acceptable_preference_wmes = NIL; s->marked_for_possible_removal = false; s->wma_val_references = NIL; return s; }
void update_for_top_state_wme_addition(wme * w) { output_link *ol; soar_callback *cb; char link_name[LINK_NAME_SIZE]; /* --- check whether the attribute is an output function --- */ symbol_to_string(w->attr, FALSE, link_name, LINK_NAME_SIZE); cb = soar_exists_callback_id(soar_agent, OUTPUT_PHASE_CALLBACK, link_name); if (!cb) return; /* --- create new output link structure --- */ allocate_with_pool(¤t_agent(output_link_pool), &ol); insert_at_head_of_dll(current_agent(existing_output_links), ol, next, prev); ol->status = NEW_OL_STATUS; ol->link_wme = w; wme_add_ref(w); ol->ids_in_tc = NIL; ol->cb = cb; /* --- make wme point to the structure --- */ w->output_link = ol; /* SW 07 10 2003 previously, this wouldn't be done until the first OUTPUT phase. However, if we add an output command in the 1st decision cycle, Soar seems to ignore it. There may be two things going on, the first having to do with the tc calculation, which may get done too late, in such a way that the initial calculation includes the command. The other thing appears to be that some data structures are not initialized until the first output phase. Namely, id->associated_output_links does not seem reflect the current output links until the first output-phase. To get past these issues, we fake a transitive closure calculation with the knowledge that the only thing on the output link at this point is the output-link identifier itself. This way, we capture a snapshot of the empty output link, so Soar can detect any changes that might occur before the first output_phase. */ current_agent(output_link_tc_num) = get_new_tc_number(); ol->link_wme->value->id.tc_num = current_agent(output_link_tc_num); current_agent(output_link_for_tc) = ol; /* --- add output_link to id's list --- */ push(current_agent(output_link_for_tc), ol->link_wme->value->id.associated_output_links); }
instantiation* make_fake_instantiation( agent* my_agent, Symbol* state, wme_set* conditions, symbol_triple_list* actions ) { // make fake instantiation instantiation* inst; allocate_with_pool( my_agent, &( my_agent->instantiation_pool ), &inst ); inst->prod = NULL; inst->next = inst->prev = NULL; inst->rete_token = NULL; inst->rete_wme = NULL; inst->match_goal = state; inst->match_goal_level = state->id.level; inst->reliable = true; inst->backtrace_number = 0; inst->in_ms = FALSE; inst->GDS_evaluated_already = FALSE; // create preferences inst->preferences_generated = NULL; { preference* pref; for ( symbol_triple_list::iterator a_it=actions->begin(); a_it!=actions->end(); a_it++ ) { pref = make_preference( my_agent, ACCEPTABLE_PREFERENCE_TYPE, (*a_it)->id, (*a_it)->attr, (*a_it)->value, NIL ); pref->o_supported = true; symbol_add_ref( pref->id ); symbol_add_ref( pref->attr ); symbol_add_ref( pref->value ); pref->inst = inst; pref->inst_next = pref->inst_prev = NULL; insert_at_head_of_dll( inst->preferences_generated, pref, inst_next, inst_prev ); } } // create conditions { condition *cond = NULL; condition *prev_cond = NULL; for ( wme_set::iterator c_it=conditions->begin(); c_it!=conditions->end(); c_it++ ) { // construct the condition allocate_with_pool( my_agent, &( my_agent->condition_pool ), &cond ); cond->type = POSITIVE_CONDITION; cond->prev = prev_cond; cond->next = NULL; if ( prev_cond != NULL ) { prev_cond->next = cond; } else { inst->top_of_instantiated_conditions = cond; inst->bottom_of_instantiated_conditions = cond; inst->nots = NULL; } cond->data.tests.id_test = make_equality_test( (*c_it)->id ); cond->data.tests.attr_test = make_equality_test( (*c_it)->attr ); cond->data.tests.value_test = make_equality_test( (*c_it)->value ); cond->test_for_acceptable_preference = (*c_it)->acceptable; cond->bt.wme_ = (*c_it); #ifndef DO_TOP_LEVEL_REF_CTS if ( inst->match_goal_level > TOP_GOAL_LEVEL ) #endif { wme_add_ref( (*c_it) ); } cond->bt.level = (*c_it)->id->id.level; cond->bt.trace = (*c_it)->preference; if ( cond->bt.trace ) { #ifndef DO_TOP_LEVEL_REF_CTS if ( inst->match_goal_level > TOP_GOAL_LEVEL ) #endif { preference_add_ref( cond->bt.trace ); } } cond->bt.CDPS = NULL; prev_cond = cond; } } return inst; }
void create_instantiation (production *prod, struct token_struct *tok, wme *w) { instantiation *inst; condition *cond; preference *pref; action *a; cons *c; bool need_to_do_support_calculations; bool trace_it; long index; Symbol **cell; allocate_with_pool (¤t_agent(instantiation_pool), &inst); inst->next = current_agent(newly_created_instantiations); current_agent(newly_created_instantiations) = inst; inst->prod = prod; inst->rete_token = tok; inst->rete_wme = w; inst->okay_to_variablize = TRUE; inst->in_ms = TRUE; /* REW: begin 09.15.96 */ /* We want to initialize the GDS_evaluated_already flag * when a new instantiation is created. */ inst->GDS_evaluated_already = FALSE; if (current_agent(operand2_mode) == TRUE) { if (current_agent(soar_verbose_flag) == TRUE) print_with_symbols("\n in create_instantiation: %y", inst->prod->name); } /* REW: end 09.15.96 */ current_agent(production_being_fired) = inst->prod; prod->firing_count++; current_agent(production_firing_count)++; /* --- build the instantiated conditions, and bind LHS variables --- */ p_node_to_conditions_and_nots (prod->p_node, tok, w, &(inst->top_of_instantiated_conditions), &(inst->bottom_of_instantiated_conditions), &(inst->nots), NIL); /* --- record the level of each of the wmes that was positively tested --- */ for (cond=inst->top_of_instantiated_conditions; cond!=NIL; cond=cond->next) { if (cond->type==POSITIVE_CONDITION) { cond->bt.level = cond->bt.wme->id->id.level; cond->bt.trace = cond->bt.wme->preference; } } /* --- print trace info --- */ trace_it = trace_firings_of_inst (inst); if (trace_it) { if (get_printer_output_column()!=1) print ("\n"); /* AGR 617/634 */ print ("Firing "); print_instantiation_with_wmes (inst, (wme_trace_type)(current_agent(sysparams)[TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM])); } /* --- initialize rhs_variable_bindings array with names of variables (if there are any stored on the production -- for chunks there won't be any) --- */ index = 0; cell = current_agent(rhs_variable_bindings); for (c=prod->rhs_unbound_variables; c!=NIL; c=c->rest) { *(cell++) = c->first; index++; } firer_highest_rhs_unboundvar_index = index-1; /* 7.1/8 merge: Not sure about this. This code in 704, but not in either 7.1 or 703/soar8 */ /* --- Before executing the RHS actions, tell the user that the -- */ /* --- phase has changed to output by printing the arrow --- */ if (trace_it && current_agent(sysparams)[TRACE_FIRINGS_PREFERENCES_SYSPARAM]) { print (" -->\n");} /* --- execute the RHS actions, collect the results --- */ inst->preferences_generated = NIL; need_to_do_support_calculations = FALSE; for (a=prod->action_list; a!=NIL; a=a->next) { pref = execute_action (a, tok, w); if (pref) { pref->inst = inst; insert_at_head_of_dll (inst->preferences_generated, pref, inst_next, inst_prev); if (inst->prod->declared_support==DECLARED_O_SUPPORT) pref->o_supported = TRUE; else if (inst->prod->declared_support==DECLARED_I_SUPPORT) pref->o_supported = FALSE; else { if (current_agent(operand2_mode) == TRUE) { pref->o_supported = (current_agent(FIRING_TYPE) == PE_PRODS) ? TRUE : FALSE; } /* REW: end 09.15.96 */ else { if (a->support==O_SUPPORT) pref->o_supported = TRUE; else if (a->support==I_SUPPORT) pref->o_supported = FALSE; else { need_to_do_support_calculations = TRUE; if (current_agent(soar_verbose_flag) == TRUE) printf("\n\nin create_instantiation(): need_to_do_support_calculations == TRUE!!!\n\n"); } } } } } /* --- reset rhs_variable_bindings array to all zeros --- */ index = 0; cell = current_agent(rhs_variable_bindings); while (index++ <= firer_highest_rhs_unboundvar_index) *(cell++) = NIL; /* --- fill in lots of other stuff --- */ fill_in_new_instantiation_stuff (inst, need_to_do_support_calculations); /* --- print trace info: printing preferences --- */ /* Note: can't move this up, since fill_in_new_instantiation_stuff gives the o-support info for the preferences we're about to print */ if (trace_it && current_agent(sysparams)[TRACE_FIRINGS_PREFERENCES_SYSPARAM]) { for (pref=inst->preferences_generated; pref!=NIL; pref=pref->inst_next) { print (" "); print_preference (pref); } } /* mvp 5-17-94 */ build_prohibits_list (inst); current_agent(production_being_fired) = NIL; /* --- build chunks/justifications if necessary --- */ chunk_instantiation (inst, (bool)current_agent(sysparams)[LEARNING_ON_SYSPARAM]); #ifndef NO_CALLBACKS /* kjc 1/00 */ /* MVP 6-8-94 */ if (!current_agent(system_halted)) { /* --- invoke callback function --- */ soar_invoke_callbacks(soar_agent, FIRING_CALLBACK, (soar_call_data) inst); } #endif }
saved_test *simplify_test (agent* thisAgent, test *t, saved_test *old_sts) { test New, subtest; saved_test *saved; Symbol *var, *sym; cons *c, *prev_c, *next_c; complex_test *ct; if (test_is_blank_test(*t)) { sym = generate_new_variable (thisAgent, "dummy-"); *t = make_equality_test_without_adding_reference (sym); return old_sts; } if (test_is_blank_or_equality_test(*t)) { return old_sts; } ct = complex_test_from_test(*t); switch (ct->type) { case CONJUNCTIVE_TEST: /* --- look at subtests for an equality test --- */ sym = NIL; for (c=ct->data.conjunct_list; c!=NIL; c=c->rest) { subtest = static_cast<char *>(c->first); if (test_is_blank_or_equality_test(subtest)) sym = referent_of_equality_test(subtest); } /* --- if no equality test was found, generate a variable for it --- */ if (!sym) { sym = generate_new_variable (thisAgent, "dummy-"); New = make_equality_test_without_adding_reference (sym); allocate_cons (thisAgent, &c); c->first = New; c->rest = ct->data.conjunct_list; ct->data.conjunct_list = c; } /* --- scan through, create saved_test for subtests except equality --- */ prev_c = NIL; c = ct->data.conjunct_list; while (c) { next_c = c->rest; subtest = static_cast<char *>(c->first); if (! test_is_blank_or_equality_test(subtest)) { /* --- create saved_test, splice this cons out of conjunct_list --- */ allocate_with_pool (thisAgent, &thisAgent->saved_test_pool, &saved); saved->next = old_sts; old_sts = saved; saved->var = sym; symbol_add_ref (sym); saved->the_test = subtest; if (prev_c) prev_c->rest = next_c; else ct->data.conjunct_list = next_c; free_cons (thisAgent, c); } else { prev_c = c; } c = next_c; } break; default: /* --- goal/impasse, disjunction, and non-equality relational tests --- */ var = generate_new_variable (thisAgent, "dummy-"); New = make_equality_test_without_adding_reference (var); allocate_with_pool (thisAgent, &thisAgent->saved_test_pool, &saved); saved->next = old_sts; old_sts = saved; saved->var = var; symbol_add_ref (var); saved->the_test = *t; *t = New; break; } return old_sts; }
void wma_activate_wme( agent* my_agent, wme* w, wma_reference num_references, wma_pooled_wme_set* o_set, bool o_only ) { // o-supported, non-architectural WME if ( wma_should_have_decay_element( w ) ) { wma_decay_element* temp_el = w->wma_decay_el; // if decay structure doesn't exist, create it if ( !temp_el ) { allocate_with_pool( my_agent, &( my_agent->wma_decay_element_pool ), &temp_el ); temp_el->this_wme = w; temp_el->just_removed = false; temp_el->just_created = true; temp_el->num_references = wma_calculate_initial_boost( my_agent, w ); temp_el->touches.history_ct = 0; temp_el->touches.next_p = 0; for ( int i=0; i<WMA_DECAY_HISTORY; i++ ) { temp_el->touches.access_history[ i ].d_cycle = 0; temp_el->touches.access_history[ i ].num_references = 0; } temp_el->touches.history_references = 0; temp_el->touches.total_references = 0; temp_el->touches.first_reference = 0; // prevents confusion with delayed forgetting temp_el->forget_cycle = static_cast< wma_d_cycle >( -1 ); w->wma_decay_el = temp_el; if ( my_agent->sysparams[ TRACE_WMA_SYSPARAM ] ) { std::string msg( "WMA @" ); std::string temp; to_string( my_agent->d_cycle_count, temp ); msg.append( temp ); msg.append( ": " ); msg.append( "add " ); to_string( w->timetag, temp ); msg.append( temp ); msg.append( " " ); to_string( w->id->id.name_letter, temp ); msg.append( temp ); to_string( w->id->id.name_number, temp ); msg.append( temp ); msg.append( " " ); switch ( w->attr->common.symbol_type ) { case INT_CONSTANT_SYMBOL_TYPE: to_string( w->attr->ic.value, temp ); break; case FLOAT_CONSTANT_SYMBOL_TYPE: to_string( w->attr->fc.value, temp ); break; case SYM_CONSTANT_SYMBOL_TYPE: to_string( w->attr->sc.name, temp ); break; } msg.append( temp ); msg.append( " " ); switch ( w->value->common.symbol_type ) { case INT_CONSTANT_SYMBOL_TYPE: to_string( w->value->ic.value, temp ); break; case FLOAT_CONSTANT_SYMBOL_TYPE: to_string( w->value->fc.value, temp ); break; case SYM_CONSTANT_SYMBOL_TYPE: to_string( w->value->sc.name, temp ); break; } msg.append( temp ); msg.append( "\n" ); print( my_agent, msg.c_str() ); xml_generate_warning( my_agent, msg.c_str() ); } } // add to o_set if necessary if ( o_set ) { o_set->insert( w ); } // otherwise update the decay element else { temp_el->num_references += num_references; my_agent->wma_touched_elements->insert( w ); } } // i-supported, non-architectural WME else if ( !o_only && ( w->preference ) && ( w->preference->reference_count ) ) { wma_pooled_wme_set* my_o_set = w->preference->wma_o_set; wma_pooled_wme_set::iterator wme_p; // if doesn't have an o_set, populate if ( !my_o_set ) { allocate_with_pool( my_agent, &( my_agent->wma_wme_oset_pool ), &my_o_set ); #ifdef USE_MEM_POOL_ALLOCATORS my_o_set = new( my_o_set ) wma_pooled_wme_set( std::less< wme* >(), soar_module::soar_memory_pool_allocator< wme* >( my_agent ) ); #else my_o_set = new( my_o_set ) wma_pooled_wme_set(); #endif w->preference->wma_o_set = my_o_set; for ( condition* c=w->preference->inst->top_of_instantiated_conditions; c; c=c->next ) { if ( c->type == POSITIVE_CONDITION ) { wma_activate_wme( my_agent, c->bt.wme_, 0, my_o_set ); } } for ( wme_p=my_o_set->begin(); wme_p!=my_o_set->end(); wme_p++ ) { // add a ref to wmes on this list wme_add_ref( (*wme_p) ); } } // iterate over the o_set for ( wme_p=my_o_set->begin(); wme_p!=my_o_set->end(); wme_p++ ) { // if populating o_set, add if ( o_set ) { o_set->insert( (*wme_p) ); } // otherwise, "activate" the wme if it is // non-architectural (avoids dereferencing // the wme preference) else { if ( (*wme_p)->wma_decay_el ) { (*wme_p)->wma_decay_el->num_references += num_references; my_agent->wma_touched_elements->insert( (*wme_p) ); } } } } // architectural else if ( !o_only && !w->preference && ( w->reference_count != 0 ) ) { // only action is to add it to the o_set if ( o_set ) { o_set->insert( w ); } } }