    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 * １．候補のうち、一番タスクが積まれていないものに前から積む
    018 * ２．同じであればリストの先頭の方に割り当てられる
    019 * ３．納期オーバーの場合は評価関数の値が小さくなるようにする
    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}