Exemplo n.º 1
0
static void CheckForPrimableJoins(
  void *theEnv,
  struct defrule *tempRule)
  {
   struct joinNode *joinPtr;
   struct partialMatch *theList;
   
   /*========================================*/
   /* Loop through each of the rule's joins. */
   /*========================================*/

   for (joinPtr = tempRule->lastJoin;
        joinPtr != NULL;
        joinPtr = GetPreviousJoin(joinPtr))
     {
      /*===============================*/
      /* Update the join if necessary. */
      /*===============================*/

      if ((joinPtr->initialize) && (! joinPtr->marked)) /* GDR 6.05 */
        {
         if (joinPtr->firstJoin == TRUE)
           {
            if (((struct patternNodeHeader *) GetPatternForJoin(joinPtr))->initialize == FALSE)
              {
               PrimeJoin(theEnv,joinPtr);
               joinPtr->marked = TRUE; /* GDR 6.05 */
              }
           }
         else if (joinPtr->lastLevel->initialize == FALSE)
           {
            PrimeJoin(theEnv,joinPtr);
            joinPtr->marked = TRUE; /* GDR 6.05 */
           }
        }

      /*================================================================*/
      /* If the join is associated with a rule activation (i.e. partial */
      /* matches that reach this join cause an activation to be placed  */
      /* on the agenda), then add activations to the agenda for the     */
      /* rule being  incrementally reset.                               */
      /*================================================================*/

      else if (joinPtr->ruleToActivate == tempRule)
        {
         for (theList = joinPtr->beta;
              theList != NULL;
              theList = theList->next)
           { AddActivation(theEnv,tempRule,theList); }
        }
     }
  }
Exemplo n.º 2
0
globle void PNLDrive(
  void *theEnv,
  struct joinNode *join,
  struct partialMatch *binds)
  {
   struct joinNode *listOfJoins;
   struct alphaMatch *tempAlpha;

    /*=======================================================*/
    /* Create a pseudo-fact representing the facts which did */
    /* not match the not CE associated with this join.       */
    /*=======================================================*/

    tempAlpha = get_struct(theEnv,alphaMatch);
    tempAlpha->next = NULL;
    tempAlpha->matchingItem = NULL;
    tempAlpha->markers = NULL;

    /*===============================================*/
    /* Store the pointer to the pseudo-fact directly */
    /* in the beta memory partial match.             */
    /*===============================================*/

    binds->counterf = FALSE;
    binds->binds[binds->bcount - 1].gm.theMatch = tempAlpha;

   /*====================================================*/
   /* Activate the rule satisfied by this partial match. */
   /*====================================================*/

   if (join->ruleToActivate != NULL) AddActivation(theEnv,join->ruleToActivate,binds);

    /*========================================================*/
    /* Send the merged partial match to all descendent joins. */
    /*========================================================*/

    listOfJoins = join->nextLevel;
    if (listOfJoins != NULL)
      {
       if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == join)
         { NetworkAssert(theEnv,binds,listOfJoins,RHS); }
       else while (listOfJoins != NULL)
         {
          NetworkAssert(theEnv,binds,listOfJoins,LHS);
          listOfJoins = listOfJoins->rightDriveNode;
         }
      }
   }
Exemplo n.º 3
0
static void PPDrive(
  void *theEnv,
  struct partialMatch *lhsBinds,
  struct partialMatch *rhsBinds,
  struct joinNode *join)
  {
   struct partialMatch *linker;
   struct joinNode *listOfJoins;
   
   /*==================================================*/
   /* Merge the alpha and beta memory partial matches. */
   /*==================================================*/

   linker = MergePartialMatches(theEnv,lhsBinds,rhsBinds,
                                (join->ruleToActivate == NULL) ? 0 : 1,
                                (int) join->logicalJoin);

   /*=======================================================*/
   /* Add the partial match to the beta memory of the join. */
   /*=======================================================*/

   linker->next = join->beta;
   join->beta = linker;

   /*====================================================*/
   /* Activate the rule satisfied by this partial match. */
   /*====================================================*/

   if (join->ruleToActivate != NULL) AddActivation(theEnv,join->ruleToActivate,linker);

   /*================================================*/
   /* Send the new partial match to all child joins. */
   /*================================================*/

   listOfJoins = join->nextLevel;
   if (listOfJoins != NULL)
     {
      if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == join)
        { NetworkAssert(theEnv,linker,listOfJoins,RHS); }
      else while (listOfJoins != NULL)
        {
         NetworkAssert(theEnv,linker,listOfJoins,LHS);
         listOfJoins = listOfJoins->rightDriveNode;
        }
     }

   return;
  }
Exemplo n.º 4
0
globle intBool EnvRefresh(
    void *theEnv,
    void *theRule)
{
    struct defrule *rulePtr;
    struct partialMatch *listOfMatches;
    unsigned long b;

    /*====================================*/
    /* Refresh each disjunct of the rule. */
    /*====================================*/

    for (rulePtr = (struct defrule *) theRule;
            rulePtr != NULL;
            rulePtr = rulePtr->disjunct)
    {
        /*================================*/
        /* Check each partial match that  */
        /* satisfies the LHS of the rule. */
        /*================================*/

        for (b = 0; b < rulePtr->lastJoin->leftMemory->size; b++)
        {
            for (listOfMatches = rulePtr->lastJoin->leftMemory->beta[b];
                    listOfMatches != NULL;
                    listOfMatches = listOfMatches->nextInMemory)
            {
                /*=======================================================*/
                /* If the partial match is associated with an activation */
                /* (which it should always be), then place a new         */
                /* activation on the agenda if this partial matchdoesn't */
                /* have an activation associated with it.                */
                /*=======================================================*/

                if (((struct joinNode *) listOfMatches->owner)->ruleToActivate != NULL)
                {
                    if (listOfMatches->marker == NULL)
                    {
                        AddActivation(theEnv,rulePtr,listOfMatches);
                    }
                }
            }
        }
    }

    return(TRUE);
}
Exemplo n.º 5
0
void NegEntryRetract(
  struct joinNode *theJoin,
  struct partialMatch *theMatch,
  int duringRetract)
  {
   struct partialMatch *theLHS;
   int result;
   struct rdriveinfo *tempDR;
   struct alphaMatch *tempAlpha;
   struct joinNode *listOfJoins;

   /*===============================================*/
   /* Loop through all LHS partial matches checking */
   /* for sets that satisfied the join expression.  */
   /*===============================================*/

   for (theLHS = theJoin->beta; theLHS != NULL; theLHS = theLHS->next)
     {
      /*===========================================================*/
      /* Don't bother checking partial matches that are satisfied. */
      /* We're looking for joins from which the removal of a       */
      /* partial match would satisfy the join.                     */
      /*===========================================================*/

      if (theLHS->counterf == FALSE) continue;

      /*==================================================*/
      /* If the partial match being removed isn't the one */
      /* preventing the LHS partial match from being      */
      /* satisifed, then don't bother processing it.      */
      /*==================================================*/

      if (theLHS->binds[theLHS->bcount - 1].gm.theValue != (void *) theMatch) continue;

      /*======================================================*/
      /* Try to find another RHS partial match which prevents */
      /* the LHS partial match from being satisifed.          */
      /*======================================================*/

      theLHS->binds[theLHS->bcount - 1].gm.theValue = NULL;
      result = FindNextConflictingAlphaMatch(theLHS,theMatch->next,theJoin);

      /*=========================================================*/
      /* If the LHS partial match now has no RHS partial matches */
      /* that conflict with it, then it satisfies the conditions */
      /* of the RHS not CE. Create a partial match and send it   */
      /* to the joins below.                                     */
      /*=========================================================*/

      if (result == FALSE)
        {
         /*===============================*/
         /* Create the new partial match. */
         /*===============================*/

         theLHS->counterf = FALSE;
         tempAlpha = get_struct(alphaMatch);
         tempAlpha->next = NULL;
         tempAlpha->matchingItem = NULL;
         tempAlpha->markers = NULL;
         theLHS->binds[theLHS->bcount - 1].gm.theMatch = tempAlpha;

         /*==============================================*/
         /* If partial matches from this join correspond */
         /* to a rule activation, then add an activation */
         /* to the agenda.                               */
         /*==============================================*/

         if (theJoin->ruleToActivate != NULL)
           { AddActivation(theJoin->ruleToActivate,theLHS); }

         /*=======================================================*/
         /* Send the partial match to the list of joins following */
         /* this join. If we're in the middle of a retract, add   */
         /* the partial match to the list of join activities that */
         /* need to be processed later. If we're doing an assert, */
         /* then the join activity can be processed immediately.  */
         /*=======================================================*/

         listOfJoins = theJoin->nextLevel;
         if (listOfJoins != NULL)
           {
            if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == theJoin)
              { NetworkAssert(theLHS,listOfJoins,RHS); }
            else
              {
               if (duringRetract)
                 {
                  tempDR = get_struct(rdriveinfo);
                  tempDR->link = theLHS;
                  tempDR->jlist = theJoin->nextLevel;
                  tempDR->next = DriveRetractionList;
                  DriveRetractionList = tempDR;
                 }
               else while (listOfJoins != NULL)
                 {
                  NetworkAssert(theLHS,listOfJoins,LHS);
                  listOfJoins = listOfJoins->rightDriveNode;
                 }
              }
           }
        }
     }
  }
Exemplo n.º 6
0
static void EmptyDrive(
  struct joinNode *join,
  struct partialMatch *rhsBinds)
  {
   struct partialMatch *linker;
   struct joinNode *listOfJoins;
   int joinExpr;

   /*======================================================*/
   /* Determine if the alpha memory partial match satifies */
   /* the join expression. If it doesn't then no further   */
   /* action is taken.                                     */
   /*======================================================*/

   if (join->networkTest != NULL)
     {
      joinExpr = EvaluateJoinExpression(join->networkTest,NULL,rhsBinds,join);
      EvaluationError = FALSE;
      if (joinExpr == FALSE) return;
     }

   /*===========================================================*/
   /* The first join of a rule cannot be connected to a NOT CE. */
   /*===========================================================*/

   if (join->patternIsNegated == TRUE)
     {
      SystemError("DRIVE",2);
      ExitRouter(EXIT_FAILURE);
     }

   /*=========================================================*/
   /* If the join's RHS entry is associated with a pattern CE */
   /* (positive entry), then copy the alpha memory partial    */
   /* match and send it to all child joins.                   */
   /*=========================================================*/

   linker = CopyPartialMatch(rhsBinds,
                             (join->ruleToActivate == NULL) ? 0 : 1,
                             (int) join->logicalJoin);

   /*=======================================================*/
   /* Add the partial match to the beta memory of the join. */
   /*=======================================================*/

   linker->next = join->beta;
   join->beta = linker;

   /*====================================================*/
   /* Activate the rule satisfied by this partial match. */
   /*====================================================*/

   if (join->ruleToActivate != NULL) AddActivation(join->ruleToActivate,linker);

   /*============================================*/
   /* Send the partial match to all child joins. */
   /*============================================*/

   listOfJoins = join->nextLevel;
   while (listOfJoins != NULL)
     {
      NetworkAssert(linker,listOfJoins,LHS);
      listOfJoins = listOfJoins->rightDriveNode;
     }
  }
Exemplo n.º 7
0
globle void NetworkAssertLeft(
  void *theEnv,
  struct partialMatch *lhsBinds,
  struct joinNode *join)
  {
   struct partialMatch *rhsBinds;
   int exprResult, restore = FALSE;
   unsigned long entryHashValue;
   struct partialMatch *oldLHSBinds = NULL;
   struct partialMatch *oldRHSBinds = NULL;
   struct joinNode *oldJoin = NULL;

   /*=========================================================*/
   /* If an incremental reset is being performed and the join */
   /* is not part of the network to be reset, then return.    */
   /*=========================================================*/

#if (! BLOAD_ONLY) && (! RUN_TIME)
   if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == FALSE)) return;
#endif

   /*===================================*/
   /* The only action for the last join */
   /* of a rule is to activate it.      */
   /*===================================*/
   
   if (join->ruleToActivate != NULL)
     {
      AddActivation(theEnv,join->ruleToActivate,lhsBinds);
      return;
     }

   /*==================================================*/
   /* Initialize some variables used to indicate which */
   /* side is being compared to the new partial match. */
   /*==================================================*/

   entryHashValue = lhsBinds->hashValue;
   if (join->joinFromTheRight)
     { rhsBinds = GetRightBetaMemory(join,entryHashValue); }
   else
     { rhsBinds = GetAlphaMemory(theEnv,(struct patternNodeHeader *) join->rightSideEntryStructure,entryHashValue); }
       
#if DEVELOPER
   if (rhsBinds != NULL)
     { EngineData(theEnv)->leftToRightLoops++; }
#endif
   
   /*====================================*/
   /* Set up the evaluation environment. */
   /*====================================*/
   
   if ((rhsBinds != NULL) || (join->secondaryNetworkTest != NULL))
     {
      oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
      oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
      oldJoin = EngineData(theEnv)->GlobalJoin;
      EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
      EngineData(theEnv)->GlobalJoin = join;
      restore = TRUE;
     }
  
   /*===================================================*/
   /* Compare each set of binds on the opposite side of */
   /* the join with the set of binds that entered this  */
   /* join. If the binds don't mismatch, then perform   */
   /* the appropriate action for the logic of the join. */
   /*===================================================*/

   while (rhsBinds != NULL)
     {
      join->memoryCompares++;

      /*===================================================*/
      /* If the join has no expression associated with it, */
      /* then the new partial match derived from the LHS   */
      /* and RHS partial matches is valid.                 */
      /*===================================================*/

      if (join->networkTest == NULL)
        { exprResult = TRUE; }

      /*=========================================================*/
      /* If the join has an expression associated with it, then  */
      /* evaluate the expression to determine if the new partial */
      /* match derived from the LHS and RHS partial matches is   */
      /* valid (i.e. variable bindings are consistent and        */
      /* predicate expressions evaluate to TRUE).                */
      /*=========================================================*/

      else
        {
#if DEVELOPER
         EngineData(theEnv)->leftToRightComparisons++;
#endif
         EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
         
         exprResult = EvaluateJoinExpression(theEnv,join->networkTest,join);
         if (EvaluationData(theEnv)->EvaluationError)
           {
            if (join->patternIsNegated) exprResult = TRUE;
            SetEvaluationError(theEnv,FALSE);
           }

#if DEVELOPER
         if (exprResult)
           { EngineData(theEnv)->leftToRightSucceeds++; }
#endif
        }
        
      // Bug Fix - Need to evaluate secondary network test for exists CE 0881

      if ((join->secondaryNetworkTest != NULL) && exprResult && join->patternIsExists)
        {
         EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
         exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
         if (EvaluationData(theEnv)->EvaluationError)
           { SetEvaluationError(theEnv,FALSE); }
        }

      /*====================================================*/
      /* If the join expression evaluated to TRUE (i.e.     */
      /* there were no conflicts between variable bindings, */
      /* all tests were satisfied, etc.), then perform the  */
      /* appropriate action given the logic of this join.   */
      /*====================================================*/

      if (exprResult != FALSE)
        {
         /*==============================================*/
         /* Use the PPDrive routine when the join isn't  */
         /* associated with a not CE and it doesn't have */
         /* a join from the right.                       */
         /*==============================================*/

         if ((join->patternIsNegated == FALSE) &&
             (join->patternIsExists == FALSE) &&
             (join->joinFromTheRight == FALSE))
           { PPDrive(theEnv,lhsBinds,rhsBinds,join); }

         /*==================================================*/
         /* At most, one partial match will be generated for */
         /* a match from the right memory of an exists CE.   */
         /*==================================================*/
         
         else if (join->patternIsExists)
           { 
            AddBlockedLink(lhsBinds,rhsBinds);
            PPDrive(theEnv,lhsBinds,NULL,join);
            EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
            EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
            EngineData(theEnv)->GlobalJoin = oldJoin;
            return;
           }
           
         /*===========================================================*/
         /* If the new partial match entered from the LHS of the join */
         /* and the join is either associated with a not CE or the    */
         /* join has a join from the right, then mark the LHS partial */
         /* match indicating that there is a RHS partial match        */
         /* preventing this join from being satisfied. Once this has  */
         /* happened, the other RHS partial matches don't have to be  */
         /* tested since it only takes one partial match to prevent   */
         /* the LHS from being satisfied.                             */
         /*===========================================================*/

         else
           {
            AddBlockedLink(lhsBinds,rhsBinds);
            break;
           }
        }

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

      rhsBinds = rhsBinds->nextInMemory;
     }

   /*==================================================================*/
   /* If a join with an associated not CE or join from the right was   */
   /* entered from the LHS side of the join, and the join expression   */
   /* failed for all sets of matches for the new bindings on the LHS   */
   /* side (there was no RHS partial match preventing the LHS partial  */
   /* match from being satisfied), then the LHS partial match appended */
   /* with an pseudo-fact that represents the instance of the not      */
   /* pattern or join from the right that was satisfied should be sent */
   /* to the joins below this join.                                    */
   /*==================================================================*/

   if ((join->patternIsNegated || join->joinFromTheRight) && 
       (! join->patternIsExists) &&
       (lhsBinds->marker == NULL))
     {
      if (join->secondaryNetworkTest != NULL)
        {
         EngineData(theEnv)->GlobalRHSBinds = NULL;
         
         exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
         if (EvaluationData(theEnv)->EvaluationError)
           { SetEvaluationError(theEnv,FALSE); }
           
         if (exprResult)
            { PPDrive(theEnv,lhsBinds,NULL,join); }
		}
      else
        { PPDrive(theEnv,lhsBinds,NULL,join); } 
     }

   /*=========================================*/
   /* Restore the old evaluation environment. */
   /*=========================================*/

   if (restore)
     {
      EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
      EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
      EngineData(theEnv)->GlobalJoin = oldJoin;
     }

   return;
  }