📄 retract.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 05/17/06 */
/* */
/* RETRACT MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Handles join network activity associated with */
/* with the removal of a data entity such as a fact or */
/* instance. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Removed LOGICAL_DEPENDENCIES compilation flag. */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/* Rule with exists CE has incorrect activation. */
/* DR0867 */
/* */
/*************************************************************/
#define _RETRACT_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#include "setup.h"
#if DEFRULE_CONSTRUCT
#include "agenda.h"
#include "argacces.h"
#include "constant.h"
#include "drive.h"
#include "engine.h"
#include "envrnmnt.h"
#include "lgcldpnd.h"
#include "match.h"
#include "memalloc.h"
#include "network.h"
#include "reteutil.h"
#include "router.h"
#include "symbol.h"
#include "retract.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static struct partialMatch *RemovePartialMatches(void *,struct alphaMatch *,
struct partialMatch *,
struct partialMatch **,int,
struct partialMatch **);
static void DeletePartialMatches(void *,struct partialMatch *,int);
static void ReturnMarkers(void *,struct multifieldMarker *);
static void DriveRetractions(void *);
static intBool FindNextConflictingAlphaMatch(void *,struct partialMatch *,
struct partialMatch *,
struct joinNode *);
static intBool PartialMatchDefunct(void *,struct partialMatch *);
/************************************************************/
/* NetworkRetract: Retracts a data entity (such as a fact */
/* or instance) from the pattern and join networks given */
/* a pointer to the list of patterns which the data */
/* entity matched. The data entity is first removed from */
/* the join network through patterns not directly */
/* enclosed within a not CE and then through patterns */
/* enclosed by a not CE. Any new partial matches created */
/* by the removal are then filtered through the join */
/* network. This ordering prevents partial matches from */
/* being generated that contain the data entity which was */
/* removed. */
/************************************************************/
globle void NetworkRetract(
void *theEnv,
struct patternMatch *listOfMatchedPatterns)
{
struct patternMatch *tempMatch;
struct partialMatch *deletedMatches, *theLast;
struct joinNode *joinPtr;
/*===============================*/
/* Remember the beginning of the */
/* list of matched patterns. */
/*===============================*/
tempMatch = listOfMatchedPatterns;
/*============================================*/
/* Remove the data entity from all joins that */
/* aren't directly enclosed by a not CE. */
/*============================================*/
for (;
listOfMatchedPatterns != NULL;
listOfMatchedPatterns = listOfMatchedPatterns->next)
{
/*====================================*/
/* Loop through the list of all joins */
/* attached to this pattern. */
/*====================================*/
for (joinPtr = listOfMatchedPatterns->matchingPattern->entryJoin;
joinPtr != NULL;
joinPtr = joinPtr->rightMatchNode)
{
if (joinPtr->patternIsNegated == FALSE)
{ PosEntryRetract(theEnv,joinPtr,
listOfMatchedPatterns->theMatch->binds[0].gm.theMatch,
listOfMatchedPatterns->theMatch,
(int) joinPtr->depth - 1,listOfMatchedPatterns->theMatch->binds[0].gm.theMatch->matchingItem); }
}
}
/*============================================*/
/* Remove the data entity from all joins that */
/* are directly enclosed by a not CE. */
/*============================================*/
listOfMatchedPatterns = tempMatch;
while (listOfMatchedPatterns != NULL)
{
/*====================================*/
/* Loop through the list of all joins */
/* attached to this pattern. */
/*====================================*/
for (joinPtr = listOfMatchedPatterns->matchingPattern->entryJoin;
joinPtr != NULL;
joinPtr = joinPtr->rightMatchNode)
{
if (joinPtr->patternIsNegated == TRUE)
{
if (joinPtr->firstJoin == TRUE)
{
SystemError(theEnv,"RETRACT",3);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
else
{
NegEntryRetract(theEnv,joinPtr,listOfMatchedPatterns->theMatch,listOfMatchedPatterns->theMatch->binds[0].gm.theMatch->matchingItem);
}
}
}
/*===================================================*/
/* Remove from the alpha memory of the pattern node. */
/*===================================================*/
theLast = NULL;
listOfMatchedPatterns->matchingPattern->alphaMemory =
RemovePartialMatches(theEnv,listOfMatchedPatterns->theMatch->binds[0].gm.theMatch,
listOfMatchedPatterns->matchingPattern->alphaMemory,
&deletedMatches,0,&theLast);
listOfMatchedPatterns->matchingPattern->endOfQueue = theLast;
DeletePartialMatches(theEnv,deletedMatches,0);
tempMatch = listOfMatchedPatterns->next;
rtn_struct(theEnv,patternMatch,listOfMatchedPatterns);
listOfMatchedPatterns = tempMatch;
}
/*=========================================*/
/* Filter new partial matches generated by */
/* retraction through the join network. */
/*=========================================*/
DriveRetractions(theEnv);
}
/***************************************************************/
/* PosEntryRetract: Handles retract for a join of a rule with */
/* a positive pattern when the retraction is starting from */
/* the RHS of that join (empty or positive LHS entry, */
/* positive RHS entry), or the LHS of that join (positive */
/* LHS entry, negative or positive RHS entry). */
/***************************************************************/
globle void PosEntryRetract(
void *theEnv,
struct joinNode *join,
struct alphaMatch *theAlphaNode,
struct partialMatch *theMatch,
int position,
void *duringRetract)
{
struct partialMatch *deletedMatches;
struct joinNode *joinPtr;
struct partialMatch *theLast;
while (join != NULL)
{
/*=========================================*/
/* Remove the bindings from this join that */
/* contain the fact to be retracted. */
/*=========================================*/
if (join->beta == NULL) return; /* optimize */
join->beta = RemovePartialMatches(theEnv,theAlphaNode,join->beta,&deletedMatches,
position,&theLast);
/*===================================================*/
/* If no facts were deleted at this join, then there */
/* is no need to check joins at a lower level. */
/*===================================================*/
if (deletedMatches == NULL) return;
/*==================================================*/
/* If there is more than one join below this join, */
/* then recursively remove fact bindings from all */
/* but one of the lower joins. Remove the bindings */
/* from the other join through this loop. */
/*==================================================*/
joinPtr = join->nextLevel;
if (joinPtr == NULL)
{
DeletePartialMatches(theEnv,deletedMatches,1);
return;
}
if (((struct joinNode *) (joinPtr->rightSideEntryStructure)) == join)
{
theMatch = deletedMatches;
while (theMatch != NULL)
{
NegEntryRetract(theEnv,joinPtr,theMatch,duringRetract);
theMatch = theMatch->next;
}
DeletePartialMatches(theEnv,deletedMatches,1);
return;
}
DeletePartialMatches(theEnv,deletedMatches,1);
while (joinPtr->rightDriveNode != NULL)
{
PosEntryRetract(theEnv,joinPtr,theAlphaNode,theMatch,position,duringRetract);
joinPtr = joinPtr->rightDriveNode;
}
join = joinPtr;
}
}
/*****************************************************************/
/* NegEntryRetract: Handles retract for a join of a rule with a */
/* not CE when the retraction is process from the RHS of that */
/* join. */
/*****************************************************************/
void NegEntryRetract(
void *theEnv,
struct joinNode *theJoin,
struct partialMatch *theMatch,
void *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(theEnv,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(theEnv,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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -