📜 ⬆️ ⬇️

Multi-criteria selection of alternatives using fuzzy inference rules. Implementation in Java. Part 2/3: Basic Algorithm

Before reading, I highly recommend reading the first part of the article:
Multi-criteria selection of alternatives using fuzzy inference rules. Part 1/3: Theory

To make a choice, a set of rules is necessary (interface Rule), which includes a set of corresponding fuzzy logic functions (implementing the Function interface) and certain input formalized data (initially representing a two-dimensional array of double elements).

For better convenience, the data (one-dimensional arrays of elements of type double) inside the Rule class is stored in the wrapper class Skill.
')
Next, the rules are passed to the Facade class, which creates fuzzy subsets of them, the sizes of which depend on the number of objects being studied and the required accuracy (specified in the static class Variables).

After finding the general functional solution of this system of subsets (the calcD method), the procedure of comparing the obtained fuzzy subsets in a unit interval is used to obtain the best solution (the calcC method); for this, the powers of these level sets and their point estimates are calculated (calcS method); In this algorithm, the class-structure Num is used to facilitate the required sorting of elements.


At the end of the work, for each object, point estimates will be obtained, the larger value of which corresponds to the best choice (getBest method).

1. Presentation of data.

Dimensions of the matrix D, affecting the accuracy of calculations, are specified by the class Variables

package Variables; public class Variables { private static int SIZE_OF_D = 11; private static double STEP_OF_D = (double)1/(SIZE_OF_D-1); public static int SIZE_OF_D();/*  SIZE_OF_D*/ public static double STEP_OF_D();/*  STEP_OF_D*/ } 


The num class facilitates tricky sorting:

 package Support; public class Num { public double x; public double u; public Num(double x, double u); //  x  u } 


Functions are nothing interesting, just interfaces containing one method and an identifier.

 package Support; public abstract class Function { public String ID; public abstract double getY(double x); } 


Similarly, the Skill class looks like to describe the parameters of each object:

 package Support; public class Skill { public double[] skill; public Skill(double[] skill);/*  skill  */ } 

The Matrix class is written for working with matrices:
 package Support; public class Matrix { private double matrix[][]; public int ROWS; public int COLUMNS; public Matrix(int rows, int columns); //    public Matrix(double[][] m); //    public double[][] getMatrix(); //      public static Matrix findMin(Matrix[] Arr) throws Exception()/*      ,     —  */ { int rows = Arr[0].getMatrix().length; int cols = Arr[0].getMatrix()[0].length; for (int i=0;i<Arr.length;i++) if ((Arr[i].getMatrix().length != rows) || (Arr[i].getMatrix()[0].length != cols)) throw new Exception("Incorrect size of matrix"); double[][] min = new double[rows][cols]; for (int i=0;i<rows;i++) for (int j=0;j<cols;j++) min[i][j]=Double.MAX_VALUE; for (int i=0;i<rows;i++) for (int j=0;j<cols;j++) for (int k=0;k<Arr.length;k++) if (Arr[k].getMatrix()[i][j]<min[i][j]) min[i][j]=Arr[k].getMatrix()[i][j]; return new Matrix(min); } public double[] getRow(int row); //    public void output(); //     } 


Rule - description of the rules:

 package Support; public class Rule{ public Skill[] u; private Function function; public double[] m; public Rule(Skill[] u, Function function) throws Exception{ this.u = u; this.function = function; m = findMin(u); } public double[] findMin(Skill[] arr) throws Exception /*        (   —     )*/ { int size=arr[0].skill.length; for (int i=0;i<arr.length;i++) if (arr[i].skill.length != size) throw new Exception("Incorrect skill"); double[] min = new double[size]; for (int i=0;i<min.length;i++) min[i] = Integer.MAX_VALUE; for (int i=0;i<arr.length;i++) for (int j=0;j<size;j++) if (arr[i].skill[j]< min[j]) min[j] = arr[i].skill[j]; return min; } public double getF(double x){ /* ,   */ return function.getY(x); } } 


SubsetD - used in the formation of matrices D (i) for each of the rules

 package Support; import Variables.Variables; public class SubsetD { private final boolean DEBUG = false; public double[][] d_arr; public SubsetD(Rule rule) throws Exception{ d_arr = makeD(rule); } /*    - */ public double[][] makeD(Rule rule) throws Exception{ d_arr = new double[rule.m.length][Variables.SIZE_OF_D()]; for (int i=0;i<rule.m.length;i++) for (int j=0;j<Variables.SIZE_OF_D();j++){ /*   D,       —      findMin*/ d_arr[i][j]=findMin(1-rule.m[i]+rule.getF(j*Variables.STEP_OF_D())); if (DEBUG) System.out.print("m["+i+"]="+rule.m[i]+"\tj*Variables.STEP_OF_D()="+j*Variables.STEP_OF_D()+"\tY="+rule.getF(j*Variables.STEP_OF_D())+"\n"); } return d_arr; } private double findMin(double x){ if (x>1) return 1; return x; } } 


One of the main classes responsible for data entry is Input:

 package Support; public abstract class Input { protected Rule[] rl = null; protected Function[] func = null; public int PARAMS_CNT = -1; public int FUNC_CNT = -1; public abstract Rule[] makeRules(double[][] arr) throws Exception; //   public abstract void initFunc(Function[] func); //   public Function[] getFunctions(); //    } 


2. Facade

The crown of the algorithm that produces all the required calculations.

 package FLO_Engine; import Variables.Variables; import Support.Matrix; import Support.Rule; import Support.SubsetD; import Support.Num; public class Facade { boolean DEBUG_D = false; boolean DEBUG_C = false; boolean DEBUG_LM = false; Facade(boolean debug_d, boolean debug_c, boolean debug_lm){} /*             */ public Matrix calcD(Rule[] rules) throws Exception{ /*      */ //page 97 Rule[] M = rules; //page 98 SubsetD[] sD = new SubsetD[M.length]; for (int i=0;i<M.length;i++) sD[i] = new SubsetD(M[i]); Matrix[] matr = new Matrix[sD.length]; for (int i=0;i<sD.length;i++){ matr[i]=new Matrix(sD[i].d_arr); if (DEBUG_D) ; /*  D(i)*/ } Matrix min = Matrix.findMin(matr); /*   D*/ if (DEBUG_D) min.output(); return min; } public double[] calcC(Matrix D){ /*   */ int len = D.COLUMNS; double[] c = new double[D.ROWS]; /*   ,    */ double[] x = getX(); /*  X    */ for (int i=0;i<D.ROWS;i++){ double[] u = D.getRow(i); Num[] arr = new Num[len]; for (int j=0;j<len;j++) arr[j]= new Num(x[j],u[j]); for (int j=0;j<len;j++) /*     ,  i-   ,             —         */ for (int k=j;k<len;k++) if (arr[k].u<arr[j].u){ Num temp = arr[k]; arr[k] = arr[j]; arr[j] = temp; } c[i] = calcS(arr); /*     i- */ } return c; } public int getBest(double[] C){} //     private double[] getX(){ /*  X      D*/ double[] temp = new double[Variables.SIZE_OF_D()]; for (int i=0;i<temp.length;i++) temp[i]=Variables.STEP_OF_D()*i; return temp; } private double calcS(num[] arr){ /*      */ int size = arr.length; double[] x = new double[size]; double[] u = new double[size]; for (int i=0;i<size;i++){ /*              */ x[i]=arr[i].x; u[i]=arr[i].u; } double max = findMax(u); /*          */ double s = 0.0; double[] m = new double[size]; double[] lbd = new double[size]; for (int i=0;i<size;i++){ /*     */ if (i==0){ lbd[i]=u[0]; m[i]=calcM(x,0); } else{ lbd[i] = u[i]-u[i-1]; m[i] = calcM(x,i); } } for (int i=0;i<size;i++) /*      */ s+=(double)lbd[i]*m[i]; return (double)s/max; //   } private double findMax(double[] arr){} /*   */ private double calcM(double[] x, int first){ /*   */ double s = 0.0; for (int i=first;i<x.length;i++) s+=x[i]; return (double)s/(x.length-first); } } 


This part does not fit the example of using the above, so the description has to be broken again. The third article will consider an example from a book with explanations, comparing the work of the code and the author’s calculations, and also will demonstrate the writing of functions and rules.

For convenient testing, a gui and an adapter were written in a fast way to the algorithm, allowing not to stitch a set of rules and functions into the code, but loading them from the outside (the class loader had to be done separately) is offtopic, but for those who want to personally run the finished application in the third parts of the article will link to it in the desktop version. Sources included.

Multi-criteria selection of alternatives using fuzzy inference rules. Implementation in Java. Part 3/3: Example

Source: https://habr.com/ru/post/136186/


All Articles