    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.penguin.math.ga;
    017
    018import java.util.ArrayList;
    019import java.util.List;
    020import java.util.Map;
    021import java.util.HashMap;
    022import java.util.Collections;                   // 6.9.8.0 (2018/05/28)
    023
    024import org.apache.commons.math3.genetics.InvalidRepresentationException;
    025
    026/**
    027 * AbstractHybsGAChromosomeのサンプル実装クラスです。
    028 * HybsGAObjectImplを利用しています。
    029 * 属性値配列(文字列)にタスクの割当先（機械や人）候補
    030 * 属性値（実数）にこのタスクにかかる時間
    031 * 属性値配列（実数）[0]にこのタスクの納期（開始からの経過時間）
    032 * を持たせているという想定です。
    033 * このクラスでは次のようにスケジュールを決めます。
    034 * １．候補のうち、一番タスクが積まれていないものに前から積む
    035 * ２．同じであればリストの先頭の方に割り当てられる
    036 * ３．納期オーバーの場合は評価関数の値が小さくなるようにする
    037 *
    038 */
    039public class HybsScheduleChromosome extends AbstractHybsGAChromosome {
    040
    041        /**
    042         * コンストラクタ。
    043         */
    044        public HybsScheduleChromosome() { super(); }            // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    045
    046        /**
    047         * コンストラクタ。
    048         *
    049         * @param representation 染色体表現
    050         */
    051        public HybsScheduleChromosome(final List<HybsGAObject> representation) {
    052                super(representation);
    053        }
    054
    055        /**
    056         * 適合度計算。
    057         *
    058         * @return 適合度計算の結果
    059         */
    060        public double fitness() {
    061                final List<HybsGAObject>                representation  = getRepresentation();
    062                final Map<String,Double>                machineList             = new HashMap<>();              //名前は機械リストだが、人でも良い
    063                final Map<String, List<String>> taskSchedule    = new HashMap<>();
    064
    065                // 実際にスケジュールの積み上げを行い、納期遅れの合計を出します
    066                // 6.9.8.0 (2018/05/28) 変数手直し
    067//              double nokisum = 0.0;
    068//              nokisum = makeSchedule( representation, machineList, taskSchedule );
    069                final double nokisum = makeSchedule( representation, machineList, taskSchedule );
    070
    071//              // リストから最大値を取得する(出てくる順番は問わない)
    072//              double maxWork=0;
    073//              for( final String mw : machineList.keySet() ){
    074//                      maxWork = machineList.get(mw) > maxWork ? machineList.get(mw) :maxWork;         // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
    075//              }
    076
    077                // リストから最大値を取得する(出てくる順番は問わない)
    078                // 6.9.8.0 (2018/05/28) 処理手直し
    079                final double maxWork = Collections.max( machineList.values() );
    080
    081                return 1 / ( maxWork + nokisum*nokisum); //納期遅れが多くなるとどんどん値が小さくなるように評価する
    082        }
    083
    084        /**
    085         * HybsGAObjectImplを利用して前からスケジュールを積み上げていきます。
    086         *
    087         * @og.rev 6.8.2.3 (2017/11/10) Doubleｲﾝｽﾀﾝｽ作成方法の変更。
    088         *
    089         * @param representation 染色体表現
    090         * @param machineList マシンに対する積み上げ工数のリスト。(書き込まれるのでfinalにしない）
    091         * @param taskSchedule マシンに対して、前からタスクをセットするリスト。(書き込まれるのでfinalにしない）
    092         * @return 納期遅れの累計
    093         */
    094        public double makeSchedule( final  List<HybsGAObject> representation , final Map<String,Double> machineList, final Map<String, List<String>> taskSchedule){
    095                HybsGAObjectImpl chrom;
    096                double nokisum = 0.0;
    097
    098                for ( int i=0; i<representation.size(); i++){
    099                        chrom = (HybsGAObjectImpl)representation.get(i);
    100
    101                        final String[] machines = chrom.getAttrStrArray();
    102                        // ここでスケジュールを当てはめていく
    103                        final double   noki = chrom.getAttrArray()[0];
    104                        String hitMachine = null;
    105                        double work=999999999;
    106                        // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
    107                        for( final String mach : machines ){
    108                                if(!machineList.containsKey( mach )){
    109                                        machineList.put( mach, Double.valueOf(0) );                             // 6.8.2.3 (2017/11/10)
    110                                        taskSchedule.put( mach, new ArrayList<String>() );
    111                                }
    112
    113                                if( machineList.get(mach) < work){
    114                                        work = machineList.get(mach);
    115                                        hitMachine = mach;
    116                                }
    117                        }
    118//                      for( int j=0; j<machines.length; j++ ){
    119//                              if(!machineList.containsKey( machines[j] )){
    120//                                              machineList.put( machines[j], Double.valueOf(0) );                              // 6.8.2.3 (2017/11/10)
    121//                                              taskSchedule.put( machines[j], new ArrayList<String>() );
    122//                              }
    123//
    124//                              if( machineList.get(machines[j]) < work){
    125//                                      work = machineList.get(machines[j]);
    126//                                      hitMachine = machines[j];
    127//                              }
    128//                      }
    129
    130                        machineList.put( hitMachine, Double.valueOf(work + chrom.getAttr()) );          // 総工数 6.8.2.3 (2017/11/10)
    131                        taskSchedule.get( hitMachine ).add( chrom.getName() );  // 割りついたタスクリスト
    132
    133                        if( work + chrom.getAttr() > noki ){
    134                                nokisum += noki - work + chrom.getAttr();                       // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
    135                        }
    136                }
    137                return nokisum;
    138        }
    139
    140        /**
    141         * 自身のクラスを新たに作成するメソッド。
    142         *
    143         * ここではオプションデータはクローンせずに参照で渡しています。
    144         * (計算では利用していません）
    145         *
    146         * @param repr 染色体表現
    147         * @return 作成された自分自身のクラス
    148         */
    149        @Override
    150        public AbstractHybsGAChromosome newFixedLengthChromosome(final List<HybsGAObject> repr) {
    151                final HybsScheduleChromosome rtn = new HybsScheduleChromosome(repr);
    152                rtn .setOptionData( optionData );
    153                return rtn;
    154        }
    155
    156        /**
    157         * 染色体表現のチェック。
    158         *
    159         * @param repr HybsGAObjectのリスト
    160         */
    161        @Override
    162        protected void checkValidity(final List<HybsGAObject> repr) throws InvalidRepresentationException {
    163                // Listの中身のチェックをする箇所。必要であれば記述する
    164        }
    165}