/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. S�nchez (luciano@uniovi.es) J. Alcal�-Fdez (jalcala@decsai.ugr.es) S. Garc�a (sglopez@ujaen.es) A. Fern�ndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ **********************************************************************/ package keel.Algorithms.Fuzzy_Rule_Learning.Genetic.ClassifierMOGUL; import java.util.*; /** * <p> * It encodes a Rule Base for the simplification process * </p> * * <p> * @author Written by Jesus Alcala Fernandez (University of Granada) 01/01/2004 * @author Modified by Francisco Jos� Berlanga (University of Ja�n) 09/12/2008 * @version 1.0 * @since JDK 1.6 * </p> */ public class RuleBase_Sel { public Rule[] BaseReglas; public char[] modificador; public int max_reglas; public int tipo_reglas, tipo_modificadores, n_etiquetas; public int n_reglas; public MyDataset tabla; public double[] GradoEmp; /** * <p> * Constructor * </p> * @param fichero String The name of the file containing the previous learned RB * @param datos MyDataset The set of examples * @param tipo1 int The type of fuzzy rule * @param tipo2 int The type of liguistic modifier * @param num_etiq int The number of liguistic labels per variable */ public RuleBase_Sel(String fichero, MyDataset datos, int tipo1, int tipo2, int num_etiq) { int i; int n_genes_modificadores = 0; tabla = datos; tipo_reglas = tipo1; tipo_modificadores = tipo2; n_etiquetas = num_etiq; leer_BR(fichero); switch (tipo_modificadores) { case 0: n_genes_modificadores = 0; break; case 1: n_genes_modificadores = tabla.n_inputs * n_etiquetas; break; case 2: n_genes_modificadores = tabla.n_inputs * n_reglas; break; } modificador = new char[n_genes_modificadores]; GradoEmp = new double[n_reglas]; } /** * <p> * Constructor * </p> * @param Max_reglas The maximum number of rules in the RB * @param datos MyDataset The set of examples * @param tipo1 int The type of fuzzy rule * @param tipo2 int The type of liguistic modifier * @param num_etiq int The number of liguistic labels per variable */ public RuleBase_Sel(int Max_reglas, MyDataset datos, int tipo1, int tipo2, int num_etiq) { int i, j; int n_genes_modificadores = 0; tabla = datos; n_reglas = 0; max_reglas = Max_reglas; tipo_reglas = tipo1; tipo_modificadores = tipo2; n_etiquetas = num_etiq; BaseReglas = new Rule[max_reglas]; switch (tipo_modificadores) { case 0: n_genes_modificadores = 0; break; case 1: n_genes_modificadores = tabla.n_inputs * n_etiquetas; break; case 2: n_genes_modificadores = tabla.n_inputs * max_reglas; break; } modificador = new char[n_genes_modificadores]; GradoEmp = new double[max_reglas]; for (i = 0; i < max_reglas; i++) { BaseReglas[i] = new Rule(tabla.n_inputs, tabla.n_variables); } } /** * <p> * Reads the previous learned RB from a input file * </p> * @param fichero String The name of the file containing the learned RB */ public void leer_BR(String fichero) { int i, j; String cadena; cadena = MyFile.ReadMyFile(fichero); StringTokenizer sT = new StringTokenizer(cadena, "\n\r\t ", false); sT.nextToken(); sT.nextToken(); sT.nextToken(); n_reglas = Integer.parseInt(sT.nextToken()); BaseReglas = new Rule[n_reglas]; for (i = 0; i < n_reglas; i++) { BaseReglas[i] = new Rule(tabla.n_inputs, tabla.nClasses); } for (i = 0; i < n_reglas; i++) { for (j = 0; j < tabla.n_inputs; j++) { BaseReglas[i].Ant[j].Etiqueta = sT.nextToken(); BaseReglas[i].Ant[j].x0 = Double.parseDouble(sT.nextToken()); BaseReglas[i].Ant[j].x1 = Double.parseDouble(sT.nextToken()); BaseReglas[i].Ant[j].x2 = BaseReglas[i].Ant[j].x1; BaseReglas[i].Ant[j].x3 = Double.parseDouble(sT.nextToken()); BaseReglas[i].Ant[j].y = 1.0; } switch (tipo_reglas) { case 1: sT.nextToken(); BaseReglas[i].Cons[0].clase = Integer.parseInt(sT.nextToken()); break; case 2: sT.nextToken(); BaseReglas[i].Cons[0].clase = Integer.parseInt(sT.nextToken()); sT.nextToken(); BaseReglas[i].Cons[0].gcerteza = Double.parseDouble(sT. nextToken()); break; case 3: for (j = 0; j < tabla.nClasses; j++) { sT.nextToken(); BaseReglas[i].Cons[j].clase = Integer.parseInt(sT.nextToken()); sT.nextToken(); BaseReglas[i].Cons[j].gcerteza = Double.parseDouble(sT. nextToken()); } } } } /* ------------------------------------------------------------------------- Fuzzification Interface ------------------------------------------------------------------------- */ /** * <p> * Fuzzification Interface * </p> * @param X double The value of the example * @param D FuzzySet The fuzzy set * @return The fuzzification value **/ public double Fuzzification(double X, FuzzySet D) { /* If X are not in the rank D, the degree is 0 */ if ((X < D.x0) || (X > D.x3)) { return (0); } if (X < D.x1) { return ((X - D.x0) * (D.y / (D.x1 - D.x0))); } if (X > D.x2) { return ((D.x3 - X) * (D.y / (D.x3 - D.x2))); } return (D.y); } /* ------------------------------------------------------------------------- Conjunction Operator ------------------------------------------------------------------------- */ /** * <p> * Minimum T-norm * </p> * @param entradas double[] The given example **/ public void Min(double[] entradas) { int b, b2; double minimo, y; for (b = 0; b < n_reglas; b++) { minimo = Fuzzification(entradas[0], BaseReglas[b].Ant[0]); for (b2 = 1; (minimo != 0.0) && (b2 < tabla.n_inputs); b2++) { y = Fuzzification(entradas[b2], BaseReglas[b].Ant[b2]); if (y < minimo) { minimo = y; } } GradoEmp[b] = minimo; } } /* ------------------------------------------------------------------------- Inference of a TSK Fuzzy System ------------------------------------------------------------------------- */ /* public double Inferencia_TSK (double [] Entrada) { double num, den, salida_regla; int i, j; num = 0; den = 0; for (i=0; i < n_reglas; i++) { if (GradoEmp[i] != 0.0) { */ /* we initialize the output to the 'b' value */ /* salida_regla = BaseReglas[i].Cons[tabla.n_inputs]; for (j=0; j<tabla.n_inputs; j++) salida_regla += BaseReglas[i].Cons[j] * Entrada[j]; num += GradoEmp[i] * salida_regla; den += GradoEmp[i]; } } if (den != 0) return (num / den); else return ((tabla.extremos[tabla.n_inputs].max - tabla.extremos[tabla.n_inputs].min)/2.0); } */ /* ------------------------------------------------------------------------- Fuzzy Controller ------------------------------------------------------------------------- */ /* public double FLC_TSK (double [] Entrada) { Min (Entrada); return (Inferencia_TSK (Entrada)); } */ /** * <p> * Prints the RB to a String * </p> * @return String The BR as a String object */ public String BRtoString() { int i, j; String cadena = ""; cadena += "Number of rules: " + n_reglas + "\n\n"; for (i = 0; i < n_reglas; i++) { for (j = 0; j < tabla.n_inputs; j++) { cadena += "" + BaseReglas[i].Ant[j].Etiqueta + " " + BaseReglas[i].Ant[j].x0 + " " + BaseReglas[i].Ant[j].x1 + " " + BaseReglas[i].Ant[j].x3 + "\n"; } switch (tipo_reglas) { case 1: cadena += "Class " + BaseReglas[i].Cons[0].clase + "\n"; break; case 2: cadena += "Class " + BaseReglas[i].Cons[0].clase + " CertaintyDegree " + BaseReglas[i].Cons[0].gcerteza + "\n"; break; case 3: for (j = 0; j < tabla.nClasses; j++) { cadena += "Class " + BaseReglas[i].Cons[j].clase + " CertaintyDegree " + BaseReglas[i].Cons[j].gcerteza + "\n"; } } cadena += "\n"; if (tipo_modificadores == 2) { /* Hedges by partition/rule */ cadena += "Hedges of the rule " + (i + 1) + ":\n"; for (j = 0; j < tabla.n_inputs; j++) { switch (modificador[(tabla.n_inputs * i) + j]) { case '0': cadena += "Var " + (j + 1) + "\t No hedge\n"; break; case '1': cadena += "Var " + (j + 1) + "\t More or less\n"; break; case '2': cadena += "Var " + (j + 1) + "\t Very\n"; break; } } cadena += "\n"; } } if (tipo_modificadores == 1) { cadena += "Hedges by partition:\n"; for (j = 0; j < tabla.n_inputs; j++) { cadena += "Variable " + (j + 1) + "\n"; for (i = 0; i < n_etiquetas; i++) { switch (modificador[(j * n_etiquetas) + i]) { case '0': cadena += "\tL " + (i + 1) + "\t No hedge\n"; break; case '1': cadena += "\tL " + (i + 1) + "\t More or Less\n"; break; case '2': cadena += "\tL " + (i + 1) + "\t Very\n"; } } } } cadena += "\n"; return (cadena); } }