home *** CD-ROM | disk | FTP | other *** search
/ Media Share 13 / mediashare_13.zip / mediashare_13 / ZIPPED / PROGRAM / APR94_1.ZIP / FUZZY.ASC < prev    next >
Text File  |  1994-02-27  |  17KB  |  473 lines

  1. _FUZZY LOGIC IN C: AN UPDATE_
  2. by John A.R. Tucker, Phillip E. Fraley, Lawrence Pl Swanson
  3.  
  4. Listing One
  5.  
  6. /* Update to Greg Viot's fuzzy system -- DDJ, February 1993, page 94 */
  7. #include <stdio.h>
  8. #include <string.h>                      /* NEW */
  9. # define max(a,b)   (a<b ? b : a)    /* NEW */
  10. # define min(a,b)   (a>b ? b : a)    /* NEW */
  11. struct io_type *System_Inputs;           /* anchor inputs NEW */
  12. struct io_type *System_Output;           /* anchor output NEW */
  13. #define MAXNAME 10
  14. #define UPPER_LIMIT 255
  15. struct io_type{
  16.    char name[MAXNAME];
  17.    int value;
  18.    struct mf_type *membership_functions;
  19.    struct io_type *next;
  20.    };
  21. struct mf_type{
  22.    char name[MAXNAME];
  23.    int value;
  24.    int point1;
  25.    int point2;
  26.    float slope1;
  27.    float slope2;
  28.    struct mf_type *next;
  29.    };
  30. struct rule_type{
  31.    struct rule_element_type *if_side;
  32.    struct rule_element_type *then_side;
  33.    struct rule_type *next;
  34.    };
  35. struct rule_element_type{
  36.    int *value;
  37.    struct rule_element_type *next;
  38.    };
  39. struct rule_type *Rule_Base;
  40.  
  41. main(argc,argv)                          /* NEW */
  42. int argc;                                /* NEW */
  43. char *argv[];                            /* NEW */
  44. {  int input1, input2;                   /* NEW */
  45.    if(argc!=3)                           /* NEW */
  46.    {  printf("Error - Must supply 2 numeric inputs.\n"); /* NEW */
  47.       printf("        Inputs scaled to range 0-255.\n"); /* NEW */
  48.       printf("Usage: %s angle velocity\n",argv[0]);      /* NEW */
  49.       exit(0);                           /* NEW */
  50.    }                                     /* NEW */
  51.    input1=atoi(argv[1]);                 /* NEW */
  52.    input2=atoi(argv[2]);                 /* NEW */
  53.    initialize_system();                  /* Read input files, NEW */
  54.    get_system_inputs(input1,input2);     /* Get & put argv NEW */
  55.    fuzzification();
  56.    rule_evaluation();
  57.    defuzzification();
  58.    put_system_outputs();                 /* print all data, NEW */
  59. }                                        /* END MAIN */
  60. fuzzification()
  61. {  struct io_type *si;
  62.    struct mf_type *mf;
  63.    for(si=System_Inputs;si!=NULL;si=si->next)
  64.       for(mf=si->membership_functions;mf!=NULL;mf=mf->next)
  65.      compute_degree_of_membership(mf,si->value);
  66. }                                        /* END FUZZIFICATION */
  67. rule_evaluation()
  68. {  struct rule_type *rule;
  69.    struct rule_element_type *ip;    /* if ptr */
  70.    struct rule_element_type *tp;    /* then ptr */
  71.    int strength;
  72.    int nomatch=0;                   /* NEW, test some rules */
  73.    for(rule=Rule_Base;rule!=NULL;rule=rule->next)
  74.    {  strength=UPPER_LIMIT;
  75.       for(ip=rule->if_side;ip!=NULL;ip=ip->next)
  76.              strength=min(strength,*(ip->value));
  77.       for(tp=rule->then_side;tp!=NULL;tp=tp->next)
  78.       {  *(tp->value)=max(strength,*(tp->value));      /* NEW */
  79.          if(strength>0)nomatch=1;                      /* NEW */
  80.       }                                                /* NEW */
  81.    }
  82.    if(nomatch==0)printf("NO MATCHING RULES FOUND!\n"); /* NEW */
  83. }                                        /* END RULE EVALUATION */
  84. defuzzification()
  85. {  struct io_type *so;
  86.    struct mf_type *mf;
  87.    int sum_of_products;
  88.    int sum_of_areas;
  89.    int area, centroid;
  90.    for(so=System_Output;so!=NULL;so=so->next)  
  91.    {  sum_of_products=0;
  92.       sum_of_areas=0;
  93.       for(mf=so->membership_functions;mf!=NULL;mf=mf->next)
  94.       {  area=compute_area_of_trapezoid(mf);
  95.      centroid=mf->point1+(mf->point2-mf->point1)/2;
  96.      sum_of_products+=area*centroid;
  97.      sum_of_areas+=area;
  98.       }
  99.       if(sum_of_areas==0)                                    /* NEW */
  100.       {  printf("Sum of Areas = 0, will cause div error\n"); /* NEW */
  101.      printf("Sum of Products= %d\n",sum_of_products);    /* NEW */
  102.      so->value=0;                                        /* NEW */
  103.      return;                                             /* NEW */
  104.       }                                                      /* NEW */
  105.       so->value=sum_of_products/sum_of_areas;
  106.    }
  107. }                                        /* END DEFUZZIFICATION */
  108. compute_degree_of_membership(mf,input)
  109. struct mf_type *mf;
  110. int input;
  111. {  int delta_1, delta_2;
  112.    delta_1=input - mf->point1;
  113.    delta_2=mf->point2 - input;
  114.    if((delta_1<=0)||(delta_2<=0))mf->value=0;
  115.    else
  116.    {  mf->value=min((mf->slope1*delta_1),(mf->slope2*delta_2));
  117.       mf->value=min(mf->value,UPPER_LIMIT);
  118.    }
  119. }                                        /* END DEGREE OF MEMBERSHIP */
  120. compute_area_of_trapezoid(mf)
  121. struct mf_type *mf;
  122. {  float run_1,run_2,area,top;
  123.    float base;
  124.    base=mf->point2 - mf->point1;
  125.    run_1=mf->value / mf->slope1;
  126.    run_2=mf->value / mf->slope2;
  127.    top=base - run_1 - run_2;
  128.    area=mf->value*(base+top)/2;
  129.    return(area);
  130. }                                        /* END AREA OF TRAPEZOID */
  131. initialize_system()                      /* NEW FUNCTION INITIALIZE */
  132. {  int a, b, c, d, x;
  133.    char buff[10],buff1[4],buff2[4];
  134.    static char filename1[]="in1";  /* "angles" filename */
  135.    static char filename2[]="in2";  /* "velocities" filename */
  136.    static char filename3[]="out1"; /* "forces" filename */
  137.    FILE *fp;
  138.    struct io_type *outptr;
  139.    struct mf_type *top_mf;
  140.    struct mf_type *mfptr;
  141.    struct io_type *ioptr;
  142.    struct rule_type *ruleptr;
  143.    struct rule_element_type *ifptr;
  144.    struct rule_element_type *thenptr;
  145.    ioptr=NULL;
  146.    ruleptr=NULL;
  147.    ifptr=NULL;
  148.    thenptr=NULL;
  149. /* READ THE FIRST FUZZY SET (ANTECEDENT); INITIALIZE STRUCTURES */
  150.    if((fp=fopen(filename1,"r"))==NULL)   /* open "angles" file */
  151.    {  printf("ERROR- Unable to open data file named %s.\n",filename1);
  152.       exit(0);
  153.    }
  154.    ioptr=(struct io_type *)calloc(1,sizeof(struct io_type));
  155.    System_Inputs=ioptr;                  /* Anchor to top of inputs */
  156.    x=fscanf(fp,"%s",buff);               /* from 1st line, get set's name */
  157.    sprintf(ioptr->name,"%s",buff);       /* into struct io_type.name */
  158.    mfptr=NULL;
  159.    while((x=fscanf(fp,"%s %d %d %d %d",buff,&a,&b,&c,&d))!=EOF)/* get line */
  160.    {  if(mfptr==NULL)                    /* first time thru only */
  161.       {  mfptr=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  162.      top_mf=mfptr;
  163.      ioptr->membership_functions=mfptr;
  164.       }
  165.       else
  166.       {  for(mfptr=top_mf;mfptr->next;mfptr=mfptr->next); /* spin to last */
  167.      mfptr->next=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  168.      mfptr=mfptr->next;
  169.       }     
  170.       sprintf(mfptr->name,"%s",buff);    /* membership name, NL, ZE, etc */
  171.       mfptr->point1=a;                   /* left x axis value */
  172.       mfptr->point2=d;                   /* right x axis value */
  173.       if(b-a>0) mfptr->slope1=UPPER_LIMIT/(b-a);     /* left slope */
  174.       else
  175.       {  printf("Error in input file %s, membership element %s.\n",
  176.          filename1,buff);
  177.      exit(1);
  178.       }
  179.       if(d-c>0) mfptr->slope2=UPPER_LIMIT/(d-c);     /* right slope */
  180.       else
  181.       {  printf("Error in input file %s, membership element %s.\n",
  182.          filename1,buff);
  183.      exit(1);
  184.       }
  185.    }
  186.    close(fp);                            /* close "angles" file */
  187. /* READ THE SECOND FUZZY SET (ANTECEDENT); INITIALIZE STRUCTURES */
  188.    if((fp=fopen(filename2,"r"))==NULL)   /* open "velocity" file */
  189.    {  printf("ERROR- Unable to open data file named %s.\n",filename2);
  190.       exit(0);
  191.    }
  192.    ioptr->next=(struct io_type *)calloc(1,sizeof(struct io_type));
  193.    ioptr=ioptr->next;
  194.    x=fscanf(fp,"%s",buff);               /* from 1st line, get set's name */
  195.    sprintf(ioptr->name,"%s",buff);       /* into struct io_type.name */
  196.    mfptr=NULL; 
  197.    while((x=fscanf(fp,"%s %d %d %d %d",buff,&a,&b,&c,&d))!=EOF)/* get line */
  198.    {  if(mfptr==NULL)                    /* first time thru only */
  199.       {  mfptr=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  200.      top_mf=mfptr;
  201.      ioptr->membership_functions=mfptr;
  202.       }
  203.       else
  204.       {  for(mfptr=top_mf;mfptr->next;mfptr=mfptr->next); /* spin to last */
  205.      mfptr->next=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  206.      mfptr=mfptr->next;
  207.       }     
  208.       sprintf(mfptr->name,"%s",buff);    /* membership name, NL, ZE, etc */
  209.       mfptr->point1=a;                   /* left x axis value */
  210.       mfptr->point2=d;                   /* right x axis value */
  211.       if(b-a>0) mfptr->slope1=UPPER_LIMIT/(b-a);     /* left slope */
  212.       else
  213.       {  printf("Error in input file %s, membership element %s.\n",
  214.          filename2,buff);
  215.      exit(1);
  216.       }
  217.       if(d-c>0) mfptr->slope2=UPPER_LIMIT/(d-c);     /* right slope */
  218.       else
  219.       {  printf("Error in input file %s, membership element %s.\n",
  220.          filename2,buff);
  221.      exit(1);
  222.       }
  223.    }
  224.    close(fp);                            /* close "velocity" file */
  225. /* READ THE THIRD FUZZY SET (CONSEQUENCE); INITIALIZE STRUCTURES */
  226.    if((fp=fopen(filename3,"r"))==NULL)   /* open "force" file */
  227.    {  printf("ERROR- Unable to open data file named %s.\n",filename3);
  228.       exit(0);
  229.    }
  230.    ioptr=(struct io_type *)calloc(1,sizeof(struct io_type));
  231.    System_Output=ioptr;                  /* Anchor output structure */
  232.    x=fscanf(fp,"%s",buff);               /* from 1st line, get set's name */
  233.    sprintf(ioptr->name,"%s",buff);       /* into struct io_type.name */
  234.    mfptr=NULL;
  235.    while((x=fscanf(fp,"%s %d %d %d %d",buff,&a,&b,&c,&d))!=EOF)/* get line */
  236.    {  if(mfptr==NULL)                    /* first time thru */
  237.       {  mfptr=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  238.      top_mf=mfptr;
  239.      ioptr->membership_functions=mfptr;
  240.       }
  241.       else
  242.       {  for(mfptr=top_mf;mfptr->next;mfptr=mfptr->next);
  243.      mfptr->next=(struct mf_type *)calloc(1,sizeof(struct mf_type));
  244.      mfptr=mfptr->next;
  245.       }     
  246.       sprintf(mfptr->name,"%s",buff);    /* membership name, NL, ZE, etc */
  247.       mfptr->point1=a;                   /* left x axis value */
  248.       mfptr->point2=d;                   /* right x axis value */
  249.       if(b-a>0) mfptr->slope1=UPPER_LIMIT/(b-a);     /* left slope */
  250.       else
  251.       {  printf("Error in input file %s, membership element %s.\n",
  252.          filename3,buff);
  253.      exit(1);
  254.       }
  255.       if(d-c>0) mfptr->slope2=UPPER_LIMIT/(d-c);     /* right slope */
  256.       else
  257.       {  printf("Error in input file %s, membership element %s.\n",
  258.          filename3,buff);
  259.      exit(1);
  260.       }
  261.    }
  262.    close(fp);                            /* close "force" file */
  263. /* READ RULES FILE; INITIALIZE STRUCTURES */
  264.    ioptr=NULL;
  265.    outptr=NULL;
  266.    if((fp=fopen("rules","r"))==NULL)     /* open rules file */
  267.    {  printf("ERROR- Unable to open data file named %s.\n","rules");
  268.       exit(0);
  269.    }
  270.    ruleptr=(struct rule_type *)calloc(1,sizeof(struct rule_type));
  271.    if(ioptr==NULL)Rule_Base=ruleptr;     /* first time thru, anchor */
  272.    while((x=fscanf(fp,"%s %s %s",buff,buff1,buff2))!=EOF) /* get a line */
  273.    {  ioptr=System_Inputs;               /* points to angle */
  274.       for(mfptr=ioptr->membership_functions;mfptr!=NULL;mfptr=mfptr->next)
  275.       {  if((strcmp(mfptr->name,buff))==0)
  276.      {  ifptr=(struct rule_element_type *)
  277.                   calloc(1,sizeof(struct rule_element_type));
  278.         ruleptr->if_side=ifptr;      /* points to angle */
  279.         ifptr->value=&mfptr->value;  /* needs address here */
  280.         ifptr->next=(struct rule_element_type *)
  281.                   calloc(1,sizeof(struct rule_element_type));
  282.         ifptr=ifptr->next;
  283.         break;                       /* match found */
  284.           }
  285.       }
  286.       ioptr=ioptr->next;                 /* points to velocity */
  287.       for(mfptr=ioptr->membership_functions;mfptr!=NULL;mfptr=mfptr->next)
  288.       {  if((strcmp(mfptr->name,buff1))==0)
  289.      {  ifptr->value=&mfptr->value;  /* needs address here */
  290.         break;                       /* match found */
  291.           }
  292.       }
  293.       if(outptr==NULL)outptr=System_Output;/* point then stuff to output */
  294.       for(mfptr=outptr->membership_functions;mfptr!=NULL;mfptr=mfptr->next)
  295.       {  if((strcmp(mfptr->name,buff2))==0)
  296.          {  thenptr=(struct rule_element_type *)
  297.                 calloc(1,sizeof(struct rule_element_type));
  298.         ruleptr->then_side=thenptr;
  299.             thenptr->value=&mfptr->value; /* needs address here */
  300.         break;                        /* match found */
  301.          }
  302.       }
  303.       ruleptr->next=(struct rule_type *)calloc(1,sizeof(struct rule_type));
  304.       ruleptr=ruleptr->next;
  305.    }                                     /* END WHILE READING RULES FILE */
  306.    close(fp);                            /* close "rules" file */
  307. }                                        /* END INITIALIZE */
  308. put_system_outputs()                     /* NEW */
  309. {  struct io_type *ioptr;
  310.    struct mf_type *mfptr;
  311.    struct rule_type *ruleptr;
  312.    struct rule_element_type *ifptr;
  313.    struct rule_element_type *thenptr;
  314.    int cnt=1;
  315.    for(ioptr=System_Inputs;ioptr!=NULL;ioptr=ioptr->next)
  316.    {  printf("%s: Value= %d\n",ioptr->name,ioptr->value);
  317.       for(mfptr=ioptr->membership_functions;mfptr!=NULL;mfptr=mfptr->next)
  318.       {  printf("  %s: Value %d Left %d Right %d\n",
  319.            mfptr->name,mfptr->value,mfptr->point1,mfptr->point2);
  320.       }
  321.      printf("\n");
  322.    }
  323.    for(ioptr=System_Output;ioptr!=NULL;ioptr=ioptr->next)
  324.    {  printf("%s: Value= %d\n",ioptr->name,ioptr->value);
  325.       for(mfptr=ioptr->membership_functions;mfptr!=NULL;mfptr=mfptr->next)
  326.       {  printf("  %s: Value %d Left %d Right %d\n",
  327.            mfptr->name,mfptr->value,mfptr->point1,mfptr->point2);
  328.       }
  329.    }
  330. /* print values pointed to by rule_type (if & then) */
  331.    printf("\n");
  332.    for(ruleptr=Rule_Base;ruleptr->next!=NULL;ruleptr=ruleptr->next)
  333.    {  printf("Rule #%d:",cnt++);
  334.       for(ifptr=ruleptr->if_side;ifptr!=NULL;ifptr=ifptr->next)
  335.           printf("  %d",*(ifptr->value));
  336.       for(thenptr=ruleptr->then_side;thenptr!=NULL;thenptr=thenptr->next)
  337.           printf("  %d\n",*(thenptr->value));
  338.    }
  339.    printf("\n");
  340. }                                        /* END PUT SYSTEM OUTPUTS */
  341. get_system_inputs(input1,input2)         /* NEW */
  342. int input1, input2;
  343. {  struct io_type *ioptr;
  344.    ioptr=System_Inputs;
  345.    ioptr->value=input1;
  346.    ioptr=ioptr->next;
  347.    ioptr->value=input2;
  348. }                                        /* END GET SYSTEM INPUTS */
  349.  
  350.  
  351. Example 1:
  352.         
  353. #include     <string.h>
  354. #define max(a,b)     (a<b   ? b : a)
  355. #define min(a,b)     (a>b   ? b : a)
  356. struct io_type *System_Inputs;
  357. struct io_type *System_Output;
  358.    
  359.  
  360. Example 2:
  361.  
  362. (a)        
  363.  
  364. if(sum_of_areas==0)
  365. {  printf("Sum     of Areas = 0, will cause div error\n");
  366.    printf("Sum     of Products= %d\n",sum_of_products);
  367.    so->value=0;
  368.    return;
  369. }
  370.         
  371. (b)
  372.  
  373. so->value=sum_of_products/sum_of_areas;
  374.  
  375.  
  376. (c)        
  377.  
  378. int nomatch=0;
  379. ....
  380. for(tp=rule->then_side;tp!=NULL;tp=tp->next)
  381. {  *(tp->value)=max(strength,*(tp->value));
  382.    if(strength>0)nomatch=1;
  383. }
  384. }
  385. if(nomatch==0)printf("NO MATCHING RULES FOUND!\n");
  386.  
  387.  
  388. Figure 1: 
  389.  
  390.               angle
  391.               NL   0    31   31   63
  392.               NM   31   63   63   95
  393.               NS   63   95   95   127
  394.               ZE   95   127  127  159
  395.               PS   127  159  159  191
  396.               PM   159  191  191  223
  397.               PL   191  223  223  255
  398.         
  399.  
  400. Figure 2: 
  401.  
  402. (a)
  403.  
  404. rule 1: IF (angle is NL) AND (velocity is ZE) THEN (force is PL)
  405. rule 2: IF (angle is ZE) AND (velocity is NL) THEN  (force is PL)
  406. rule 3: IF (angle is NM) AND (velocity is ZE) THEN (force is PM)    ....
  407. rule 15: IF (angle is PL) AND (velocity is ZE) THEN (force is NL)
  408.  
  409.  
  410. (b)
  411.         
  412. NL ZE PL
  413. ZE NL PL
  414. NM ZE PM
  415.  ....
  416. PL ZE NL
  417.  
  418.  
  419. Figure 4:
  420.         
  421. rule 1: IF (angle is NL) AND (velocity is ZE) THEN (force is PL)
  422.  
  423.  
  424. Figure 5:
  425.         
  426. fuzz 60 125
  427.  
  428. angle: Value= 60
  429.   NL: Value 21 Left 0 Right 63
  430.   NM: Value 203 Left 31 Right 95
  431.   NS: Value 0 Left 63 Right 127
  432.   ZE: Value 0 Left 95 Right 159
  433.   PS: Value 0 Left 127 Right 191
  434.   PM: Value 0 Left 159 Right 223
  435.   PL: Value 0 Left 191 Right 255
  436.  
  437. velocity: Value=  125
  438.   NL: Value 0 Left 0 Right 64
  439.   NM: Value 0 Left 31 Right 95
  440.   NS: Value 14 Left 63 Right 127
  441.   ZE: Value 210 Left 95 Right 159
  442.   PS: Value 0 Left 127 Right 191
  443.   PM: Value 0 Left 159 Right 223
  444.   PL: Value 0 Left 191 Right 255
  445.  
  446. force: Value= 134
  447.   NL: Value 0 Left 0 Right 63
  448.   NM: Value 203 Left 31 Right 95
  449.   NS: Value 0 Left 63 Right 127
  450.   ZE: Value 0 Left 95 Right 159
  451.   PS: Value 0 Left 127 Right 191
  452.   PM: Value 203 Left 159  Right 223
  453.   PL: Value 21 Left 191 Right 255
  454.  
  455.  
  456.   Rule #1:  21  210  21
  457.   Rule #2:  0  0      21
  458.   Rule #3:  203 210  203
  459.   Rule #4:  0  0      203
  460.   Rule #5:  0  210  0
  461.   Rule #6:  0  14  0
  462.   Rule #7:  0  0      0
  463.   Rule #8:  0  210  0
  464.   Rule #9:  0  0      0
  465.   Rule #10:  0  210  0
  466.   Rule #11:  0  14  0
  467.   Rule #12:  0  0  203
  468.   Rule #13:  203      210  203
  469.   Rule #14:  0  0  0
  470.   Rule #15:  0  210  0
  471.  
  472.  
  473.