Beispiel #1
0
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);
        }
    }
}
Beispiel #2
0
wme *add_input_wme(Symbol * id, Symbol * attr, Symbol * value)
{
    wme *w;

    /* --- a little bit of error checking --- */
    if (!(id && attr && value)) {
        print("Error: an input routine gave a NULL argument to add_input_wme.\n");
        return NIL;
    }
    /* --- go ahead and add the wme --- */
    w = make_wme(id, attr, value, FALSE);
    insert_at_head_of_dll(id->id.input_wmes, w, next, prev);
    add_wme_to_wm(w);

    /* SW NOTE:
     * In an ideal world, we could capture input wmes here as well as
     * in soar_cAddWme.  However the problem is that based on the arguments
     * to this function it is impossible to determine if the wme which is
     * being added references new, or just previously defined symbols. 
     * As a result, we cannot capture input wmes asserted using this function
     * with any hope of accurately replaying them in the future.
     */

    return w;
}
Beispiel #3
0
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;
}
Beispiel #4
0
void cache_preference_if_necessary(agent* thisAgent, preference* pref)
{
    if ((pref->inst->match_goal_level != TOP_GOAL_LEVEL) && thisAgent->explanationMemory->is_any_enabled())
    {
        preference* lNewPref = shallow_copy_preference(thisAgent, pref);
        insert_at_head_of_dll(pref->inst->preferences_cached, lNewPref, inst_next, inst_prev);
    }
}
Beispiel #5
0
	wme *add_module_wme( agent *my_agent, Symbol *id, Symbol *attr, Symbol *value )
	{
		slot *my_slot = make_slot( my_agent, id, attr );
		wme *w = make_wme( my_agent, id, attr, value, false );

		insert_at_head_of_dll( my_slot->wmes, w, next, prev );
		add_wme_to_wm( my_agent, w );

		return w;
	}
Beispiel #6
0
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(&current_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);

}
Beispiel #7
0
void SMem_Manager::install_buffered_triple_list(Symbol* state, wme_set& cue_wmes, symbol_triple_list& my_list, bool meta, bool stripLTILinks)
{
    if (my_list.empty())
    {
        return;
    }
    dprint(DT_SMEM_INSTANCE, "install_buffered_triple_list called in state %y.  Creating architectural instantiation.\n", state);

    instantiation* inst = make_architectural_instantiation_for_memory_system(thisAgent, state, &cue_wmes, &my_list, true);
    for (preference* pref = inst->preferences_generated; pref;)
    {
        if (add_preference_to_tm(thisAgent, pref))
        {
            // and add it to the list of preferences to be removed
            // when the goal is removed
            dprint(DT_SMEM_INSTANCE, "...adding preference %p to WM\n", pref);
            insert_at_head_of_dll(state->id->preferences_from_goal, pref, all_of_goal_next, all_of_goal_prev);
            pref->on_goal_list = true;
            if (meta)
            {
                // if this is a meta wme, then it is completely local
                // to the state and thus we will manually remove it
                // (via preference removal) when the time comes
                state->id->smem_info->smem_wmes->push_back(pref);
            }
        }
        else
        {
            dprint(DT_SMEM_INSTANCE, "...could not add preference %p to WM.  Deallocating.\n", pref);
            if (pref->reference_count == 0)
            {
                preference* previous = pref;
                pref = pref->inst_next;
                possibly_deallocate_preference_and_clones(thisAgent, previous, true);
                continue;
            }
        }
        if (stripLTILinks)
        {
            pref->id->id->LTI_ID = 0;
            pref->id->update_cached_lti_print_str();
            if (pref->value->is_sti())
            {
                pref->value->id->LTI_ID = 0;
                pref->value->update_cached_lti_print_str();
            }

        }
        pref = pref->inst_next;
    }

    if (!meta)
    {
        // Create an architectural instantiation to allow backtracing
        // for chunks, justifications and the GDS.

        instantiation* my_justification_list = NIL;
        dprint(DT_MILESTONES, "Asserting preferences of new architectural instantiation in _smem_process_buffered_wme_list...\n");
        // if any justifications are created, assert their preferences manually
        // (copied mainly from assert_new_preferences with respect to our circumstances)
        if (my_justification_list != NIL)
        {
            preference* just_pref = NIL;
            instantiation* next_justification = NIL;

            for (instantiation* my_justification = my_justification_list;
                my_justification != NIL;
                my_justification = next_justification)
            {
                next_justification = my_justification->next;

                if (my_justification->in_ms)
                {
                    insert_at_head_of_dll(my_justification->prod->instantiations, my_justification, next, prev);
                }

                for (just_pref = my_justification->preferences_generated; just_pref != NIL;)
                {
                    if (add_preference_to_tm(thisAgent, just_pref))
                    {
                        if (wma_enabled(thisAgent))
                        {
                            wma_activate_wmes_in_pref(thisAgent, just_pref);
                        }
                    }
                    else
                    {
                        if (just_pref->reference_count == 0)
                        {
                            preference* previous = just_pref;
                            just_pref = just_pref->inst_next;
                            possibly_deallocate_preference_and_clones(thisAgent, previous, true);
                            continue;
                        }
                    }

                    just_pref = just_pref->inst_next;
                }
            }
        }
    }
}
Beispiel #8
0
bool add_preference_to_tm(agent* thisAgent, preference* pref)
{

    slot* s = make_slot(thisAgent, pref->id, pref->attr);
    preference* p2;

    if (!thisAgent->Decider->settings[DECIDER_KEEP_TOP_OPREFS] && (pref->inst->match_goal == thisAgent->top_state) && pref->o_supported && !s->isa_context_slot && (pref->type == ACCEPTABLE_PREFERENCE_TYPE) )
    {
        /* We could potentially cache a list of all o-supported values in the slot so that we don't have to iterate
         * through all of the preferences. We would need to maintain the list as we decide non-context slots */
        bool already_top_o_supported = false;

        for (p2 = s->all_preferences; (p2 && !already_top_o_supported); p2 = p2->all_of_slot_next)
        {
            if ((p2->value == pref->value) && p2->o_supported && (p2->inst->match_goal == thisAgent->top_state))
            {
                already_top_o_supported = true;
            }
        }

        if (already_top_o_supported)
        {
            if (thisAgent->trace_settings[TRACE_FIRINGS_PREFERENCES_SYSPARAM])
            {
                thisAgent->outputManager->printa_sf(thisAgent,  "%e+ ");
                print_preference(thisAgent, pref, false);
                thisAgent->outputManager->printa_sf(thisAgent,  " (%y) ALREADY SUPPORTED ON TOP LEVEL.  IGNORING.\n", pref->inst->prod_name);
            }
            return false;
        }
    }

    pref->slot = s;

    insert_at_head_of_dll(s->all_preferences, pref, all_of_slot_next, all_of_slot_prev);

    /*  add to preference list of slot (according to match goal level of the instantiations) */

    if (!s->preferences[pref->type])
    {
        /*  this is the only pref. of its type, just put it at the head */
        insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
    }
    else if (s->preferences[pref->type]->inst->match_goal_level >= pref->inst->match_goal_level)
    {
        /*  it belongs at the head of the list, so put it there */
        insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
    }
    else
    {
        /*  scan through the pref. list, find the one to insert after */
        for (p2 = s->preferences[pref->type]; p2->next != NIL; p2 = p2->next)
        {
            if (p2->next->inst->match_goal_level >= pref->inst->match_goal_level)
            {
                break;
            }
        }

        /*  insert pref after p2 */
        pref->next = p2->next;
        pref->prev = p2;
        p2->next = pref;
        if (pref->next)
        {
            pref->next->prev = pref;
        }
    }

    pref->in_tm = true;
    preference_add_ref(pref);

    /* If the slot is unchanged but has some references laying around, we clear them
     * This does not lead to immediate memory deallocate/allocate but once the WMEs are
     * resolved, this should free the memory. */
    if (wma_enabled(thisAgent) && !s->isa_context_slot)
    {
        if (!s->changed)
        {
            if (s->wma_val_references != NIL)
            {
                s->wma_val_references->clear();
            }
        }
    }

    mark_slot_as_changed(thisAgent, s);

    if (wma_enabled(thisAgent) && !s->isa_context_slot)
    {
        bool exists = false;
        wme* w = pref->slot->wmes;
        while (!exists && w)
        {
            if (w->value == pref->value)
            {
                exists = true;
            }

            w = w->next;
        }

        /* If wme exists, it should already have been updated during assertion of new preferences */
        if (!exists)
        {
            if (s->wma_val_references == NIL)
            {
                thisAgent->memoryManager->allocate_with_pool(MP_wma_slot_refs, &(s->wma_val_references));
#ifdef USE_MEM_POOL_ALLOCATORS
                s->wma_val_references = new(s->wma_val_references) wma_sym_reference_map(std::less< Symbol* >(), soar_module::soar_memory_pool_allocator< std::pair< Symbol*, uint64_t > >());
#else
                s->wma_val_references = new(s->wma_val_references) wma_sym_reference_map();
#endif
            }

            (*s->wma_val_references)[ pref->value ]++;
        }
    }

    /*  update identifier levels */
    if (pref->value->symbol_type == IDENTIFIER_SYMBOL_TYPE)
    {
        post_link_addition(thisAgent, pref->id, pref->value);
    }
    if (preference_is_binary(pref->type))
    {
        if (pref->referent->symbol_type == IDENTIFIER_SYMBOL_TYPE)
        {
            post_link_addition(thisAgent, pref->id, pref->referent);
        }
    }

    /*  if acceptable/require pref for context slot, we may need to add a wme later */
    if ((s->isa_context_slot) &&  ((pref->type == ACCEPTABLE_PREFERENCE_TYPE) || (pref->type == REQUIRE_PREFERENCE_TYPE)))
    {
        mark_context_slot_as_acceptable_preference_changed(thisAgent, s);
    }
    if (thisAgent->trace_settings[TRACE_FIRINGS_PREFERENCES_SYSPARAM])
    {
        thisAgent->outputManager->printa_sf(thisAgent,  "%e+ ");
        print_preference(thisAgent, pref, false);
        thisAgent->outputManager->printa_sf(thisAgent,  " (%y)\n", pref->inst->prod_name);
    }

    return true;
}
Beispiel #9
0
	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;
	}
Beispiel #10
0
void assert_new_preferences (void) {
  instantiation *inst, *next_inst;
  preference *pref, *next_pref;
  preference *o_rejects;

  o_rejects = NIL;  


  /* REW: begin 09.15.96 */
  if ((current_agent(operand2_mode) == TRUE) &&
      (current_agent(soar_verbose_flag) == TRUE))
     printf("\n   in assert_new_preferences:");
  /* REW: end   09.15.96 */


  for (inst=current_agent(newly_created_instantiations);
       inst!=NIL;
       inst=next_inst) {
    next_inst = inst->next;
    if (inst->in_ms)
      insert_at_head_of_dll (inst->prod->instantiations, inst, next, prev);


    /* REW: begin 09.15.96 */
    if (current_agent(operand2_mode) == TRUE) {
       if (current_agent(soar_verbose_flag) == TRUE)
	  print_with_symbols("\n      asserting instantiation: %y\n",
			     inst->prod->name);
    }
    /* REW: end   09.15.96 */


    for (pref=inst->preferences_generated; pref!=NIL; pref=next_pref) {
      next_pref = pref->inst_next;
      if ((pref->type==REJECT_PREFERENCE_TYPE)&&(pref->o_supported)) {
        /* --- o-reject: just put it in the buffer for later --- */
        pref->next = o_rejects;
        o_rejects = pref;


	/* REW: begin 09.15.96 */
	/* No knowledge retrieval necessary in Operand2 */
	/* REW: end   09.15.96 */

      } else if (inst->in_ms || pref->o_supported) {
        /* --- normal case --- */
        add_preference_to_tm (pref);


	/* REW: begin 09.15.96 */
	/* No knowledge retrieval necessary in Operand2 */
	/* REW: end   09.15.96 */


      } else {
        /* --- inst. is refracted chunk, and pref. is not o-supported:
           remove the preference --- */
        /* --- first splice it out of the clones list--otherwise we might
           accidentally deallocate some clone that happens to have refcount==0
           just because it hasn't been asserted yet --- */
        if (pref->next_clone) pref->next_clone->prev_clone = pref->prev_clone;
        if (pref->prev_clone) pref->prev_clone->next_clone = pref->next_clone;
        pref->next_clone = pref->prev_clone = NIL;
        /* --- now add then remove ref--this should result in deallocation */
        preference_add_ref (pref);
        preference_remove_ref (pref);
      }
    }
  }

  if (o_rejects) process_o_rejects_and_deallocate_them (o_rejects);
}
Beispiel #11
0
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 (&current_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
}
Beispiel #12
0
void fill_in_new_instantiation_stuff (instantiation *inst,
                                      bool need_to_do_support_calculations) {
  condition *cond;
  preference *p;
  goal_stack_level level;

  production_add_ref (inst->prod);
  
  find_match_goal (inst);

  level = inst->match_goal_level;

  /* Note: since we'll never backtrace through instantiations at the top
     level, it might make sense to not increment the reference counts
     on the wmes and preferences here if the instantiation is at the top
     level.  As it stands now, we could gradually accumulate garbage at
     the top level if we have a never-ending sequence of production
     firings at the top level that chain on each other's results.  (E.g.,
     incrementing a counter on every decision cycle.)  I'm leaving it this
     way for now, because if we go to S-Support, we'll (I think) need to
     save these around (maybe). */

  /* KJC 6/00:  maintaining all the top level ref cts does have a big
     impact on memory pool usage and also performance (due to malloc).
	 (See tests done by Scott Wallace Fall 99.)	 Therefore added 
	 preprocessor macro so that by setting macro the top level ref cts are not 
	 incremented.  It's possible that in some systems, these ref cts may 
	 be desireable: they can be added by defining DO_TOP_LEVEL_REF_CTS
	 */

  for (cond=inst->top_of_instantiated_conditions; cond!=NIL; cond=cond->next)
    if (cond->type==POSITIVE_CONDITION) {
        #ifdef DO_TOP_LEVEL_REF_CTS
		wme_add_ref (cond->bt.wme);
        #else
		if (level > TOP_GOAL_LEVEL) wme_add_ref (cond->bt.wme);
        #endif
		/* --- if trace is for a lower level, find one for this level --- */
      if (cond->bt.trace) {
        if (cond->bt.trace->inst->match_goal_level > level) { 
          cond->bt.trace = find_clone_for_level (cond->bt.trace, level);
		} 
        #ifdef DO_TOP_LEVEL_REF_CTS
		if (cond->bt.trace) preference_add_ref (cond->bt.trace);
        #else
		if ((cond->bt.trace) && (level > TOP_GOAL_LEVEL)) 
			preference_add_ref (cond->bt.trace);
        #endif
      }
    }



  if (inst->match_goal) {
    for (p=inst->preferences_generated; p!=NIL; p=p->inst_next) {
      insert_at_head_of_dll (inst->match_goal->id.preferences_from_goal, p,
                             all_of_goal_next, all_of_goal_prev);
      p->on_goal_list = TRUE;
    }
  }
  inst->backtrace_number = 0;

  if ((current_agent(o_support_calculation_type) == 0) ||
	  (current_agent(o_support_calculation_type) == 3))  {
    /* --- do calc's the normal Soar 6 way --- */  
    if (need_to_do_support_calculations)
      calculate_support_for_instantiation_preferences (inst);
  } else if (current_agent(o_support_calculation_type) == 1) {
    if (need_to_do_support_calculations)
      calculate_support_for_instantiation_preferences (inst);
    /* --- do calc's both ways, warn on differences --- */
    if ((inst->prod->declared_support!=DECLARED_O_SUPPORT) &&
        (inst->prod->declared_support!=DECLARED_I_SUPPORT)) {
      /* --- At this point, we've done them the normal way.  To look for
             differences, save o-support flags on a list, then do Doug's
             calculations, then compare and restore saved flags. --- */
      list *saved_flags;
      preference *pref;
      bool difference_found;
      saved_flags = NIL;
      for (pref=inst->preferences_generated; pref!=NIL; pref=pref->inst_next)
        push ((pref->o_supported ? pref : NIL), saved_flags);
      saved_flags = destructively_reverse_list (saved_flags);
      dougs_calculate_support_for_instantiation_preferences (inst);
      difference_found = FALSE;
      for (pref=inst->preferences_generated; pref!=NIL; pref=pref->inst_next){
        cons *c; bool b;
        c = saved_flags; saved_flags = c->rest;
        b = (c->first ? TRUE : FALSE); free_cons (c);
        if (pref->o_supported != b) difference_found = TRUE;
        pref->o_supported = b;
      }
      if (difference_found) {
        print_with_symbols("\n*** O-support difference found in production %y",
                           inst->prod->name);
      }
    }
  }
  else {
    /* --- do calc's Doug's way --- */
    if ((inst->prod->declared_support!=DECLARED_O_SUPPORT) &&
        (inst->prod->declared_support!=DECLARED_I_SUPPORT)) {
      dougs_calculate_support_for_instantiation_preferences (inst);
    }
  }
}
Beispiel #13
0
void reorder_simplified_conditions (agent* thisAgent, 
									condition **top_of_conds,
                                    condition **bottom_of_conds,
                                    list *roots,
                                    tc_number bound_vars_tc_number,
                                    Bool reorder_nccs) {
  condition *remaining_conds;           /* header of dll */
  condition *first_cond, *last_cond;
  condition *cond, *next_cond;
  condition *min_cost_conds, *chosen;
  int64_t cost = 0;
  int64_t min_cost = 0;
  list *new_vars;

  remaining_conds = *top_of_conds;
  first_cond = NIL;
  last_cond = NIL;
  new_vars = NIL;
  
  /* repeat:  scan through remaining_conds
              rate each one
              if tie, call lookahead routine
              add min-cost item to conds
  */
  
  while (remaining_conds) {
    /* --- find min-cost set --- */
    min_cost_conds = NIL;
    min_cost = 0;
    for (cond=remaining_conds; cond!=NIL; cond=cond->next) {
      cost = cost_of_adding_condition (thisAgent, cond, bound_vars_tc_number, roots);
      if ((! min_cost_conds) || (cost < min_cost)) {
        min_cost = cost;
        min_cost_conds = cond;
        cond->reorder.next_min_cost = NIL;
      } else if (cost==min_cost) {
        cond->reorder.next_min_cost = min_cost_conds;
        min_cost_conds = cond;
      }
      /* if (min_cost <= 1) break;  This optimization needs to be removed,
                                    otherwise the tie set is not created.
                                    Without the tie set we can't check the
                                    canonical order. */
    }
    /* --- if min_cost==MAX_COST, print error message --- */
    if ((min_cost==MAX_COST) &&
        thisAgent->sysparams[PRINT_WARNINGS_SYSPARAM]) {
      print (thisAgent, "Warning:  in production %s,\n",
             thisAgent->name_of_production_being_reordered);
      print (thisAgent, "     The LHS conditions are not all connected.\n");
      /* BUGBUG I'm not sure whether this can ever happen. */

      // XML geneneration
      growable_string gs = make_blank_growable_string(thisAgent);
      add_to_growable_string(thisAgent, &gs, "Warning:  in production ");
      add_to_growable_string(thisAgent, &gs, thisAgent->name_of_production_being_reordered);
      add_to_growable_string(thisAgent, &gs, "\n     The LHS conditions are not all connected.");
      xml_generate_warning(thisAgent, text_of_growable_string(gs));
      free_growable_string(thisAgent, gs);

     }
    /* --- if more than one min-cost item, and cost>1, do lookahead --- */
    if ((min_cost > 1) && (min_cost_conds->reorder.next_min_cost)) {
      min_cost = MAX_COST + 1;
      for (cond=min_cost_conds, next_cond = cond->reorder.next_min_cost;
           cond!=NIL;
           cond=next_cond, next_cond=(cond?cond->reorder.next_min_cost:NIL)) {
        cost = find_lowest_cost_lookahead (thisAgent, remaining_conds, cond,
                                           bound_vars_tc_number, roots);
        if (cost < min_cost) {
          min_cost = cost;
          min_cost_conds = cond;
          cond->reorder.next_min_cost = NIL;
        } else {
/*******************************************************************
 These code segments find the condition in the tie set with the smallest
 value in the canonical order. This ensures that productions with the
 same set of conditions are ordered the same. Except if the variables
 are assigned differently.
*********************************************************************/
          if (cost == min_cost && cond->type == POSITIVE_CONDITION) {
              if (canonical_cond_greater(min_cost_conds,cond)) {
                min_cost = cost;
                min_cost_conds = cond;
                cond->reorder.next_min_cost = NIL;
              }
            }
        }
/*******************************************************************/

      }
    }
/*******************************************************************/
    if (min_cost == 1 && (min_cost_conds->reorder.next_min_cost)) {
      for (cond=min_cost_conds; cond!=NIL; cond=cond->reorder.next_min_cost) {
        if (cond->type == POSITIVE_CONDITION &&
          min_cost_conds->type == POSITIVE_CONDITION &&
          canonical_cond_greater(min_cost_conds,cond))
        {
          min_cost = cost;
          min_cost_conds = cond;
        }
       else if (cond->type != POSITIVE_CONDITION &&
                 min_cost_conds->type == POSITIVE_CONDITION)
        {
          min_cost = cost;
          min_cost_conds = cond;
        }
      }
    }
/*******************************************************************/

    /* --- install the first item in the min-cost set --- */
    chosen = min_cost_conds;
    remove_from_dll (remaining_conds, chosen, next, prev);
    if (!first_cond) first_cond = chosen;
    /* Note: args look weird on the next line, because we're really
       inserting the chosen item at the *end* of the list */
    insert_at_head_of_dll (last_cond, chosen, prev, next);

    /* --- if a conjunctive negation, recursively reorder its conditions --- */
    if ((chosen->type==CONJUNCTIVE_NEGATION_CONDITION) && reorder_nccs) {
      list *ncc_roots;
      ncc_roots = collect_root_variables (thisAgent, chosen->data.ncc.top,
                                          bound_vars_tc_number, TRUE);
      reorder_condition_list (thisAgent, &(chosen->data.ncc.top),
                              &(chosen->data.ncc.bottom),
                              ncc_roots,
                              bound_vars_tc_number,
                              reorder_nccs);
      free_list (thisAgent, ncc_roots);
    }

    /* --- update set of bound variables for newly added condition --- */
    add_bound_variables_in_condition (thisAgent, chosen, bound_vars_tc_number, &new_vars);
    
    /* --- if all roots are bound, set roots=NIL: don't need 'em anymore --- */
    if (roots) {
      cons *c;
      for (c=roots; c!=NIL; c=c->rest)
        if (static_cast<Symbol *>(c->first)->var.tc_num != bound_vars_tc_number)
          break;
      if (!c) roots=NIL;
    }

  } /* end of while (remaining_conds) */

  unmark_variables_and_free_list (thisAgent, new_vars);
  *top_of_conds = first_cond;
  *bottom_of_conds = last_cond;
}