📄 reteutil.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.30 10/19/06 */ /* */ /* RETE UTILITY MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides a set of utility functions useful to *//* other modules. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//* 6.24: Removed INCREMENTAL_RESET compilation flag. *//* *//* Rule with exists CE has incorrect activation. *//* DR0867 *//* *//* 6.30: Added support for hashed alpha memories. *//* *//* Removed pseudo-facts used in not CEs. *//* *//*************************************************************/#define _RETEUTIL_SOURCE_#include <stdio.h>#define _STDIO_INCLUDED_#include "setup.h"#if DEFRULE_CONSTRUCT#include "drive.h"#include "engine.h"#include "envrnmnt.h"#include "incrrset.h"#include "match.h"#include "memalloc.h"#include "moduldef.h"#include "pattern.h"#include "retract.h"#include "router.h"#include "reteutil.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static void TraceErrorToRuleDriver(void *,struct joinNode *,char *,int,int); static struct alphaMemoryHash *FindAlphaMemory(void *,struct patternNodeHeader *,unsigned long); static unsigned long AlphaMemoryHashValue(struct patternNodeHeader *,unsigned long); static void UnlinkAlphaMemory(void *,struct patternNodeHeader *,struct alphaMemoryHash *); static void UnlinkAlphaMemoryBucketSiblings(void *,struct alphaMemoryHash *); static void InitializePMLinks(struct partialMatch *); static void UnlinkBetaPartialMatchfromAlphaAndBetaLineage(struct partialMatch *); static int CountPriorPatterns(struct joinNode *); static void ResizeBetaMemory(void *,struct betaMemory *); static void ResetBetaMemory(void *,struct betaMemory *);#if (CONSTRUCT_COMPILER || BLOAD_AND_BSAVE) && (! RUN_TIME) static void TagNetworkTraverseJoins(void *,long int *,long int *,struct joinNode *);#endif /***********************************************************//* PrintPartialMatch: Prints out the list of fact indices *//* and/or instance names associated with a partial match *//* or rule instantiation. *//***********************************************************/globle void PrintPartialMatch( void *theEnv, char *logicalName, struct partialMatch *list) { struct patternEntity *matchingItem; unsigned short i; for (i = 0; i < list->bcount;) { if ((get_nth_pm_match(list,i) != NULL) && (get_nth_pm_match(list,i)->matchingItem != NULL)) { matchingItem = get_nth_pm_match(list,i)->matchingItem; (*matchingItem->theInfo->base.shortPrintFunction)(theEnv,logicalName,matchingItem); } else { EnvPrintRouter(theEnv,logicalName,"*"); } i++; if (i < list->bcount) EnvPrintRouter(theEnv,logicalName,","); } }/**********************************************//* CopyPartialMatch: Copies a partial match. *//**********************************************/globle struct partialMatch *CopyPartialMatch( void *theEnv, struct partialMatch *list) { struct partialMatch *linker; unsigned short i; linker = get_var_struct(theEnv,partialMatch,sizeof(struct genericMatch) * (list->bcount - 1)); InitializePMLinks(linker); linker->betaMemory = TRUE; linker->busy = FALSE; linker->rhsMemory = FALSE; linker->bcount = list->bcount; linker->hashValue = 0; for (i = 0; i < linker->bcount; i++) linker->binds[i] = list->binds[i]; return(linker); }/**********************************************//* CreateEmptyPartialMatch: *//**********************************************/globle struct partialMatch *CreateEmptyPartialMatch( void *theEnv) { struct partialMatch *linker; short int i = 0; linker = get_struct(theEnv,partialMatch); InitializePMLinks(linker); linker->betaMemory = TRUE; linker->busy = FALSE; linker->rhsMemory = FALSE; linker->bcount = 1; linker->hashValue = 0; linker->binds[i++].gm.theValue = NULL; return(linker); }/****************************************************//* InitializePMLinks: *//****************************************************/static void InitializePMLinks( struct partialMatch *theMatch) { theMatch->nextInMemory = NULL; theMatch->prevInMemory = NULL; theMatch->nextRightChild = NULL; theMatch->prevRightChild = NULL; theMatch->nextLeftChild = NULL; theMatch->prevLeftChild = NULL; theMatch->children = NULL; theMatch->rightParent = NULL; theMatch->leftParent = NULL; theMatch->blockList = NULL; theMatch->nextBlocked = NULL; theMatch->prevBlocked = NULL; theMatch->marker = NULL; theMatch->dependents = NULL; } /***********************************************************//* UpdateBetaPMLinks: . *//***********************************************************/globle void UpdateBetaPMLinks( void *theEnv, struct partialMatch *thePM, struct partialMatch *lhsBinds, struct partialMatch *rhsBinds, struct joinNode *join, unsigned long hashValue, int side) { unsigned long betaLocation; struct betaMemory *theMemory; if (side == LHS) { theMemory = join->leftMemory; thePM->rhsMemory = FALSE; } else { theMemory = join->rightMemory; thePM->rhsMemory = TRUE; } thePM->hashValue = hashValue; /*================================*/ /* Update the node's linked list. */ /*================================*/ betaLocation = hashValue % theMemory->size; if (side == LHS) { thePM->nextInMemory = theMemory->beta[betaLocation]; if (theMemory->beta[betaLocation] != NULL) { theMemory->beta[betaLocation]->prevInMemory = thePM; } theMemory->beta[betaLocation] = thePM; } else { if (theMemory->last[betaLocation] != NULL) { theMemory->last[betaLocation]->nextInMemory = thePM; thePM->prevInMemory = theMemory->last[betaLocation]; } else { theMemory->beta[betaLocation] = thePM; } theMemory->last[betaLocation] = thePM; } theMemory->count++; join->memoryAdds++; thePM->owner = join; /*======================================*/ /* Update the alpha memory linked list. */ /*======================================*/ if (rhsBinds != NULL) { thePM->nextRightChild = rhsBinds->children; if (rhsBinds->children != NULL) { rhsBinds->children->prevRightChild = thePM; } rhsBinds->children = thePM; thePM->rightParent = rhsBinds; } /*=====================================*/ /* Update the beta memory linked list. */ /*=====================================*/ if (lhsBinds != NULL) { thePM->nextLeftChild = lhsBinds->children; if (lhsBinds->children != NULL) { lhsBinds->children->prevLeftChild = thePM; } lhsBinds->children = thePM; thePM->leftParent = lhsBinds; } if (! DefruleData(theEnv)->BetaMemoryResizingFlag) { return; } if ((theMemory->size > 1) && (theMemory->count > (theMemory->size * 11))) { ResizeBetaMemory(theEnv,theMemory); } }/**********************************************************//* AddBlockedLink: Adds a link between a partial match in *//* the beta memory of a join (with a negated RHS) and a *//* partial match in its right memory that prevents the *//* partial match from being satisfied and propagated to *//* the next join in the rule. *//**********************************************************/globle void AddBlockedLink( struct partialMatch *thePM, struct partialMatch *rhsBinds) { thePM->marker = rhsBinds; thePM->nextBlocked = rhsBinds->blockList; if (rhsBinds->blockList != NULL) { rhsBinds->blockList->prevBlocked = thePM; } rhsBinds->blockList = thePM; }/*************************************************************//* RemoveBlockedLink: Removes a link between a partial match *//* in the beta memory of a join (with a negated RHS) and a *//* partial match in its right memory that prevents the *//* partial match from being satisfied and propagated to *//* the next join in the rule. *//*************************************************************/globle void RemoveBlockedLink( struct partialMatch *thePM) { struct partialMatch *blocker; if (thePM->prevBlocked == NULL) { blocker = (struct partialMatch *) thePM->marker; blocker->blockList = thePM->nextBlocked; } else { thePM->prevBlocked->nextBlocked = thePM->nextBlocked; } if (thePM->nextBlocked != NULL) { thePM->nextBlocked->prevBlocked = thePM->prevBlocked; } thePM->nextBlocked = NULL; thePM->prevBlocked = NULL; thePM->marker = NULL; } /***********************************************************//* UnlinkBetaPMFromNodeAndLineage: . *//***********************************************************/globle void UnlinkBetaPMFromNodeAndLineage( void *theEnv, struct joinNode *join, struct partialMatch *thePM, int side) { unsigned long betaLocation; struct betaMemory *theMemory; if (side == LHS) { theMemory = join->leftMemory; } else { theMemory = join->rightMemory; } /*=============================================*/ /* Update the nextInMemory/prevInMemory links. */ /*=============================================*/ theMemory->count--; join->memoryDeletes++; betaLocation = thePM->hashValue % theMemory->size; if ((side == RHS) && (theMemory->last[betaLocation] == thePM)) { theMemory->last[betaLocation] = thePM->prevInMemory; } if (thePM->prevInMemory == NULL) { betaLocation = thePM->hashValue % theMemory->size; theMemory->beta[betaLocation] = thePM->nextInMemory; } else { thePM->prevInMemory->nextInMemory = thePM->nextInMemory; } if (thePM->nextInMemory != NULL) { thePM->nextInMemory->prevInMemory = thePM->prevInMemory; } thePM->nextInMemory = NULL; thePM->prevInMemory = NULL; UnlinkBetaPartialMatchfromAlphaAndBetaLineage(thePM); if (! DefruleData(theEnv)->BetaMemoryResizingFlag) { return; } if ((theMemory->count == 0) && (theMemory->size > 1)) { ResetBetaMemory(theEnv,theMemory); } } /***********************************************************//* UnlinkNonLeftLineage: . *//***********************************************************/globle void UnlinkNonLeftLineage( void *theEnv, struct joinNode *join, struct partialMatch *thePM, int side) { unsigned long betaLocation; struct betaMemory *theMemory; struct partialMatch *tempPM; if (side == LHS) { theMemory = join->leftMemory; } else { theMemory = join->rightMemory; } /*=============================================*/ /* Update the nextInMemory/prevInMemory links. */ /*=============================================*/ theMemory->count--; join->memoryDeletes++; betaLocation = thePM->hashValue % theMemory->size; if ((side == RHS) && (theMemory->last[betaLocation] == thePM)) { theMemory->last[betaLocation] = thePM->prevInMemory; } if (thePM->prevInMemory == NULL) { betaLocation = thePM->hashValue % theMemory->size; theMemory->beta[betaLocation] = thePM->nextInMemory; } else { thePM->prevInMemory->nextInMemory = thePM->nextInMemory; } if (thePM->nextInMemory != NULL) { thePM->nextInMemory->prevInMemory = thePM->prevInMemory; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -