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 * 1.候補のうち、一番タスクが積まれていないものに前から積む
035 * 2.同じであればリストの先頭の方に割り当てられる
036 * 3.納期オーバーの場合は評価関数の値が小さくなるようにする
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;         // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
096                double nokisum = 0.0;
097
098                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
099//              for ( int i=0; i<representation.size(); i++){
100//                      chrom = (HybsGAObjectImpl)representation.get(i);
101                for ( final HybsGAObject gaObjct : representation ){
102                        chrom = (HybsGAObjectImpl)gaObjct;
103                        final String[] machines = chrom.getAttrStrArray();
104                        // ここでスケジュールを当てはめていく
105                        final double   noki = chrom.getAttrArray()[0];
106                        String hitMachine = null;
107                        double work=999_999_999;        // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseUnderscoresInNumericLiterals
108                        // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
109                        for( final String mach : machines ){
110                                if(!machineList.containsKey( mach )){
111                                        // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing
112//                                      machineList.put( mach, Double.valueOf(0) );                             // 6.8.2.3 (2017/11/10)
113                                        machineList.put( mach, 0.0 );                                                   // 6.8.2.3 (2017/11/10)
114                                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseDiamondOperator 対応
115//                                      taskSchedule.put( mach, new ArrayList<String>() );
116                                        taskSchedule.put( mach, new ArrayList<>() );                    // ArrayList<String>()
117                                }
118
119                                if( machineList.get(mach) < work){
120                                        work = machineList.get(mach);
121                                        hitMachine = mach;
122                                }
123                        }
124//                      for( int j=0; j<machines.length; j++ ){
125//                              if(!machineList.containsKey( machines[j] )){
126//                                              machineList.put( machines[j], Double.valueOf(0) );                              // 6.8.2.3 (2017/11/10)
127//                                              taskSchedule.put( machines[j], new ArrayList<String>() );
128//                              }
129//
130//                              if( machineList.get(machines[j]) < work){
131//                                      work = machineList.get(machines[j]);
132//                                      hitMachine = machines[j];
133//                              }
134//                      }
135
136                        // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing
137//                      machineList.put( hitMachine, Double.valueOf(work + chrom.getAttr()) );          // 総工数 6.8.2.3 (2017/11/10)
138                        machineList.put( hitMachine, work + chrom.getAttr() );          // 総工数 6.8.2.3 (2017/11/10)
139                        taskSchedule.get( hitMachine ).add( chrom.getName() );          // 割りついたタスクリスト
140
141                        if( work + chrom.getAttr() > noki ){
142                                nokisum += noki - work + chrom.getAttr();                       // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
143                        }
144                }
145                return nokisum;
146        }
147
148        /**
149         * 自身のクラスを新たに作成するメソッド。
150         *
151         * ここではオプションデータはクローンせずに参照で渡しています。
152         * (計算では利用していません)
153         *
154         * @param repr 染色体表現
155         * @return 作成された自分自身のクラス
156         */
157        @Override
158        public AbstractHybsGAChromosome newFixedLengthChromosome(final List<HybsGAObject> repr) {
159                final HybsScheduleChromosome rtn = new HybsScheduleChromosome(repr);
160                rtn.setOptionData( optionData );
161                return rtn;
162        }
163
164        /**
165         * 染色体表現のチェック。
166         *
167         * @param repr HybsGAObjectのリスト
168         */
169        @Override
170        protected void checkValidity(final List<HybsGAObject> repr) throws InvalidRepresentationException {
171                // Listの中身のチェックをする箇所。必要であれば記述する
172        }
173}