?? engine.c
字號:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.30 10/19/06 */ /* */ /* ENGINE MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides functionality primarily associated with *//* the run and focus commands. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* Bebe Ly *//* Brian L. Donnell *//* *//* Revision History: *//* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 *//* *//* Corrected compilation errors for files *//* generated by constructs-to-c. DR0861 *//* *//* 6.24: Removed DYNAMIC_SALIENCE, INCREMENTAL_RESET, *//* and LOGICAL_DEPENDENCIES compilation flags. *//* *//* Renamed BOOLEAN macro type to intBool. *//* *//* Added access functions to the HaltRules flag. *//* *//* Added EnvGetNextFocus, EnvGetFocusChanged, and *//* EnvSetFocusChanged functions. *//* *//* 6.30: Added additional developer statistics to help *//* analyze join network performance. *//* *//* Removed pseudo-facts used in not CEs. *//* *//*************************************************************/#define _ENGINE_SOURCE_#include <stdio.h>#define _STDIO_INCLUDED_#include <string.h>#include "setup.h"#if DEFRULE_CONSTRUCT#include "agenda.h"#include "argacces.h"#include "constant.h"#include "envrnmnt.h"#include "factmngr.h"#include "inscom.h"#include "memalloc.h"#include "modulutl.h"#include "prccode.h"#include "prcdrfun.h"#include "proflfun.h"#include "reteutil.h"#include "retract.h"#include "router.h"#include "ruledlt.h"#include "sysdep.h"#include "utility.h"#include "watch.h"#include "engine.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static struct activation *NextActivationToFire(void *); static struct defmodule *RemoveFocus(void *,struct defmodule *); static void DeallocateEngineData(void *);/*****************************************************************************//* InitializeEngine: Initializes the activations and statistics watch items. *//*****************************************************************************/globle void InitializeEngine( void *theEnv) { AllocateEnvironmentData(theEnv,ENGINE_DATA,sizeof(struct engineData),DeallocateEngineData); EngineData(theEnv)->IncrementalResetFlag = TRUE; #if DEBUGGING_FUNCTIONS AddWatchItem(theEnv,"statistics",0,&EngineData(theEnv)->WatchStatistics,20,NULL,NULL); AddWatchItem(theEnv,"focus",0,&EngineData(theEnv)->WatchFocus,0,NULL,NULL);#endif } /*************************************************//* DeallocateEngineData: Deallocates environment *//* data for engine functionality. *//*************************************************/static void DeallocateEngineData( void *theEnv) { struct focus *tmpPtr, *nextPtr; DeallocateCallList(theEnv,EngineData(theEnv)->ListOfRunFunctions); tmpPtr = EngineData(theEnv)->CurrentFocus; while (tmpPtr != NULL) { nextPtr = tmpPtr->next; rtn_struct(theEnv,focus,tmpPtr); tmpPtr = nextPtr; } }/*************************************************//* EnvRun: C access routine for the run command. *//*************************************************/globle long long EnvRun( void *theEnv, long long runLimit) { long long 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 short i; struct patternEntity *theMatchingItem; struct partialMatch *theBasis; ACTIVATION *theActivation; char *ruleFiring;#if PROFILING_FUNCTIONS struct profileFrameInfo profileFrame;#endif struct trackedMemory *theTM; /*=====================================================*/ /* 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;#if DEVELOPER EngineData(theEnv)->leftToRightComparisons = 0; EngineData(theEnv)->rightToLeftComparisons = 0; EngineData(theEnv)->leftToRightSucceeds = 0; EngineData(theEnv)->rightToLeftSucceeds = 0; EngineData(theEnv)->leftToRightLoops = 0; EngineData(theEnv)->rightToLeftLoops = 0; EngineData(theEnv)->findNextConflictingComparisons = 0; EngineData(theEnv)->betaHashListSkips = 0; EngineData(theEnv)->betaHashHTSkips = 0; EngineData(theEnv)->unneededMarkerCompare = 0;#endif /*=====================================================*/ /* 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); theTM = AddTrackedMemory(theEnv,theActivation,sizeof(struct activation)); 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]; gensprintf(printSpace,"FIRE %4lld ",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->marker = 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++) { if (theBasis->binds[i].gm.theMatch == NULL) continue; 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. */ /*===================================================*/ theBasis->busy = FALSE; for (i = 0; i < (theBasis->bcount); i++) { if (theBasis->binds[i].gm.theMatch == NULL) continue; theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem; if (theMatchingItem != NULL) { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); } } /*========================================*/ /* Return the agenda node to free memory. */ /*========================================*/ RemoveTrackedMemory(theEnv,theTM); 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))(); } } }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -