移植Matlab的底層模糊邏輯控制庫(C語言)

        Matlab擁有很多好用的Toolbox,如遺傳算法,模糊邏輯控制(Fuzzy Logic Control,FLC),神經網絡等等,一般都是大神寫的,然後提交給Matlab公司,接着審覈之後加入到新的版本中,大致的看了下Toolbox文件夾下面的各個庫代碼,大部分是用matlab語言寫的,但是有些是採用C語言寫的(貌似 Matlab程序本身就是採用C/C++寫的,所以m語言和C語言之間可以很好的調用來調用去的。)
        雖然說FLC不是太複雜,自己寫一個也不會太難,但是當我看了matlab下面的FLC庫文件的C語言實現,我覺得還是算了,因爲他(就是ANFIS的發明者——Jyh-Shing Roger Jang(張智星),Zadeh的學生)在對模糊的理解之上寫的相當的完備。
Step 1. 進入Toolbox文件夾,找到如下兩個C文件

Step 2. “fis.c”文件時FLC實現部分,一般不用動它。現在來看看“fismain.c”部分,它調用前者的API。
 原版的fismain.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * Stand-alone codes for fuzzy inference systems.
 * J.-S. Roger Jang, 1994.
 * Copyright 1994-2002 The MathWorks, Inc.
 * $Revision: 1.12 $  $Date: 2002/06/17 12:47:24 $
 */


/* This part is for MACs only */
#if defined(applec) || defined(__MWERKS__) || defined (THINK_C) || defined(powerc)

#include <stdio.h>
#include <stdarg.h>

FILE    *output_file;

#define PRINTF macprintf

int macprintf(char* format, ...)    
{
    va_list arg;
    int     ret;
    
    va_start(arg, format);
    ret = vfprintf(output_file, format, arg);
    va_end(arg);
    
    return(ret);
}
#endif /* applec || __MWERKS__ || THINK_C || powerc */

/* Start of the regular fismain.c */
/* 這裏要改,當然include還是展開,但是我們把它放在vs2008裏面,方便管理,還是用.h頭文件吧。 */
#include "fis.c"

/***********************************************************************
 Main routine 
 **********************************************************************/


int
main(int argc, char **argv)
{
    FIS *fis;
    int i, j;
    int debug = 0;

    DOUBLE **dataMatrix, **fisMatrix, **outputMatrix;
    char *fis_file, *data_file;
    int data_row_n, data_col_n, fis_row_n, fis_col_n;
/* 這裏也要改,讀取我們的配置文件——FLC有很多需要選擇的參數以及方法 */
#if defined(applec) || defined(__MWERKS__) || defined (THINK_C) || defined(powerc)
    /* For MACs only */
    data_file = "fismain.in";
    fis_file = "fismain.fis";
    output_file = fisOpenFile("fismain.out","w");
#else
    /* input arguments checking */
    if (argc != 3) {
        PRINTF("Usage: %s data_file fis_file\n", argv[0]);
        exit(1);
    }
    data_file = argv[1];
    fis_file = argv[2];
#endif /* applec || __MWERKS__ || THINK_C || powerc */

    /* obtain data matrix and FIS matrix */
    dataMatrix = returnDataMatrix(data_file, &data_row_n, &data_col_n);
    fisMatrix = returnFismatrix(fis_file, &fis_row_n, &fis_col_n);

    /* build FIS data structure */
    fis = (FIS *)fisCalloc(1sizeof(FIS));
    fisBuildFisNode(fis, fisMatrix, fis_col_n, MF_POINT_N);

    /* error checking */
    if (data_col_n < fis->in_n) {
        PRINTF("Given FIS is a %d-input %d-output system.\n",
            fis->in_n, fis->out_n);
        PRINTF("Given data file does not have enough input entries.\n");
        fisFreeMatrix((void **)dataMatrix, data_row_n);
        fisFreeMatrix((void **)fisMatrix, fis_row_n);
        fisFreeFisNode(fis);
        fisError("Exiting ...");
    }

    /* debugging */
    if (debug)
        fisPrintData(fis);

    /* create output matrix */
    outputMatrix = (DOUBLE **)fisCreateMatrix(data_row_n, fis->out_n, sizeof(DOUBLE));

    /* evaluate FIS on each input vector */
    for (i = 0; i < data_row_n; i++)
        getFisOutput(dataMatrix[i], fis, outputMatrix[i]);

    /* print output vector */
    for (i = 0; i < data_row_n; i++) {
        for (j = 0; j < fis->out_n; j++)
            PRINTF("%.12f ", outputMatrix[i][j]);
        PRINTF("\n");
    }

    /* clean up memory */
    fisFreeFisNode(fis);
    fisFreeMatrix((void **)dataMatrix, data_row_n);
    fisFreeMatrix((void **)fisMatrix, fis_row_n);
    fisFreeMatrix((void **)outputMatrix, data_row_n);
    exit(0);
}

大致需要改的,就是所指出來得兩部分。很簡單的,直接看修改後的代碼。
Step 3. 修改
 修改後的main.c 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * Stand-alone codes for fuzzy inference systems.
 * J.-S. Roger Jang, 1994.
 * Copyright 1994-2002 The MathWorks, Inc.
 * $Revision: 1.12 $  $Date: 2002/06/17 12:47:24 $
 */

/* Start of the regular main.c */
#include "fis.h"

/***********************************************************************
 Main routine 
 **********************************************************************/

int main(int argc, char **argv)
{
    FIS *fis;
    int i, j;
    int debug = 1;

    double **dataMatrix, **fisMatrix, **outputMatrix;
    char *fis_file, *data_file;
    int data_row_n, data_col_n, fis_row_n, fis_col_n;

    data_file = "dataMatrixFile.txt";
    fis_file = "fisMatrixFile.txt";

    /* obtain data matrix and FIS matrix 從文件讀入輸入數據矩陣和模糊矩陣,將其放入二維矩陣中*/
    dataMatrix = returnDataMatrix(data_file, &data_row_n, &data_col_n);
    fisMatrix = returnFismatrix(fis_file, &fis_row_n, &fis_col_n);

    /* build FIS data structure 建立模糊數據結構*/
    fis = (FIS *)fisCalloc(1sizeof(FIS));
    /*將fisMatrix中的數據導入到fis中*/
    fisBuildFisNode(fis, fisMatrix, fis_col_n, MF_POINT_N);

    /* error checking 錯誤檢測*/
    if (data_col_n < fis->in_n) {
        printf("Given FIS is a %d-input %d-output system.\n",
            fis->in_n, fis->out_n);
        printf("Given data file does not have enough input entries.\n");
        fisFreeMatrix((void **)dataMatrix, data_row_n);
        fisFreeMatrix((void **)fisMatrix, fis_row_n);
        fisFreeFisNode(fis);
        fisError("Exiting ...");
    }

    /* fisDebugging 調試數據輸出*/
    if (debug)
        fisPrintData(fis);

    /* create output matrix 創建輸出矩陣5x1*/
    outputMatrix = (double **)fisCreateMatrix(data_row_n, fis->out_n, sizeof(double));

    /* evaluate FIS on each input vector 獲取輸入->開始模糊推理->輸出矩陣*/
    for (i = 0; i < data_row_n; i++)
        getFisOutput(dataMatrix[i], fis, outputMatrix[i]);

    /* print output vector 得到輸出並打印*/
    for (i = 0; i < data_row_n; i++) {
        for (j = 0; j < fis->out_n; j++)
            printf("%.12f ", outputMatrix[i][j]);
        printf("\n");
    }

    /* clean up memory 清理內存*/
    fisFreeFisNode(fis);
    fisFreeMatrix((void **)dataMatrix, data_row_n);
    fisFreeMatrix((void **)fisMatrix, fis_row_n);
    fisFreeMatrix((void **)outputMatrix, data_row_n);

    getchar();
    return 0;
}

 當然還有我們的fis.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#ifndef __FIS_H__
# define __FIS_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/***********************************************************************
 Macros and definitions
 **********************************************************************/

/* Define portable printf and DOUBLE */
#if defined(MATLAB_MEX_FILE)
# define PRINTF mexPrintf
# define DOUBLE real_T
#elif defined(__SIMSTRUC__)
# define PRINTF ssPrintf
# define DOUBLE real_T
#else
# define PRINTF printf
# define DOUBLE double
#endif

#ifndef ABS
# define ABS(x)   ( (x) > (0) ? (x): (-(x)) )
#endif
#ifndef MAX
# define MAX(x,y) ( (x) > (y) ? (x) : (y) )
#endif
#ifndef MIN
# define MIN(x,y) ( (x) < (y) ? (x) : (y) )
#endif
#define MF_PARA_N 4
#define STR_LEN 500
#define MF_POINT_N 101

/* debugging macros */
/*
#define PRINT(expr) printf(#expr " = %g\n", (DOUBLE)expr)
#define PRINTMAT(mat,m,n) printf(#mat " = \n"); fisPrintMatrix(mat,m,n)
#define FREEMAT(mat,m) printf("Free " #mat " ...\n"); fisFreeMatrix(mat,m)
#define FREEARRAY(array) printf("Free " #array " ...\n"); free(array)
*/


#if (defined(MATLAB_MEX_FILE) && !defined(__SIMSTRUC__))
# define FREE mxFree
#else
# define FREE free
#endif

#define FREEMAT(mat,m) fisFreeMatrix(mat,m)
#define FREEARRAY(array) FREE(array)

/***********************************************************************
 Data types
 **********************************************************************/


typedef struct fis_node {
    int handle;
    int load_param;
    char name[STR_LEN];
    char type[STR_LEN];
    char andMethod[STR_LEN];
    char orMethod[STR_LEN];
    char impMethod[STR_LEN];
    char aggMethod[STR_LEN];
    char defuzzMethod[STR_LEN];
    int userDefinedAnd;
    int userDefinedOr;
    int userDefinedImp;
    int userDefinedAgg;
    int userDefinedDefuzz;
    int in_n;
    int out_n;
    int rule_n;
    int **rule_list;
    DOUBLE *rule_weight;
    int *and_or;    /* AND-OR indicator */
    DOUBLE *firing_strength;
    DOUBLE *rule_output;
    /* Sugeno: output for each rules */
    /* Mamdani: constrained output MF values of rules */
    struct io_node **input;
    struct io_node **output;
    DOUBLE (*andFcn)(DOUBLE, DOUBLE);
    DOUBLE (*orFcn)(DOUBLE, DOUBLE);
    DOUBLE (*impFcn)(DOUBLE, DOUBLE);
    DOUBLE (*aggFcn)(DOUBLE, DOUBLE);
    DOUBLE (*defuzzFcn)();
    DOUBLE *BigOutMfMatrix; /* used for Mamdani system only */
    DOUBLE *BigWeightMatrix;/* used for Mamdani system only */
    DOUBLE *mfs_of_rule;    /* MF values in a rule */

    DOUBLE *bias; /*bias, to be tuned when no rules are fired*/
    int isbias;

    struct fis_node *next;
} FIS;



typedef struct io_node {
    char name[STR_LEN];
    int mf_n;
    DOUBLE bound[2];
    DOUBLE value;
    struct mf_node **mf;
} IO;



typedef struct mf_node {
    char label[STR_LEN];    /* MF name */
    char type[STR_LEN];     /* MF type */
    int nparams;            /* length of params field */
    DOUBLE *params;         /* MF parameters */
    int userDefined;        /* 1 if the MF is user-defined */
    DOUBLE (*mfFcn)(DOUBLE, DOUBLE *); /* pointer to a mem. fcn */ 
    DOUBLE value;           /* for Sugeno only */
    DOUBLE *value_array;    /* for Mamdani only, array of MF values */
} MF;


/***********************************************************************
some redefinition universal functions 
 **********************************************************************/

/* display error message and exit */
void fisError(char *msg);

/* define a standard memory access function with error checking */
void *fisCalloc(int num_of_x, int size_of_x);

char **fisCreateMatrix(int row_n, int col_n, int element_size);
void fisFreeMatrix(void **matrix, int row_n);

/***********************************************************************
 Data structure: construction, printing, and destruction 
 **********************************************************************/


/* Build/Free FIS node and load parameter from fismatrix directly */
/* col_n is the number of columns of the fismatrix */
void fisBuildFisNode(FIS *fis, DOUBLE **fismatrix, int col_n, int numofpoints);
void fisFreeFisNode(FIS *fis);

void fisPrintData(FIS *fis);

/***********************************************************************
 Evaluate the constructed FIS based on given input vector 
 **********************************************************************/


/* given input vector and FIS data structure, return output */
/* this is a wrap-up on fisEvaluate() */  
void getFisOutput(DOUBLE *input, FIS *fis, DOUBLE *output);

/* return a FIS matrix with all information */
DOUBLE **returnFismatrix(char *fis_file, int *row_n_p, int *col_n_p);

/* return data matrix */
DOUBLE **returnDataMatrix(char *filename, int *row_n_p, int *col_n_p);

#endif /* __FIS__ */





Step 4. 編寫配置文件
我們另外還需要兩個配置文件:
    data_file = "dataMatrixFile.txt";   //輸入數據 
    fis_file = "fisMatrixFile.txt";    //方法及其參數選擇
給一個示例如下:
 fisMatrixFile.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
[System]
Name='Fuzzy1'
Type='mamdani'
Version=2.0
NumInputs=3
NumOutputs=1
NumRules=27
AndMethod='min'
OrMethod='max'
ImpMethod='prod'
AggMethod='sum'
DefuzzMethod='mom'

[Input1]
Name='QueueLength'
Range=[0 20]
NumMFs=3
MF1='Low':'trapmf',[0 0 6 8]
MF2='Median':'trapmf',[6 8 12 14]
MF3='High':'trapmf',[12 14 20 20]

[Input2]
Name='RTime'
Range=[0 70]
NumMFs=3
MF1='Low':'trapmf',[0 0 20 30]
MF2='Median':'trapmf',[20 30 40 50]
MF3='High':'trapmf',[40 50 70 70]

[Input3]
Name='DownFlow'
Range=[0 80]
NumMFs=3
MF1='Small':'trapmf',[0 0 10 30]
MF2='Median':'trapmf',[10 30 50 70]
MF3='Large':'trapmf',[50 70 80 80]

[Output1]
Name='ppd'
Range=[0 1]
NumMFs=3
MF1='Small':'trapmf',[0 0 0.2 0.4]
MF2='Median':'trapmf',[0.2 0.4 0.6 0.8]
MF3='Large':'trapmf',[0.6 0.8 1 1]

[Rules]
1 1 11 (1) : 1
1 1 21 (1) : 1
1 1 31 (1) : 1
1 2 11 (1) : 1
1 2 21 (1) : 1
1 2 31 (1) : 1
1 3 11 (1) : 1
1 3 21 (1) : 1 
1 3 31 (1) : 1
2 1 12 (1) : 1
2 1 22 (1) : 1
2 1 32 (1) : 1
2 2 12 (1) : 1
2 2 22 (1) : 1
2 2 32 (1) : 1
2 3 12 (1) : 1
2 3 22 (1) : 1
2 3 32 (1) : 1
3 1 13 (1) : 1
3 1 23 (1) : 1
3 1 33 (1) : 1
3 2 13 (1) : 1
3 2 23 (1) : 1
3 2 33 (1) : 1
3 3 13 (1) : 1
3 3 23 (1) : 1
3 3 33 (1) : 1

 dataMatrixFile.txt
1
2
3
4
5
0 0 0
2 7 8
10 35 40
16 41 64
20 70 80

Step 5. 新建工程並驗證

dataMatrixFile.txt有四組輸入,看結果如下:


看和我們手算的一不一樣呢?

至於配置文件裏面的每一項內容,看到這裏的同學肯定是曉得了,就不囉嗦了~~~
good luck~~~

末了,附上工程文件,猛戳此處


發佈了55 篇原創文章 · 獲贊 35 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章