release 0.1.15
[liba.git] / src / pid_fuzzy.c
blobf2ee2b30ca3677c21857519822982bb7fd985ba8
1 #include "a/pid_fuzzy.h"
2 #include "a/mf.h"
4 a_float (*a_pid_fuzzy_opr(unsigned int opr))(a_float, a_float)
6 switch (opr)
8 default:
9 case A_PID_FUZZY_EQU:
10 return a_fuzzy_equ;
11 case A_PID_FUZZY_CAP:
12 return a_fuzzy_cap;
13 case A_PID_FUZZY_CAP_ALGEBRA:
14 return a_fuzzy_cap_algebra;
15 case A_PID_FUZZY_CAP_BOUNDED:
16 return a_fuzzy_cap_bounded;
17 case A_PID_FUZZY_CUP:
18 return a_fuzzy_cup;
19 case A_PID_FUZZY_CUP_ALGEBRA:
20 return a_fuzzy_cup_algebra;
21 case A_PID_FUZZY_CUP_BOUNDED:
22 return a_fuzzy_cup_bounded;
26 void a_pid_fuzzy_set_opr(a_pid_fuzzy *ctx, unsigned int opr) { ctx->opr = a_pid_fuzzy_opr(opr); }
28 A_HIDDEN unsigned int a_pid_fuzzy_mf(a_float x, unsigned int n, a_float const *a, unsigned int *idx, a_float *val);
29 unsigned int a_pid_fuzzy_mf(a_float x, unsigned int n, a_float const *a, unsigned int *idx, a_float *val)
31 unsigned int counter = 0;
32 for (unsigned int i = 0; i != n; ++i)
34 a_float y = 0;
35 switch ((int)*a++)
37 default:
38 case A_MF_NUL: goto out;
39 case A_MF_GAUSS:
40 y = a_mf_gauss(x, a[0], a[1]);
41 a += 2;
42 break;
43 case A_MF_GAUSS2:
44 y = a_mf_gauss2(x, a[0], a[1], a[2], a[3]);
45 a += 4;
46 break;
47 case A_MF_GBELL:
48 y = a_mf_gbell(x, a[0], a[1], a[2]);
49 a += 3;
50 break;
51 case A_MF_SIG:
52 y = a_mf_sig(x, a[0], a[1]);
53 a += 2;
54 break;
55 case A_MF_DSIG:
56 y = a_mf_dsig(x, a[0], a[1], a[2], a[3]);
57 a += 4;
58 break;
59 case A_MF_PSIG:
60 y = a_mf_psig(x, a[0], a[1], a[2], a[3]);
61 a += 4;
62 break;
63 case A_MF_TRAP:
64 y = a_mf_trap(x, a[0], a[1], a[2], a[3]);
65 a += 4;
66 break;
67 case A_MF_TRI:
68 y = a_mf_tri(x, a[0], a[1], a[2]);
69 a += 3;
70 break;
71 case A_MF_LINS:
72 y = a_mf_lins(x, a[0], a[1]);
73 a += 2;
74 break;
75 case A_MF_LINZ:
76 y = a_mf_linz(x, a[0], a[1]);
77 a += 2;
78 break;
79 case A_MF_S:
80 y = a_mf_s(x, a[0], a[1]);
81 a += 2;
82 break;
83 case A_MF_Z:
84 y = a_mf_z(x, a[0], a[1]);
85 a += 2;
86 break;
87 case A_MF_PI:
88 y = a_mf_pi(x, a[0], a[1], a[2], a[3]);
89 a += 4;
90 break;
92 if (y > A_FLOAT_EPSILON)
94 *idx++ = i;
95 *val++ = y;
96 ++counter;
99 out:
100 return counter;
103 void a_pid_fuzzy_set_rule(a_pid_fuzzy *ctx, unsigned int nrule, a_float const *me, a_float const *mec,
104 a_float const *mkp, a_float const *mki, a_float const *mkd)
106 ctx->me = me;
107 ctx->mec = mec;
108 ctx->mkp = mkp;
109 ctx->mki = mki;
110 ctx->mkd = mkd;
111 ctx->nrule = nrule;
114 void *a_pid_fuzzy_bfuzz(a_pid_fuzzy const *ctx) { return ctx->idx; }
115 void a_pid_fuzzy_set_bfuzz(a_pid_fuzzy *ctx, void *ptr, a_size num)
117 ctx->nfuzz = (unsigned int)num;
118 ctx->idx = (unsigned int *)ptr;
119 if (ptr) { ptr = (a_byte *)ptr + 2 * sizeof(unsigned int) * num; }
120 ctx->val = (a_float *)ptr;
123 void a_pid_fuzzy_set_kpid(a_pid_fuzzy *ctx, a_float kp, a_float ki, a_float kd)
125 a_pid_set_kpid(&ctx->pid, kp, ki, kd);
126 ctx->kp = kp;
127 ctx->ki = ki;
128 ctx->kd = kd;
131 A_HIDDEN void a_pid_fuzzy_out_(a_pid_fuzzy *ctx, a_float ec, a_float e);
132 void a_pid_fuzzy_out_(a_pid_fuzzy *ctx, a_float ec, a_float e)
134 a_float kp = 0;
135 a_float ki = 0;
136 a_float kd = 0;
137 /* calculate membership */
138 unsigned int const ne = a_pid_fuzzy_mf(e, ctx->nrule, ctx->me, ctx->idx, ctx->val);
139 if (!ne) { goto pid; }
140 unsigned int *const idx = ctx->idx + ne;
141 a_float *const val = ctx->val + ne;
142 unsigned int const nec = a_pid_fuzzy_mf(ec, ctx->nrule, ctx->mec, idx, val);
143 if (!nec) { goto pid; }
144 a_float *const mat = val + nec;
145 /* joint membership */
146 a_float inv = 0;
148 a_float *it = mat;
149 for (unsigned int i = 0; i != ne; ++i)
151 for (unsigned int j = 0; j != nec; ++j)
153 *it = ctx->opr(ctx->val[i], val[j]); /* mat(i,j)=f(e[i],ec[j]) */
154 inv += *it++;
156 ctx->idx[i] *= ctx->nrule;
159 inv = 1 / inv;
160 /* mean of centers defuzzifier */
161 if (ctx->mkp)
163 a_float const *it = mat;
164 for (unsigned int i = 0; i != ne; ++i)
166 a_float const *const mkp = ctx->mkp + ctx->idx[i];
167 for (unsigned int j = 0; j != nec; ++j)
169 kp += *it++ * mkp[idx[j]]; /* += mat(i,j) * mkp(e[i],ec[j]) */
172 kp *= inv;
174 if (ctx->mki)
176 a_float const *it = mat;
177 for (unsigned int i = 0; i != ne; ++i)
179 a_float const *const mki = ctx->mki + ctx->idx[i];
180 for (unsigned int j = 0; j != nec; ++j)
182 ki += *it++ * mki[idx[j]]; /* += mat(i,j) * mki(e[i],ec[j]) */
185 ki *= inv;
187 if (ctx->mkd)
189 a_float const *it = mat;
190 for (unsigned int i = 0; i != ne; ++i)
192 a_float const *const mkd = ctx->mkd + ctx->idx[i];
193 for (unsigned int j = 0; j != nec; ++j)
195 kd += *it++ * mkd[idx[j]]; /* += mat(i,j) * mkd(e[i],ec[j]) */
198 kd *= inv;
200 pid:
201 a_pid_set_kpid(&ctx->pid, ctx->kp + kp, ctx->ki + ki, ctx->kd + kd);
204 A_HIDDEN a_float a_pid_run_(a_pid *ctx, a_float set, a_float fdb, a_float err);
205 a_float a_pid_fuzzy_run(a_pid_fuzzy *ctx, a_float set, a_float fdb)
207 a_float const err = set - fdb;
208 a_pid_fuzzy_out_(ctx, err - ctx->pid.err, err);
209 return a_pid_run_(&ctx->pid, set, fdb, err);
212 A_HIDDEN a_float a_pid_pos_(a_pid *ctx, a_float fdb, a_float err);
213 a_float a_pid_fuzzy_pos(a_pid_fuzzy *ctx, a_float set, a_float fdb)
215 a_float const err = set - fdb;
216 a_pid_fuzzy_out_(ctx, err - ctx->pid.err, err);
217 return a_pid_pos_(&ctx->pid, fdb, err);
220 A_HIDDEN a_float a_pid_inc_(a_pid *ctx, a_float fdb, a_float err);
221 a_float a_pid_fuzzy_inc(a_pid_fuzzy *ctx, a_float set, a_float fdb)
223 a_float const err = set - fdb;
224 a_pid_fuzzy_out_(ctx, err - ctx->pid.err, err);
225 return a_pid_inc_(&ctx->pid, fdb, err);
228 void a_pid_fuzzy_zero(a_pid_fuzzy *ctx) { a_pid_zero(&ctx->pid); }