001package org.opengion.penguin.math.ga;
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() { super(); }            // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
028
029        /**
030         * コンストラクタ。
031         * 
032         * @param representation 染色体表現
033         */
034        public HybsScheduleChromosome(final List<HybsGAObject> representation) {
035                super(representation);
036        }
037
038        /**
039         * 適合度計算。
040         * 
041         * @return 適合度計算の結果
042         */
043        public double fitness() { 
044                final List<HybsGAObject> representation = getRepresentation();
045                double nokisum = 0.0;
046                final Map<String,Double> machineList = new HashMap<>(); //名前は機械リストだが、人でも良い
047                final Map<String, List<String>> taskSchedule = new HashMap<>();
048
049                // 実際にスケジュールの積み上げを行い、納期遅れの合計を出します
050                nokisum = makeSchedule( representation, machineList, taskSchedule );
051
052                // リストから最大値を取得する(出てくる順番は問わない)
053                double maxWork=0;
054                for( final String mw : machineList.keySet() ){
055                        maxWork = ( machineList.get(mw) > maxWork ) ? machineList.get(mw) :maxWork;
056                }
057
058                return 1 / ( maxWork + nokisum*nokisum); //納期遅れが多くなるとどんどん値が小さくなるように評価する
059        }
060
061        /**
062         * HybsGAObjectImplを利用して前からスケジュールを積み上げていきます。
063         * 
064         * @og.rev 6.8.2.3 (2017/11/10) Doubleインスタンス作成方法の変更。
065         * 
066         * @param representation 染色体表現
067         * @param machineList マシンに対する積み上げ工数のリスト。(書き込まれるのでfinalにしない)
068         * @param taskSchedule マシンに対して、前からタスクをセットするリスト。(書き込まれるのでfinalにしない)
069         * @return 納期遅れの累計
070         */
071        public double makeSchedule( final  List<HybsGAObject> representation , final Map<String,Double> machineList, final Map<String, List<String>> taskSchedule){
072                HybsGAObjectImpl chrom;
073                double nokisum = 0.0;
074
075                for ( int i=0; i<representation.size(); i++){
076                        chrom = (HybsGAObjectImpl)representation.get(i);
077
078                        final String[] machines = chrom.getAttrStrArray();
079                        // ここでスケジュールを当てはめていく
080                        final double   noki = chrom.getAttrArray()[0];
081                        String hitMachine = null;
082                        double work=999999999;
083                        for( int j=0; j<machines.length; j++ ){
084                                if(!machineList.containsKey( machines[j] )){
085                                                machineList.put( machines[j], Double.valueOf(0) );                              // 6.8.2.3 (2017/11/10)
086                                                taskSchedule.put( machines[j], new ArrayList<String>() );
087                                }
088
089                                if( machineList.get(machines[j]) < work){
090                                        work = machineList.get(machines[j]);
091                                        hitMachine = machines[j];
092                                }
093                        }
094
095                        machineList.put( hitMachine, Double.valueOf(work + chrom.getAttr()) );          // 総工数 6.8.2.3 (2017/11/10)
096                        taskSchedule.get( hitMachine ).add( chrom.getName() ); // 割りついたタスクリスト
097
098                        if( work + chrom.getAttr() > noki ){
099                                nokisum += ( noki - (work + chrom.getAttr()) ); 
100                        }
101                }
102                return nokisum;
103        }
104
105        /**
106         * 自身のクラスを新たに作成するメソッド。
107         * 
108         * ここではオプションデータはクローンせずに参照で渡しています。
109         * (計算では利用していません)
110         * 
111         * @param repr 染色体表現
112         * @return 作成された自分自身のクラス
113         */
114        @Override
115        public AbstractHybsGAChromosome newFixedLengthChromosome(final List<HybsGAObject> repr) {
116                final HybsScheduleChromosome rtn = new HybsScheduleChromosome(repr);
117                rtn .setOptionData( optionData );
118                return rtn;
119        }
120
121        /**
122         * 染色体表現のチェック。
123         * 
124         * @param repr HybsGAObjectのリスト
125         */
126        @Override
127        protected void checkValidity(final List<HybsGAObject> repr) throws InvalidRepresentationException {
128                // Listの中身のチェックをする箇所。必要であれば記述する
129        }
130}