Example #1
0
globle intBool EnvDeleteActivation(
    void *theEnv,
    void *theActivation)
{
    if (theActivation == NULL) RemoveAllActivations(theEnv);
    else RemoveActivation(theEnv,(struct activation *) theActivation,TRUE,TRUE);

    return(TRUE);
}
Example #2
0
globle void ClearRuleFromAgenda(
    void *theEnv,
    void *vTheRule)
{
    struct defrule *theRule = (struct defrule *) vTheRule;
    struct defrule *tempRule;
    struct activation *agendaPtr, *agendaNext;

    /*============================================*/
    /* Get a pointer to the agenda for the module */
    /* in which the rule is contained.            */
    /*============================================*/

    agendaPtr = ((struct defruleModule *) theRule->header.whichModule)->agenda;

    /*==============================================*/
    /* Loop through every activation on the agenda. */
    /*==============================================*/

    while (agendaPtr != NULL)
    {
        agendaNext = agendaPtr->next;

        /*========================================================*/
        /* Check each disjunct of the rule against the activation */
        /* to determine if the activation points to the rule. If  */
        /* it does, then remove the activation from the agenda.   */
        /*========================================================*/

        for (tempRule = theRule;
                tempRule != NULL;
                tempRule = tempRule->disjunct)
        {
            if (agendaPtr->theRule == tempRule)
            {
                RemoveActivation(theEnv,agendaPtr,TRUE,TRUE);
                break;
            }
        }

        agendaPtr = agendaNext;
    }
}
Example #3
0
globle void RemoveAllActivations(
    void *theEnv)
{
    struct activation *tempPtr, *theActivation;
    struct salienceGroup *theGroup, *tempGroup;

    theActivation = GetDefruleModuleItem(theEnv,NULL)->agenda;
    while (theActivation != NULL)
    {
        tempPtr = theActivation->next;
        RemoveActivation(theEnv,theActivation,TRUE,TRUE);
        theActivation = tempPtr;
    }

    theGroup = GetDefruleModuleItem(theEnv,NULL)->groupings;
    while (theGroup != NULL)
    {
        tempGroup = theGroup->next;
        rtn_struct(theEnv,salienceGroup,theGroup);
        theGroup = tempGroup;
    }
}
Example #4
0
static struct partialMatch *RemovePartialMatches(
  struct alphaMatch *theAlphaNode,
  struct partialMatch *listOfPMs,
  struct partialMatch **deleteHead,
  int position,
  struct partialMatch **returnLast)
  {
   struct partialMatch *head, *lastPM, *nextPM;
   struct partialMatch *lastDelete = NULL;

   /*====================================================*/
   /* Initialize pointers used for creating the new list */
   /* of partial matches and the list of partial matches */
   /* to be deleted.                                     */
   /*====================================================*/

   head = listOfPMs;
   lastPM = listOfPMs;
   *deleteHead = NULL;

   /*==========================================*/
   /* Loop through each of the partial matches */
   /* and determine if it needs to be deleted. */
   /*==========================================*/

   while (listOfPMs != NULL)
     {
      if ((listOfPMs->counterf == TRUE) && (position == (listOfPMs->bcount - 1)))
        {
         lastPM = listOfPMs;
         listOfPMs = listOfPMs->next;
        }

      /*=====================================================*/
      /* Otherwise, if the specified position in the partial */
      /* match contains the specified data entity, then      */
      /* remove the partial match from the list and add it   */
      /* to a deletion list.                                 */
      /*=====================================================*/

      else if (listOfPMs->binds[position].gm.theMatch == theAlphaNode)
        {
         /*===================================================*/
         /* If the partial match has an activation associated */
         /* with it, then return the activation.              */
         /*===================================================*/

         if ((listOfPMs->activationf) ?
             (listOfPMs->binds[listOfPMs->bcount].gm.theValue != NULL) : FALSE)
           { RemoveActivation((struct activation *) listOfPMs->binds[listOfPMs->bcount].gm.theValue,TRUE,TRUE); }

         /*==================================================*/
         /* If the partial match is at the head of the list  */
         /* of matches, then use the following deletion code */
         /* for the head of the list.                        */
         /*==================================================*/

         if (listOfPMs == head)
           {
            /*===================================*/
            /* Remember the new beginning of the */
            /* new list of partial matches.      */
            /*===================================*/

            nextPM = listOfPMs->next;

            /*=============================================*/
            /* Add the partial match to the deletion list. */
            /*=============================================*/

            if (*deleteHead == NULL)
              { *deleteHead = listOfPMs; }
            else
              { lastDelete->next = listOfPMs; }

            listOfPMs->next = NULL;
            lastDelete = listOfPMs;

            /*================================================*/
            /* Update the head and tail pointers for the new  */
            /* list of partial matches as well as the pointer */
            /* to the next partial match to be examined.      */
            /*================================================*/

            listOfPMs = nextPM;
            head = listOfPMs;
            lastPM = head;
           }

         /*======================================*/
         /* Otherwise, use the following code to */
         /* delete the partial match.            */
         /*======================================*/

         else
           {
            /*========================================*/
            /* Detach the partial match being deleted */
            /* from the new list of partial matches.  */
            /*========================================*/

            lastPM->next = listOfPMs->next;

            /*=============================================*/
            /* Add the partial match to the deletion list. */
            /*=============================================*/

            if (*deleteHead == NULL)
              { *deleteHead = listOfPMs; }
            else
              { lastDelete->next = listOfPMs; }

            listOfPMs->next = NULL;
            lastDelete = listOfPMs;

            /*=============================*/
            /* Move on to the next partial */
            /* match to be examined.       */
            /*=============================*/

            listOfPMs = lastPM->next;
           }
        }

      /*==============================================*/
      /* Otherwise, the partial match should be added */
      /* to the new list of partial matches.          */
      /*==============================================*/

      else
        {
         lastPM = listOfPMs;
         listOfPMs = listOfPMs->next;
        }
     }

   /*===============================================*/
   /* Return the last partial match in the new list */
   /* of partial matches via one of the function's  */
   /* parameters.                                   */
   /*===============================================*/

   *returnLast = lastPM;

   /*=====================================================*/
   /* Return the head of the new list of partial matches. */
   /*=====================================================*/

   return(head);
  }
Example #5
0
static void PNRDrive(
  struct joinNode *join,
  struct partialMatch *lhsBinds,
  struct partialMatch *rhsBinds)
  {
   struct joinNode *listOfJoins;

   /*==================================================*/
   /* If the partial match already has a partial match */
   /* in the alpha memory which prevents it from being */
   /* satisfied, then don't do anything.               */
   /*==================================================*/

   if (lhsBinds->counterf == TRUE) return;

   /*=================================================*/
   /* Set the counterf flag to indicate that an alpha */
   /* memory partial match is preventing the beta     */
   /* memory partial match from being satisfied.      */
   /*=================================================*/

   lhsBinds->counterf = TRUE;

   /*===================================================================*/
   /* If the partial match caused an activation, remove the activation. */
   /*===================================================================*/

   if ((lhsBinds->activationf) ?
       (lhsBinds->binds[lhsBinds->bcount].gm.theValue != NULL) : FALSE)
     { RemoveActivation((struct activation *) lhsBinds->binds[lhsBinds->bcount].gm.theValue,TRUE,TRUE); }

   /*===========================================================*/
   /* The counterf flag was FALSE. This means that a pointer to */
   /* the pseudo-fact matching the not CE is stored directly in */
   /* the partial match. Determine the ID of this pseudo-fact   */
   /* and remove all partial matches from descendent joins that */
   /* contain the ID.                                           */
   /*===========================================================*/

   if (join->joinFromTheRight) /* DR0834 */
     {
      RetractCheckDriveRetractions(lhsBinds->binds[lhsBinds->bcount - 1].gm.theMatch,
                                   (int) join->depth-1);
     }

   listOfJoins = join->nextLevel;
   if (listOfJoins != NULL)
     {
      if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == join)
        { NegEntryRetract(listOfJoins,lhsBinds,FALSE); }
      else while (listOfJoins != NULL)
        {

         PosEntryRetract(listOfJoins,
                         lhsBinds->binds[lhsBinds->bcount - 1].gm.theMatch,
                         lhsBinds,(int) join->depth-1,FALSE);
         listOfJoins = listOfJoins->rightDriveNode;
        }
     }

   /*=========================================================================*/
   /* Remove any logical dependency links associated with this partial match. */
   /*=========================================================================*/

#if LOGICAL_DEPENDENCIES
   if (lhsBinds->dependentsf) RemoveLogicalSupport(lhsBinds);
#endif

   /*========================================*/
   /* Put the pseudo-fact on a garbage list. */
   /*========================================*/

   lhsBinds->binds[lhsBinds->bcount - 1].gm.theMatch->next = GarbageAlphaMatches;
   GarbageAlphaMatches = lhsBinds->binds[lhsBinds->bcount - 1].gm.theMatch;

   /*========================================================*/
   /* Store the partial match from the alpha memory that is  */
   /* preventing the LHS partial match from being satisfied. */
   /*========================================================*/

   lhsBinds->binds[lhsBinds->bcount - 1].gm.theValue = (void *) rhsBinds;
  }
Example #6
0
globle long int EnvRun(
  void *theEnv,
  long int runLimit)
  {
   long int rulesFired = 0;
   DATA_OBJECT result;
   struct callFunctionItem *theRunFunction;
#if DEBUGGING_FUNCTIONS
   unsigned long maxActivations = 0, sumActivations = 0;
#if DEFTEMPLATE_CONSTRUCT
   unsigned long maxFacts = 0, sumFacts = 0;
#endif
#if OBJECT_SYSTEM
   unsigned long maxInstances = 0, sumInstances = 0;
#endif
   double endTime, startTime = 0.0;
   unsigned long tempValue;
#endif
   unsigned int i;
   struct patternEntity *theMatchingItem;
   struct partialMatch *theBasis;
   ACTIVATION *theActivation;
   char *ruleFiring;
#if PROFILING_FUNCTIONS
   struct profileFrameInfo profileFrame;
#endif

   /*=====================================================*/
   /* Make sure the run command is not already executing. */
   /*=====================================================*/

   if (EngineData(theEnv)->AlreadyRunning) return(0);
   EngineData(theEnv)->AlreadyRunning = TRUE;

   /*================================*/
   /* Set up statistics information. */
   /*================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
#if DEFTEMPLATE_CONSTRUCT
      maxFacts = GetNumberOfFacts(theEnv);
      sumFacts = maxFacts;
#endif
#if OBJECT_SYSTEM
      maxInstances = GetGlobalNumberOfInstances(theEnv);
      sumInstances = maxInstances;
#endif
      maxActivations = GetNumberOfActivations(theEnv);
      sumActivations = maxActivations;
      startTime = gentime();
     }
#endif

   /*=============================*/
   /* Set up execution variables. */
   /*=============================*/

   if (EvaluationData(theEnv)->CurrentEvaluationDepth == 0) SetHaltExecution(theEnv,FALSE);
   EngineData(theEnv)->HaltRules = FALSE;

   /*=====================================================*/
   /* Fire rules until the agenda is empty, the run limit */
   /* has been reached, or a rule execution error occurs. */
   /*=====================================================*/

   theActivation = NextActivationToFire(theEnv);
   while ((theActivation != NULL) &&
          (runLimit != 0) &&
          (EvaluationData(theEnv)->HaltExecution == FALSE) &&
          (EngineData(theEnv)->HaltRules == FALSE))
     {
      /*===========================================*/
      /* Detach the activation from the agenda and */
      /* determine which rule is firing.           */
      /*===========================================*/

      DetachActivation(theEnv,theActivation);
      ruleFiring = EnvGetActivationName(theEnv,theActivation);
      theBasis = (struct partialMatch *) GetActivationBasis(theActivation);
      EngineData(theEnv)->ExecutingRule = (struct defrule *) GetActivationRule(theActivation);

      /*=============================================*/
      /* Update the number of rules that have fired. */
      /*=============================================*/

      rulesFired++;
      if (runLimit > 0) { runLimit--; }

      /*==================================*/
      /* If rules are being watched, then */
      /* print an information message.    */
      /*==================================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->ExecutingRule->watchFiring)
        {
         char printSpace[60];

         sprintf(printSpace,"FIRE %4ld ",rulesFired);
         EnvPrintRouter(theEnv,WTRACE,printSpace);
         EnvPrintRouter(theEnv,WTRACE,ruleFiring);
         EnvPrintRouter(theEnv,WTRACE,": ");
         PrintPartialMatch(theEnv,WTRACE,theBasis);
         EnvPrintRouter(theEnv,WTRACE,"\n");
        }
#endif

      /*=================================================*/
      /* Remove the link between the activation and the  */
      /* completed match for the rule. Set the busy flag */
      /* for the completed match to TRUE (so the match   */
      /* upon which our RHS variables are dependent is   */
      /* not deleted while our rule is firing). Set up   */
      /* the global pointers to the completed match for  */
      /* routines which do variable extractions.         */
      /*=================================================*/

      theBasis->binds[theBasis->bcount].gm.theValue = NULL;
      theBasis->busy = TRUE;

      EngineData(theEnv)->GlobalLHSBinds = theBasis;
      EngineData(theEnv)->GlobalRHSBinds = NULL;

      /*===================================================================*/
      /* Increment the count for each of the facts/objects associated with */
      /* the rule activation so that the facts/objects cannot be deleted   */
      /* by garbage collection while the rule is executing.                */
      /*===================================================================*/

      for (i = 0; i < theBasis->bcount; i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->incrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*====================================================*/
      /* Execute the rule's right hand side actions. If the */
      /* rule has logical CEs, set up the pointer to the    */
      /* rules logical join so the assert command will      */
      /* attach the appropriate dependencies to the facts.  */
      /*====================================================*/

      EngineData(theEnv)->TheLogicalJoin = EngineData(theEnv)->ExecutingRule->logicalJoin;
      EvaluationData(theEnv)->CurrentEvaluationDepth++;
      SetEvaluationError(theEnv,FALSE);
      EngineData(theEnv)->ExecutingRule->executing = TRUE;

#if PROFILING_FUNCTIONS
      StartProfile(theEnv,&profileFrame,
                   &EngineData(theEnv)->ExecutingRule->header.usrData,
                   ProfileFunctionData(theEnv)->ProfileConstructs);
#endif

      EvaluateProcActions(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule,
                          EngineData(theEnv)->ExecutingRule->actions,EngineData(theEnv)->ExecutingRule->localVarCnt,
                          &result,NULL);

#if PROFILING_FUNCTIONS
      EndProfile(theEnv,&profileFrame);
#endif

      EngineData(theEnv)->ExecutingRule->executing = FALSE;
      SetEvaluationError(theEnv,FALSE);
      EvaluationData(theEnv)->CurrentEvaluationDepth--;
      EngineData(theEnv)->TheLogicalJoin = NULL;

      /*=====================================================*/
      /* If rule execution was halted, then print a message. */
      /*=====================================================*/

#if DEBUGGING_FUNCTIONS
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules && EngineData(theEnv)->ExecutingRule->watchFiring))
#else
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules))
#endif

        {
         PrintErrorID(theEnv,"PRCCODE",4,FALSE);
         EnvPrintRouter(theEnv,WERROR,"Execution halted during the actions of defrule ");
         EnvPrintRouter(theEnv,WERROR,ruleFiring);
         EnvPrintRouter(theEnv,WERROR,".\n");
        }

      /*===================================================================*/
      /* Decrement the count for each of the facts/objects associated with */
      /* the rule activation. If the last match for the activation         */
      /* is from a not CE, then we need to make sure that the last         */
      /* match is an actual match for the CE and not a counter.            */
      /*===================================================================*/

      theBasis->busy = FALSE;

      for (i = 0; i < (theBasis->bcount - 1); i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      i = (unsigned) (theBasis->bcount - 1);
      if (theBasis->counterf == FALSE)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*========================================*/
      /* Return the agenda node to free memory. */
      /*========================================*/

      RemoveActivation(theEnv,theActivation,FALSE,FALSE);

      /*======================================*/
      /* Get rid of partial matches discarded */
      /* while executing the rule's RHS.      */
      /*======================================*/

      FlushGarbagePartialMatches(theEnv);

      /*==================================*/
      /* Get rid of other garbage created */
      /* while executing the rule's RHS.  */
      /*==================================*/

      PeriodicCleanup(theEnv,FALSE,TRUE);

      /*==========================*/
      /* Keep up with statistics. */
      /*==========================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->WatchStatistics)
        {
#if DEFTEMPLATE_CONSTRUCT
         tempValue = GetNumberOfFacts(theEnv);
         if (tempValue > maxFacts) maxFacts = tempValue;
         sumFacts += tempValue;
#endif
#if OBJECT_SYSTEM
         tempValue = GetGlobalNumberOfInstances(theEnv);
         if (tempValue > maxInstances) maxInstances = tempValue;
         sumInstances += tempValue;
#endif
         tempValue = GetNumberOfActivations(theEnv);
         if (tempValue > maxActivations) maxActivations = tempValue;
         sumActivations += tempValue;
        }
#endif

      /*==================================*/
      /* Update saliences if appropriate. */
      /*==================================*/

      if (EnvGetSalienceEvaluation(theEnv) == EVERY_CYCLE) EnvRefreshAgenda(theEnv,NULL);

      /*========================================*/
      /* Execute the list of functions that are */
      /* to be called after each rule firing.   */
      /*========================================*/

      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }

      /*========================================*/
      /* If a return was issued on the RHS of a */
      /* rule, then remove *that* rule's module */
      /* from the focus stack                   */
      /*========================================*/

      if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
        { RemoveFocus(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule); }
      ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;

      /*========================================*/
      /* Determine the next activation to fire. */
      /*========================================*/

      theActivation = (struct activation *) NextActivationToFire(theEnv);

      /*==============================*/
      /* Check for a rule breakpoint. */
      /*==============================*/

      if (theActivation != NULL)
        {
         if (((struct defrule *) GetActivationRule(theActivation))->afterBreakpoint)
           {
            EngineData(theEnv)->HaltRules = TRUE;
            EnvPrintRouter(theEnv,WDIALOG,"Breaking on rule ");
            EnvPrintRouter(theEnv,WDIALOG,EnvGetActivationName(theEnv,theActivation));
            EnvPrintRouter(theEnv,WDIALOG,".\n");
           }
        }
     }

   /*=====================================================*/
   /* Make sure run functions are executed at least once. */
   /*=====================================================*/

   if (rulesFired == 0)
     {
      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }
     }

   /*======================================================*/
   /* If rule execution was halted because the rule firing */
   /* limit was reached, then print a message.             */
   /*======================================================*/

   if (runLimit == rulesFired)
     { EnvPrintRouter(theEnv,WDIALOG,"rule firing limit reached\n"); }

   /*==============================*/
   /* Restore execution variables. */
   /*==============================*/

   EngineData(theEnv)->ExecutingRule = NULL;
   EngineData(theEnv)->HaltRules = FALSE;

   /*=================================================*/
   /* Print out statistics if they are being watched. */
   /*=================================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
      char printSpace[60];

      endTime = gentime();

      PrintLongInteger(theEnv,WDIALOG,rulesFired);
      EnvPrintRouter(theEnv,WDIALOG," rules fired");

#if (! GENERIC)
      if (startTime != endTime)
        {
         EnvPrintRouter(theEnv,WDIALOG,"        Run time is ");
         PrintFloat(theEnv,WDIALOG,endTime - startTime);
         EnvPrintRouter(theEnv,WDIALOG," seconds.\n");
         PrintFloat(theEnv,WDIALOG,(double) rulesFired / (endTime - startTime));
         EnvPrintRouter(theEnv,WDIALOG," rules per second.\n");
        }
      else
        { EnvPrintRouter(theEnv,WDIALOG,"\n"); }
#endif

#if DEFTEMPLATE_CONSTRUCT
      sprintf(printSpace,"%ld mean number of facts (%ld maximum).\n",
                          (long) (((double) sumFacts / (rulesFired + 1)) + 0.5),
                          maxFacts);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

#if OBJECT_SYSTEM
      sprintf(printSpace,"%ld mean number of instances (%ld maximum).\n",
                          (long) (((double) sumInstances / (rulesFired + 1)) + 0.5),
                          maxInstances);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

      sprintf(printSpace,"%ld mean number of activations (%ld maximum).\n",
                          (long) (((double) sumActivations / (rulesFired + 1)) + 0.5),
                          maxActivations);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
     }
#endif

   /*==========================================*/
   /* The current module should be the current */
   /* focus when the run finishes.             */
   /*==========================================*/

   if (EngineData(theEnv)->CurrentFocus != NULL)
     {
      if (EngineData(theEnv)->CurrentFocus->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv)))
        { EnvSetCurrentModule(theEnv,(void *) EngineData(theEnv)->CurrentFocus->theModule); }
     }

   /*===================================*/
   /* Return the number of rules fired. */
   /*===================================*/

   EngineData(theEnv)->AlreadyRunning = FALSE;
   return(rulesFired);
  }