⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cstrnops.c

📁 VC嵌入式CLips专家系统,实现战场环境的目标识别
💻 C
📖 第 1 页 / 共 3 页
字号:
   /*******************************************************/
   /*      "C" Language Integrated Production System      */
   /*                                                     */
   /*             CLIPS Version 6.24  07/01/05            */
   /*                                                     */
   /*            CONSTRAINT OPERATIONS MODULE             */
   /*******************************************************/

/*************************************************************/
/* Purpose: Provides functions for performing operations on  */
/*   constraint records including computing the intersection */
/*   and union of constraint records.                        */
/*                                                           */
/* Principal Programmer(s):                                  */
/*      Gary D. Riley                                        */
/*                                                           */
/* Contributing Programmer(s):                               */
/*                                                           */
/* Revision History:                                         */
/*                                                           */
/*      6.24: Added allowed-classes slot facet.              */
/*                                                           */
/*************************************************************/

#define _CSTRNOPS_SOURCE_

#include "setup.h"

#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>

#if (! RUN_TIME)

#include "constant.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "router.h"
#include "extnfunc.h"
#include "scanner.h"
#include "multifld.h"
#include "constrnt.h"
#include "cstrnchk.h"
#include "cstrnutl.h"

#include "cstrnops.h"

/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/

   static void                     IntersectNumericExpressions(void *,
                                                               CONSTRAINT_RECORD *,
                                                               CONSTRAINT_RECORD *,
                                                               CONSTRAINT_RECORD *,int);
   static void                     IntersectAllowedValueExpressions(void *,
                                                                    CONSTRAINT_RECORD *,
                                                                    CONSTRAINT_RECORD *,
                                                                    CONSTRAINT_RECORD *);
   static void                     IntersectAllowedClassExpressions(void *,
                                                                    CONSTRAINT_RECORD *,
                                                                    CONSTRAINT_RECORD *,
                                                                    CONSTRAINT_RECORD *);
   static int                      FindItemInExpression(int,void *,int,struct expr *);
   static void                     UpdateRestrictionFlags(CONSTRAINT_RECORD *);
#if (! BLOAD_ONLY)
   static void                     UnionRangeMinMaxValueWithList(void *,
                                                                 struct expr *,
                                                                 struct expr *,
                                                                 struct expr **,
                                                                 struct expr **);
   static void                     UnionNumericExpressions(void *,
                                                         CONSTRAINT_RECORD *,
                                                         CONSTRAINT_RECORD *,
                                                         CONSTRAINT_RECORD *,int);
   static struct expr             *AddToUnionList(void *,
                                                  struct expr *,struct expr *,
                                                  CONSTRAINT_RECORD *);
   static void                     UnionAllowedValueExpressions(void *,
                                                                CONSTRAINT_RECORD *,
                                                                CONSTRAINT_RECORD *,
                                                                CONSTRAINT_RECORD *);
   static void                     UnionAllowedClassExpressions(void *,
                                                                CONSTRAINT_RECORD *,
                                                                CONSTRAINT_RECORD *,
                                                                CONSTRAINT_RECORD *);
   static int                      RestrictionOnType(int,CONSTRAINT_RECORD *);
#endif

/**************************************************************/
/* IntersectConstraints: Creates a new constraint record that */
/*   is the intersection of two other constraint records.     */
/**************************************************************/
globle struct constraintRecord *IntersectConstraints(
  void *theEnv,
  CONSTRAINT_RECORD *c1,
  CONSTRAINT_RECORD *c2)
  {
   struct constraintRecord *rv;
   int c1Changed = FALSE, c2Changed = FALSE;

   /*=================================================*/
   /* If both constraint records are NULL,then create */
   /* a constraint record that allows any value.      */
   /*=================================================*/

   if ((c1 == NULL) && (c2 == NULL))
     {
      rv = GetConstraintRecord(theEnv);
      rv->multifieldsAllowed = TRUE;
      return(rv);
     }

   /*=================================================*/
   /* If one of the constraint records is NULL, then  */
   /* the intersection is the other constraint record */
   /* (a NULL value means no constraints).            */
   /*=================================================*/

   if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2));

   if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1));

   /*=================================*/
   /* Create a new constraint record. */
   /*=================================*/

   rv = GetConstraintRecord(theEnv);

   /*==============================*/
   /* Intersect the allowed types. */
   /*==============================*/

   if ((c1->multifieldsAllowed != c2->multifieldsAllowed) &&
       (c1->singlefieldsAllowed != c2->singlefieldsAllowed))
     {
      rv->anyAllowed = FALSE;
      return(rv);
     }

   if (c1->multifieldsAllowed && c2->multifieldsAllowed)
     { rv->multifieldsAllowed = TRUE; }
   else
     { rv->multifieldsAllowed = FALSE; }

   if (c1->singlefieldsAllowed && c2->singlefieldsAllowed)
     { rv->singlefieldsAllowed = TRUE; }
   else
     { rv->singlefieldsAllowed = FALSE; }

   if (c1->anyAllowed && c2->anyAllowed) rv->anyAllowed = TRUE;
   else
     {
      if (c1->anyAllowed)
        {
         c1Changed = TRUE;
         SetAnyAllowedFlags(c1,FALSE);
        }
      else if (c2->anyAllowed)
        {
         c2Changed = TRUE;
         SetAnyAllowedFlags(c2,FALSE);
        }

      rv->anyAllowed = FALSE;
      rv->symbolsAllowed = (c1->symbolsAllowed && c2->symbolsAllowed);
      rv->stringsAllowed = (c1->stringsAllowed && c2->stringsAllowed);
      rv->floatsAllowed = (c1->floatsAllowed && c2->floatsAllowed);
      rv->integersAllowed = (c1->integersAllowed && c2->integersAllowed);
      rv->instanceNamesAllowed = (c1->instanceNamesAllowed && c2->instanceNamesAllowed);
      rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed && c2->instanceAddressesAllowed);
      rv->externalAddressesAllowed = (c1->externalAddressesAllowed && c2->externalAddressesAllowed);
      rv->voidAllowed = (c1->voidAllowed && c2->voidAllowed);
      rv->multifieldsAllowed = (c1->multifieldsAllowed && c2->multifieldsAllowed);
      rv->factAddressesAllowed = (c1->factAddressesAllowed && c2->factAddressesAllowed);

      if (c1Changed) SetAnyAllowedFlags(c1,TRUE);
      if (c2Changed) SetAnyAllowedFlags(c2,TRUE);
     }

   /*=====================================*/
   /* Intersect the allowed-values flags. */
   /*=====================================*/

   if (c1->anyRestriction || c2->anyRestriction) rv->anyRestriction = TRUE;
   else
     {
      rv->anyRestriction = FALSE;
      rv->symbolRestriction = (c1->symbolRestriction || c2->symbolRestriction);
      rv->stringRestriction = (c1->stringRestriction || c2->stringRestriction);
      rv->floatRestriction = (c1->floatRestriction || c2->floatRestriction);
      rv->integerRestriction = (c1->integerRestriction || c2->integerRestriction);
      rv->classRestriction = (c1->classRestriction || c2->classRestriction);
      rv->instanceNameRestriction = (c1->instanceNameRestriction || c2->instanceNameRestriction);
     }

   /*==================================================*/
   /* Intersect the allowed values list, allowed class */
   /* list, min and max values, and the range values.  */
   /*==================================================*/

   IntersectAllowedValueExpressions(theEnv,c1,c2,rv);
   IntersectAllowedClassExpressions(theEnv,c1,c2,rv);
   IntersectNumericExpressions(theEnv,c1,c2,rv,TRUE);
   IntersectNumericExpressions(theEnv,c1,c2,rv,FALSE);

   /*==========================================*/
   /* Update the allowed-values flags based on */
   /* the previous intersection for allowed,   */
   /* min and max, and range values.           */
   /*==========================================*/

   UpdateRestrictionFlags(rv);

   /*============================================*/
   /* If multifields are allowed, then intersect */
   /* the constraint record for them.            */
   /*============================================*/

   if (rv->multifieldsAllowed)
     {
      rv->multifield = IntersectConstraints(theEnv,c1->multifield,c2->multifield);
      if (UnmatchableConstraint(rv->multifield))
        { rv->multifieldsAllowed = FALSE; }
     }

   /*========================*/
   /* Return the intersected */
   /* constraint record.     */
   /*========================*/

   return(rv);
  }

/*************************************************/
/* IntersectAllowedValueExpressions: Creates the */
/*   intersection of two allowed-values lists.   */
/*************************************************/
static void IntersectAllowedValueExpressions(
  void *theEnv,
  CONSTRAINT_RECORD *constraint1,
  CONSTRAINT_RECORD *constraint2,
  CONSTRAINT_RECORD *newConstraint)
  {
   struct expr *theList1, *theList2;
   struct expr *theHead = NULL, *tmpExpr;

   /*===========================================*/
   /* Loop through each value in allowed-values */
   /* list of the first constraint record. Add  */
   /* each value to a list if it satisfies the  */
   /* restrictions for both constraint records. */
   /*===========================================*/

   for (theList1 = constraint1->restrictionList;
        theList1 != NULL;
        theList1 = theList1->nextArg)
     {
      if (CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint1) &&
          CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint2))
        {
         tmpExpr = GenConstant(theEnv,theList1->type,theList1->value);
         tmpExpr->nextArg = theHead;
         theHead = tmpExpr;
        }
     }

   /*===========================================*/
   /* Loop through each value in allowed-values */
   /* list of the second constraint record. Add */
   /* each value to a list if it satisfies the  */
   /* restrictions for both constraint records. */
   /*===========================================*/

   for (theList2 = constraint2->restrictionList;
        theList2 != NULL;
        theList2 = theList2->nextArg)
     {
      if (FindItemInExpression(theList2->type,theList2->value,TRUE,theHead))
        { /* The value is already in the list--Do nothing */ }
      else if (CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint1) &&
               CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint2))
        {
         tmpExpr = GenConstant(theEnv,theList2->type,theList2->value);
         tmpExpr->nextArg = theHead;
         theHead = tmpExpr;
        }
     }

   /*================================================*/
   /* Set the allowed values list for the constraint */
   /* record to the intersected values of the two    */
   /* other constraint records.                      */
   /*================================================*/

   newConstraint->restrictionList = theHead;
  }
  
/*************************************************/
/* IntersectAllowedClassExpressions: Creates the */
/*   intersection of two allowed-classes lists.  */
/*************************************************/
static void IntersectAllowedClassExpressions(
  void *theEnv,
  CONSTRAINT_RECORD *constraint1,
  CONSTRAINT_RECORD *constraint2,
  CONSTRAINT_RECORD *newConstraint)
  {
   struct expr *theList1, *theList2;
   struct expr *theHead = NULL, *tmpExpr;

   /*============================================*/
   /* Loop through each value in allowed-classes */
   /* list of the first constraint record. Add   */
   /* each value to a list if it satisfies the   */
   /* restrictions for both constraint records.  */
   /*============================================*/
   
   for (theList1 = constraint1->classList;
        theList1 != NULL;
        theList1 = theList1->nextArg)
     {
      if (CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint1) &&
          CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint2))
        {
         tmpExpr = GenConstant(theEnv,theList1->type,theList1->value);
         tmpExpr->nextArg = theHead;
         theHead = tmpExpr;
        }
     }

   /*============================================*/
   /* Loop through each value in allowed-classes */
   /* list of the second constraint record. Add  */
   /* each value to a list if it satisfies the   */
   /* restrictions for both constraint records.  */
   /*============================================*/

   for (theList2 = constraint2->classList;
        theList2 != NULL;
        theList2 = theList2->nextArg)
     {
      if (FindItemInExpression(theList2->type,theList2->value,TRUE,theHead))
        { /* The value is already in the list--Do nothing */ }
      else if (CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint1) &&
               CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint2))
        {
         tmpExpr = GenConstant(theEnv,theList2->type,theList2->value);
         tmpExpr->nextArg = theHead;
         theHead = tmpExpr;
        }
     }

   /*=================================================*/
   /* Set the allowed classes list for the constraint */
   /* record to the intersected values of the two     */
   /* other constraint records.                       */
   /*=================================================*/

   newConstraint->classList = theHead;
  }
  
/*********************************************************/
/* IntersectNumericExpressions: Creates the intersection */
/*   of two range or two min/max-fields constraints.     */
/*********************************************************/
static void IntersectNumericExpressions(
  void *theEnv,
  CONSTRAINT_RECORD *constraint1,
  CONSTRAINT_RECORD *constraint2,
  CONSTRAINT_RECORD *newConstraint,
  int range)
  {
   struct expr *tmpmin1, *tmpmax1, *tmpmin2, *tmpmax2, *theMin, *theMax;
   struct expr *theMinList, *theMaxList, *lastMin = NULL, *lastMax = NULL;
   int cmaxmax, cminmin, cmaxmin, cminmax;

   /*==========================================*/
   /* Initialize the new range/min/max values  */
   /* for the intersection of the constraints. */
   /*==========================================*/

   theMinList = NULL;
   theMaxList = NULL;

   /*=================================*/
   /* Determine the min/max values of */
   /* the first constraint record.    */
   /*=================================*/

   if (range)
     {
      tmpmin1 = constraint1->minValue;
      tmpmax1 = constraint1->maxValue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -