JAVA實現雙邊決策

 現實生活中存在不少問題,好比商品買賣如何實現商家利潤最大化?大學生招生錄取如何實現總體效果最好?病人醫生如何實現總體服務水平最高等?這些咱們均可以把他統一的轉化爲雙邊決策問題。下面先說說本身對雙邊決策的理解。html

 

雙邊決策——我的理解java

      爲了幫助你們理解,我用一個簡單的例子介紹什麼是雙邊決策,加入如今市場上有10位顧客,分別爲A0、A一、A二、A三、A四、A五、A六、A七、A八、A9,市場上有是個商品,分別爲B0、B一、B二、B三、B四、B五、B六、B七、B八、B9,如今要求要把這10個商品分別分給這10位顧客,要求總體的滿意程度最高,固然每位顧客對每一個商品的打分是不同的,加入M位顧客對N件商品的滿意度爲AMBN,那麼如何分配這些商品才能使總體的滿意度最高?像這個爲題就是一個雙邊決策問題。算法

 

算法介紹數組

      目前關於雙邊決策的實現算法有不少,下面就介紹一種本身想到的(若有雷同,純屬巧合),這個算法是基於以前本身寫的一篇遺傳算法的文章想到的。本身這個算法要求顧客和商品的數目必須一致,而且是一對一的關係,若是數目不一致或者是一對N(N是一個具體值)的時候,咱們能夠經過構建虛擬的商品(顧客)來使用這個算法,下面我就簡單介紹下算法思想:app

1)咱們首先選取一個分配方案,這裏咱們不防假定初始的分配方案就是M件商品分給M位顧客;ide

2)咱們將比較步長step設置爲1;測試

3)判斷step是否超過數組長度,若是超過結束算法,若是沒超過繼續執行下一步;this

4)比較step步長下的兩位顧客,假設將他們的分配方案對調,若是對調以後的滿意度大於對調前的滿意度就進行對調,不然保持原樣,將比較位日後移動一位繼續進行第4)步;spa

5)該步長step下已經沒有能夠對調的分配方案,將步長step加1;.net

6)跳到第3)步繼續執行。

 

      在上述算法描述中,咱們重點介紹下第4)步,這裏咱們假設第1位顧客分配的商品是1號商品,第2位顧客分配的商品是2號商品,他們對商品的滿意度分別爲A1B一、A2B2,這時這兩個顧客的整體滿意度爲SCORE1=A1B1+A2B2,這裏咱們將他們的分配方案對調,也就是第1位顧客分配的商品是2號商品,第2位顧客分配的商品是1號商品,這時候他們對商品的滿意度分別爲A1B二、A2B1,這兩個顧客的總體滿意度爲SCORE2=A1B2+A2B1,若是SCORE1小於SCORE2,那麼咱們就改變分配策略,不然保持原來的分配策略。

 

Java代碼分析

      對於上面的介紹也許並非太具體,或者並不知道用JAVA如何實現,下面咱們就對如何實現作拆解:

1)在寫算法的時候,咱們首先須要定義一些常量、保存分配方案等:

 

[java] view plain copy

 print?

  1. public class TwoSidedDecision {  
  2.     private int num = 10;//個體數目  
  3.     private boolean maxFlag = true;//是否求最大值  
  4.     private int[][] scoreArray;//AB之間的互評得分  
  5.     private int[] decisionArray;//A選擇B的方式  
  6. }  

      這裏有一個maxFlag屬性,他的做用是用來標識咱們的雙邊決策是要取最大值仍是要取最小值,true表示最大值,false表示最小值;num用來標識個體的個數,scoreArray數組用來表示用戶對商品的滿意度,decisionArray用來保存商品的分配方案,decisionArray[0]表示編號爲0的顧客分配的商品是decisionArray[0];

 

2)在運行算法以前,咱們須要設置個體數目

 

[java] view plain copy

 print?

  1. public void setNum(int num) {  
  2.     if (num < 1) {  
  3.         System.out.println("num must be greater than 0");  
  4.         return;  
  5.     }  
  6.     this.num = num;  
  7. }  


3)顧客對商品進行滿意度打分並肯定初始分配方案

 

[java] view plain copy

 print?

  1. public void setScoreArray(int[][] scoreArray) {  
  2.     if (scoreArray == null) {  
  3.         System.out.println("scoreArray is null");  
  4.     }  
  5.     if (!(scoreArray.length == num && scoreArray[0].length == num)) {  
  6.         System.out.println("scoreArray`s must be " + num);  
  7.     }  
  8.     this.scoreArray = scoreArray;  
  9.     decisionArray = new int[num];  
  10.     //初始決策,對角線  
  11.     for (int i = 0; i < num; i++) {  
  12.         decisionArray[i] = i;  
  13.     }  
  14.     decision();  
  15. }  

 

 

4)而後進行算法描述中的第4)步,確認分配方案是否對調

 

[java] view plain copy

 print?

  1. private boolean compare(int stepSize) {  
  2.     for (int i = 0; i < num - stepSize; i++) {  
  3.         int a1 = i;  
  4.         int a2 = i + stepSize;  
  5.         int b1 = decisionArray[a1];  
  6.         int b2 = decisionArray[a2];  
  7.         //原始兩個得分之和  
  8.         int score1 = scoreArray[a1][b1] + scoreArray[a2][b2];  
  9.         int between1 = Math.abs(scoreArray[a1][b1] - scoreArray[a2][b2]);  
  10.         //交換後的兩個得分之和  
  11.         int score2 = scoreArray[a1][b2] + scoreArray[a2][b1];  
  12.         int between2 = Math.abs(scoreArray[a1][b2] - scoreArray[a2][b1]);  
  13.         if (maxFlag) { //最後的得分最大  
  14.             if (score1 <= score2) {//交換後的分數不小於交換前的  
  15.                 //交換後的分數大於交換前的或者交換後的差值大於交換前的  
  16.                 if (score1 < score2 || between2 > between1) {  
  17.                     decisionArray[a1] = b2;  
  18.                     decisionArray[a2] = b1;  
  19.                     return true;  
  20.                 }  
  21.             }  
  22.         } else { //最後的得分最小  
  23.             if (score1 >= score2) {//交換後的分數不小於交換前的  
  24.                 //交換後的分數大於交換前的或者交換後的差值大於交換前的  
  25.                 if (score1 > score2 || between2 > between1) {  
  26.                     decisionArray[a1] = b2;  
  27.                     decisionArray[a2] = b1;  
  28.                     return true;  
  29.                 }  
  30.             }  
  31.         }  
  32.     }  
  33.     return false;  
  34. }  

 

 

      這個方法的返回值是確認該步長下是否發生對調,若是該步長沒有發生對調,咱們能夠進行下一個步長的比較。這樣就完成了雙邊決策算法,下面咱們看一下測試結果。

 

運行結果

最大值測試

img

 

最小值測試

img

 

完整代碼

 

[java] view plain copy

 print?

  1.  /**   
  2.  *@Description: 雙邊匹配決策算法 
  3.  */   
  4. package com.lulei.twosided.matching.decisionmaking;    
  5.   
  6. import com.lulei.util.JsonUtil;  
  7.     
  8. public class TwoSidedDecision {  
  9.     private int num = 10;//個體數目  
  10.     private boolean maxFlag = true;//是否求最大值  
  11.     private int[][] scoreArray;//AB之間的互評得分  
  12.     private int[] decisionArray;//A選擇B的方式  
  13.       
  14.     public boolean isMaxFlag() {  
  15.         return maxFlag;  
  16.     }  
  17.   
  18.     public void setMaxFlag(boolean maxFlag) {  
  19.         this.maxFlag = maxFlag;  
  20.     }  
  21.   
  22.     /** 
  23.      * @return 
  24.      * @Author:lulei   
  25.      * @Description: 得到最後的決策 
  26.      */  
  27.     public int[] getDecisionArray() {  
  28.         return decisionArray;  
  29.     }  
  30.       
  31.     /** 
  32.      * @return 
  33.      * @Author:lulei   
  34.      * @Description: 獲取決策的評分 
  35.      */  
  36.     public int getScoreSum() {  
  37.         int sum = 0;  
  38.         for (int i = 0; i < num; i++) {  
  39.             sum += scoreArray[i][decisionArray[i]];  
  40.         }  
  41.         return sum;  
  42.     }  
  43.   
  44.     /** 
  45.      * @param num 
  46.      * @Author:lulei   
  47.      * @Description: 設置雙邊決策個體個數 
  48.      */  
  49.     public void setNum(int num) {  
  50.         if (num < 1) {  
  51.             System.out.println("num must be greater than 0");  
  52.             return;  
  53.         }  
  54.         this.num = num;  
  55.     }  
  56.       
  57.     /** 
  58.      * @param scoreArray 
  59.      * @Author:lulei   
  60.      * @Description: 設置A類個體與B類個體間的評價 
  61.      */  
  62.     public void setScoreArray(int[][] scoreArray) {  
  63.         if (scoreArray == null) {  
  64.             System.out.println("scoreArray is null");  
  65.         }  
  66.         if (!(scoreArray.length == num && scoreArray[0].length == num)) {  
  67.             System.out.println("scoreArray`s must be " + num);  
  68.         }  
  69.         this.scoreArray = scoreArray;  
  70.         decisionArray = new int[num];  
  71.         //初始決策,對角線  
  72.         for (int i = 0; i < num; i++) {  
  73.             decisionArray[i] = i;  
  74.         }  
  75.         decision();  
  76.     }  
  77.       
  78.     /** 
  79.      * @Author:lulei   
  80.      * @Description: 計算最優決策 
  81.      */  
  82.     private void decision() {  
  83.         if (scoreArray == null || decisionArray == null) {  
  84.             System.out.println("please init scoreArray");  
  85.         }  
  86.         for (int stepSize = 1; stepSize < num; stepSize++) {  
  87.             //特定步長下的交換  
  88.             while (compare(stepSize));  
  89.         }  
  90.     }   
  91.       
  92.     /** 
  93.      * @param stepSize 
  94.      * @return 
  95.      * @Author:lulei   
  96.      * @Description: 特定步長比較,返回值確認是否發生交換 
  97.      */  
  98.     private boolean compare(int stepSize) {  
  99.         for (int i = 0; i < num - stepSize; i++) {  
  100.             int a1 = i;  
  101.             int a2 = i + stepSize;  
  102.             int b1 = decisionArray[a1];  
  103.             int b2 = decisionArray[a2];  
  104.             //原始兩個得分之和  
  105.             int score1 = scoreArray[a1][b1] + scoreArray[a2][b2];  
  106.             int between1 = Math.abs(scoreArray[a1][b1] - scoreArray[a2][b2]);  
  107.             //交換後的兩個得分之和  
  108.             int score2 = scoreArray[a1][b2] + scoreArray[a2][b1];  
  109.             int between2 = Math.abs(scoreArray[a1][b2] - scoreArray[a2][b1]);  
  110.             if (maxFlag) { //最後的得分最大  
  111.                 if (score1 <= score2) {//交換後的分數不小於交換前的  
  112.                     //交換後的分數大於交換前的或者交換後的差值大於交換前的  
  113.                     if (score1 < score2 || between2 > between1) {  
  114.                         decisionArray[a1] = b2;  
  115.                         decisionArray[a2] = b1;  
  116.                         return true;  
  117.                     }  
  118.                 }  
  119.             } else { //最後的得分最小  
  120.                 if (score1 >= score2) {//交換後的分數不小於交換前的  
  121.                     //交換後的分數大於交換前的或者交換後的差值大於交換前的  
  122.                     if (score1 > score2 || between2 > between1) {  
  123.                         decisionArray[a1] = b2;  
  124.                         decisionArray[a2] = b1;  
  125.                         return true;  
  126.                     }  
  127.                 }  
  128.             }  
  129.         }  
  130.         return false;  
  131.     }  
  132.   
  133.     public static void main(String[] args) {  
  134.         int[][] scoreArray = {  
  135.                 {0,1,2,3,4,5,6,7,8,9},  
  136.                 {1,2,3,4,5,6,7,8,9,0},  
  137.                 {2,3,4,5,6,7,8,9,0,1},  
  138.                 {3,4,5,6,7,8,9,0,1,2},  
  139.                 {4,5,6,7,8,9,0,1,2,3,},  
  140.                 {5,6,7,8,9,0,1,2,3,4},  
  141.                 {6,7,8,9,0,1,2,3,4,5},  
  142.                 {7,8,9,0,1,2,3,4,5,6},  
  143.                 {8,9,0,1,2,3,4,5,6,7},  
  144.                 {9,0,1,2,3,4,5,6,7,8}};  
  145.         TwoSidedDecision test = new TwoSidedDecision();  
  146.         test.setNum(10);  
  147.         test.setMaxFlag(false);  
  148.         test.setScoreArray(scoreArray);  
  149.         System.out.println("最優決策");  
  150.         System.out.println(JsonUtil.parseJson(test.getDecisionArray()));  
  151.         System.out.println("決策得分");  
  152.         System.out.println(test.getScoreSum());  
  153.     }  
  154.   
  155. }  
相關文章
相關標籤/搜索