/* layer 6 */ static DOUBLE anfisDivisionNode(FIS *fis, int index, char *action, int index2) { DOUBLE total_wf, total_w; anfisSetupInputArray(fis, index); total_wf = fis->node[index]->input[0]; total_w = fis->node[index]->input[1]; if (total_w == 0) { if (fis->isbias) { fis->skipdatapoint = 1; return 0; } else fisError("Total of firing strength is zero! Type HELP FUZZYZEROFIRING for more information.\n"); } if (strcmp(action, "forward") == 0) return(total_wf/total_w); if (strcmp(action, "backward") == 0) { if (index2 == 0) return(1/total_w); if (index2 == 1) return(-total_wf/(total_w*total_w)); fisError("Wrong index2!\n"); } if (strcmp(action, "parameter") == 0) return(0.0); fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
/* apply given function to an array */ static DOUBLE fisArrayOperation(DOUBLE *array, int size, DOUBLE (*fcn)()) { int i; DOUBLE out; if (size == 0) fisError("Given size is zero!"); out = array[0]; for (i = 1; i < size; i++) out = (*fcn)(out, array[i]); return(out); }
/* layer 1 */ static DOUBLE anfisMfNode(FIS *fis, int index, char *action, int index2) { int which_input = fis->node[index]->fanin->index; int which_mf = fis->node[index]->ll_index; DOUBLE input_value = fis->node[which_input]->value; DOUBLE (*mfFcn)() = fis->input[which_input]->mf[which_mf]->mfFcn; DOUBLE *para = fis->node[index]->para; if (strcmp(action, "forward") == 0) { /* temperary storage for future use */ fis->node[index]->tmp = (*mfFcn)(input_value, para); return(fis->node[index]->tmp); } if (strcmp(action, "backward") == 0) fisError("MF derivatives w.r.t. inputs should not be called!"); if (strcmp(action, "parameter") == 0) { /* temperary storage for future use */ return(fisMfDerivative(mfFcn, input_value, para, index2)); } fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
/* layer 2 */ static DOUBLE anfisInvNode(FIS *fis, int index, char *action, int index2) { int fanin_node_index = fis->node[index]->fanin->index; DOUBLE in_mf_value = fis->node[fanin_node_index]->value; if (strcmp(action, "forward") == 0) return(1.0 - in_mf_value); if (strcmp(action, "backward") == 0) return(-1.0); if (strcmp(action, "parameter") == 0) return(0.0); fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
/* layer 3 */ static DOUBLE anfisAndOrNode(FIS *fis, int index, char *action, int index2) { DOUBLE *input = fis->node[index]->input; int which_rule = fis->node[index]->l_index; int and_or = fis->and_or[which_rule]; DOUBLE (*AndOrFcn)() = and_or == 1? fis->andFcn:fis->orFcn; int i; anfisSetupInputArray(fis, index); if (strcmp(action, "forward") == 0) { fis->node[index]->tmp = fisArrayOperation(input, fis->node[index]->fanin_n, AndOrFcn); return(fis->node[index]->tmp); } if (strcmp(action, "backward") == 0) { if ((AndOrFcn == fisMin) || (AndOrFcn == fisMax)) { for (i = 0; i < fis->node[index]->fanin_n; i++) if (fis->node[index]->tmp == input[i]) break; return(index2 == i? 1.0:0.0); } if (AndOrFcn == fisProduct) { DOUBLE product = 1.0; for (i = 0; i < fis->node[index]->fanin_n; i++) { if (i == index2) continue; product *= input[i]; } return(product); } if (AndOrFcn == fisProbOr) { DOUBLE product = 1.0; for (i = 0; i < fis->node[index]->fanin_n; i++) { if (i == index2) continue; product *= (1 - input[i]); } return(product); } } if (strcmp(action, "parameter") == 0) return(0.0); fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
/* layer 5 */ static DOUBLE anfisSummationNode(FIS *fis, int index, char *action, int index2) { FAN *p, *fanin = fis->node[index]->fanin; DOUBLE sum = 0; for (p = fanin; p != NULL; p = p->next) sum += fis->node[p->index]->value; if (strcmp(action, "forward") == 0) return(sum); if (strcmp(action, "backward") == 0) return(1.0); if (strcmp(action, "parameter") == 0) return(0.0); fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
/* layer 4 */ static DOUBLE anfisRuleOutputNode(FIS *fis, int index, char *action, int index2) { DOUBLE *input; DOUBLE firing_strength; DOUBLE *para = fis->node[index]->para; int i; DOUBLE sum = 0; anfisSetupInputArray(fis, index); input = fis->node[index]->input; /* ========== */ if (fis->order==1) { for (i = 0; i < fis->in_n; i++) sum += input[i]*para[i]; sum += para[fis->in_n]; } else sum = para[0]; firing_strength = input[fis->in_n]; if (strcmp(action, "forward") == 0) return(firing_strength*sum); /* ========== */ if (strcmp(action, "backward") == 0) return(index2 != fis->in_n? fis->order*(firing_strength*para[index2]):sum); /* ========== */ if (strcmp(action, "parameter") == 0) { if (fis->order == 1) return(index2 != fis->in_n? firing_strength*input[index2]:firing_strength); else return(firing_strength); } fisError("Unknown action!\n"); return(0); /* for suppressing compiler's warning only */ }
DOUBLE calc_fuzzy(DOUBLE** dataMatrix, int data_col_n) { // Assume we always have one row of data in this version // i.e., dataMatrix is a type DOUBLE[data_col_n][1] const int data_row_n = 1; const bool debug = false; FIS *fis; DOUBLE **fisMatrix, **outputMatrix; char *fis_file; int fis_row_n, fis_col_n; // NOTE: We need to store this with the GUI exe somehow... fis_file = "bin/fismain.fis"; /* obtain FIS matrix */ fisMatrix = returnFismatrix(fis_file, &fis_row_n, &fis_col_n); /* build FIS data structure */ fis = (FIS *)fisCalloc(1, sizeof(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 ..."); return -1.0; } /* 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 (int i = 0; i < data_row_n; i++) getFisOutput(dataMatrix[i], fis, outputMatrix[i]); /* print output vector */ if(debug) { for (int i = 0; i < data_row_n; i++) { for (int j = 0; j < fis->out_n; j++) PRINTF("%.12f ", outputMatrix[i][j]); PRINTF("\n"); } } DOUBLE fuzzyVal = outputMatrix[0][0]; /* clean up memory */ fisFreeFisNode(fis); fisFreeMatrix((void **)dataMatrix, data_row_n); fisFreeMatrix((void **)fisMatrix, fis_row_n); fisFreeMatrix((void **)outputMatrix, data_row_n); return fuzzyVal; }
/* layer 0 */ static DOUBLE anfisInputNode(FIS *fis, int index, char *action, int index2) { fisError("anfisInputNode should not be called at all!"); return(0); /* for suppressing compiler's warning only */ }