ファジー推論ルールを使用した選択肢の多基準選択。 Java実装。 パート2/3:基本的なアルゴリズム

読む前に、記事の最初の部分を読むことを強くお勧めします。

ファジー推論ルールを使用した選択肢の多基準選択。 パート1/3:理論



選択するには、対応するファジー論理関数(Functionインターフェイスを実装)のセットと特定の形式化された入力データ(最初はdouble要素の2次元配列を表す)を含むルールセット(Ruleインターフェイス)が必要です。



便宜上、Ruleクラス内のデータ(double要素の1次元配列)は、Skillラッパークラスに保存されます。



次に、ルールはFacadeクラスに渡され、ファジーサブセットからファジーサブセットが作成されます。そのサイズは、調査するオブジェクトの数と必要な精度(静的変数クラスで指定)に依存します。



このサブセットシステムの一般的な機能ソリューション(calcDメソッド)を見つけた後、単位間隔で結果のファジーサブセットを比較する手順を適用して、最適なソリューション(calcCメソッド)を取得します。 このために、レベルセットのデータのカーディナリティとそれらのポイント推定値が計算されます(calcSメソッド)。 このアルゴリズムでは、要素の必要なソートを容易にするために、Numクラス構造が使用されます。





作業の最後に、各オブジェクトのポイント推定値が取得されます。この値の大きい方が最適な選択に対応します(getBestメソッド)。



1.データの提示。



計算の精度に影響する行列Dの次元は、変数クラスによって設定されます



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*/ }
      
      







トリッキーなソートを簡単にするnumクラス:



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







関数-興味深いものは何もありません。ただ1つのメソッドと識別子を含むインターフェースです。



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







Skillクラスは、各オブジェクトのパラメーターを説明するために似ています:



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





マトリックスを操作するために、Matrixクラスが記述されています。

 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(); //     }
      
      







ルール-ルールの説明:



 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-各ルールの行列D(i)の形成に使用



 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; } }
      
      







データ入力を担当する主なクラスの1つは入力です:



 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.ファサード



必要な計算をすべて実行するアルゴリズムの王冠。



 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); } }
      
      







前述の使用例はこの部分には当てはまらないため、説明を改める必要があります。 3番目の記事では、説明付きの本の例、コードと著者の計算の比較、および関数とルールの記述について説明します。



このアルゴリズムの便利なテストのために、すぐにGUIとアダプターを作成しました。これにより、一連のルールと関数をコードに縫い付けるのではなく、外部からロードできます(クラスローダーも個別にロードする必要がありました)。記事の一部は、デスクトップバージョンでのリンクになります。 ソースが含まれています。



ファジー推論ルールを使用した選択肢の多基準選択。 Java実装。 パート3/3:例



All Articles