001package org.opengion.penguin.math;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Map;
006import java.util.HashMap;
007import org.apache.commons.math3.genetics.InvalidRepresentationException;
008
009/**
010 * AbstractHybsGAChromosomeのサンプル実装クラスです。
011 * HybsGAObjectImplを利用しています。
012 * 属性値配列(文字列)にタスクの割当先(機械や人)候補
013 * 属性値(実数)にこのタスクにかかる時間
014 * 属性値配列(実数)[0]にこのタスクの納期(開始からの経過時間)
015 * を持たせているという想定です。
016 * このクラスでは次のようにスケジュールを決めます。
017 * 1.候補のうち、一番タスクが積まれていないものに前から積む
018 * 2.同じであればリストの先頭の方に割り当てられる
019 * 3.納期オーバーの場合は評価関数の値が小さくなるようにする
020 *
021 */
022public class HybsScheduleChromosome extends AbstractHybsGAChromosome {
023
024        /**
025         * コンストラクタ。
026         */
027        public HybsScheduleChromosome() {
028                super();
029        }
030
031        /**
032         * コンストラクタ。
033         * 
034         * @param representation 染色体表現
035         */
036        public HybsScheduleChromosome(final List<HybsGAObject> representation) {
037                super(representation);
038        }
039
040        /**
041         * 適合度計算。
042         * 
043         * @return 適合度計算の結果
044         */
045        public double fitness() { 
046                final List<HybsGAObject> representation = getRepresentation();
047                double nokisum = 0.0;
048//              final HashMap<String,Double> machineList = new HashMap<String, Double>(); //名前は機械リストだが、人でも良い
049//              final HashMap<String, ArrayList<String>> taskSchedule = new HashMap<String, ArrayList<String>>();
050                final Map<String,Double> machineList = new HashMap<String,Double>(); //名前は機械リストだが、人でも良い
051                final Map<String, List<String>> taskSchedule = new HashMap<String, List<String>>();
052                
053                // 実際にスケジュールの積み上げを行い、納期遅れの合計を出します
054                nokisum = makeSchedule( representation, machineList, taskSchedule );
055
056                // リストから最大値を取得する(出てくる順番は問わない)
057                double maxWork=0;
058                for( final String mw : machineList.keySet() ){
059                        maxWork = ( machineList.get(mw) > maxWork ) ? machineList.get(mw) :maxWork;
060                }
061
062                return 1 / ( maxWork + nokisum*nokisum); //納期遅れが多くなるとどんどん値が小さくなるように評価する
063        }
064
065        /**
066         * HybsGAObjectImplを利用して前からスケジュールを積み上げていきます。
067         * 
068         * @param representation 染色体表現
069         * @param machineList マシンに対する積み上げ工数のリスト。(書き込まれるのでfinalにしない)
070         * @param taskSchedule マシンに対して、前からタスクをセットするリスト。(書き込まれるのでfinalにしない)
071         * @return 納期遅れの累計
072         */
073//      public double makeSchedule( final  List<HybsGAObject> representation , final HashMap<String,Double> machineList, final HashMap<String, ArrayList<String>> taskSchedule){
074        public double makeSchedule( final  List<HybsGAObject> representation , final Map<String,Double> machineList, final Map<String, List<String>> taskSchedule){
075                HybsGAObjectImpl chrom;
076                double nokisum = 0.0;
077
078                for ( int i=0; i<representation.size(); i++){
079                        chrom = (HybsGAObjectImpl)representation.get(i);
080
081                        final String[] machines = chrom.getAttrStrArray();
082                        // ここでスケジュールを当てはめていく
083                        final double   noki = chrom.getAttrArray()[0];
084                        String hitMachine = null;
085                        double work=999999999;
086                        for( int j=0; j<machines.length; j++ ){
087                                if(!machineList.containsKey( machines[j] )){
088                                                machineList.put( machines[j], new Double(0) );
089                                                taskSchedule.put( machines[j], new ArrayList<String>() );
090                                }
091
092                                if( machineList.get(machines[j]) < work){
093                                        work = machineList.get(machines[j]);
094                                        hitMachine = machines[j];
095                                }
096                        }
097
098                        machineList.put( hitMachine, new Double(work + chrom.getAttr()) ); // 総工数
099                        taskSchedule.get( hitMachine ).add( chrom.getName() ); // 割りついたタスクリスト
100                        
101                        if( work + chrom.getAttr() > noki ){
102                                nokisum += ( noki - (work + chrom.getAttr()) ); 
103                        }
104                }
105                return nokisum;
106        }
107
108        /**
109         * 自身のクラスを新たに作成するメソッド。
110         * 
111         * ここではオプションデータはクローンせずに参照で渡しています。
112         * (計算では利用していません)
113         * 
114         * @param repr 染色体表現
115         * @return 作成された自分自身のクラス
116         */
117        @Override
118        public AbstractHybsGAChromosome newFixedLengthChromosome(final List<HybsGAObject> repr) {
119                final HybsScheduleChromosome rtn = new HybsScheduleChromosome(repr);
120                rtn .setOptionData( optionData );
121                return rtn;
122        }
123
124        /**
125         * 染色体表現のチェック。
126         * 
127         * @param repr HybsGAObjectのリスト
128         */
129        @Override
130        protected void checkValidity(final List<HybsGAObject> repr) throws InvalidRepresentationException {
131                // Listの中身のチェックをする箇所。必要であれば記述する
132        }
133}