OSDN Git Service

cflib は plugins プロジェクトから,Stigmata直下のプロジェクトに移行したため,このリポジトリからは削除した.
[stigmata/stigmata-plugins.git] / osb / src / main / java / jp / sourceforge / stigmata / birthmarks / osb / OperandStackBehaviorsBirthmarkComparator.java
1 package jp.sourceforge.stigmata.birthmarks.osb;
2
3 import jp.sourceforge.stigmata.Birthmark;
4 import jp.sourceforge.stigmata.BirthmarkContext;
5 import jp.sourceforge.stigmata.BirthmarkElement;
6 import jp.sourceforge.stigmata.birthmarks.comparators.AbstractBirthmarkComparator;
7 import jp.sourceforge.stigmata.birthmarks.osb.hungarian.CostMatrix;
8 import jp.sourceforge.stigmata.birthmarks.osb.hungarian.HungarianMethod;
9 import jp.sourceforge.stigmata.spi.BirthmarkService;
10
11 /**
12  * 
13  * @author Fumiya Iwama
14  * @author Ryouta Obatake
15  * @author Akinori Kataoka
16  * @author Takayuki Kitano
17  */
18 public class OperandStackBehaviorsBirthmarkComparator extends AbstractBirthmarkComparator{
19                 public OperandStackBehaviorsBirthmarkComparator(BirthmarkService spi){
20                         super(spi);
21                 }               
22
23     @Override
24     public double compare(Birthmark b1, Birthmark b2, BirthmarkContext context){
25         BirthmarkElement[] elementsA = b1.getElements();
26         BirthmarkElement[] elementsB = b2.getElements();
27
28         //両方0だったら(片方でも0だったら、return0)
29         if(elementsA.length != 0 && elementsA.length != 0){ 
30             double[][] sim = createMatrix(elementsA,elementsB);
31             // matchには、類似度の合計値が最大となる値が入る
32             double match = calculateMatch(sim); 
33             // BehaviorSetのBehaviorの数のうち、大きい方を max に代入     
34             int max = Math.max(elementsA.length, elementsB.length);
35             
36             return match / max;//Similarityを返す
37         }
38         else{
39             return 0;
40         }
41     }
42
43     public double compare(BirthmarkElement element1, BirthmarkElement element2){
44         if(element1 instanceof OperandStackBehaviorsBirthmarkElement &&
45                 element2 instanceof OperandStackBehaviorsBirthmarkElement){
46             return ((OperandStackBehaviorsBirthmarkElement)element1).getSimilarity(
47                     (OperandStackBehaviorsBirthmarkElement)element2
48             );
49         }
50         throw new IllegalArgumentException("only OperandStackBehaviorBirthmarkElement");
51     }
52
53     protected double[][] createMatrix(BirthmarkElement[] elementsA, BirthmarkElement[] elementsB){
54         double[][] matrix = new double[elementsA.length][elementsB.length];//simは実数だからdouble
55         for(int i = 0; i < elementsA.length; i++){
56             for(int j = 0; j < elementsB.length; j++){
57                 OperandStackBehaviorsBirthmarkElement osb1 = (OperandStackBehaviorsBirthmarkElement)elementsA[i];
58                 OperandStackBehaviorsBirthmarkElement osb2 = (OperandStackBehaviorsBirthmarkElement)elementsB[j];
59                 matrix[i][j] = osb1.getSimilarity(osb2);
60             }
61         }
62         return matrix;
63     }
64
65     /**
66      * ハンガリアン法を使い,類似度を求める.
67      * @param matrixArray Birthmarkの要素間の類似度をまとめた2次元配列.
68      * @return 類似度の和が最大となるよう組み合わせた値.
69      */
70     protected double calculateMatch(double[][] matrixArray){
71         CostMatrix matrix = new CostMatrix(matrixArray, true);
72         HungarianMethod method = new HungarianMethod(matrix);
73
74         return method.solve();
75     }
76 }