001package org.opengion.penguin.math.ga; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Map; 006import java.util.HashMap; 007import java.util.Collections; // 6.9.8.0 (2018/05/28) 008 009import org.apache.commons.math3.genetics.InvalidRepresentationException; 010 011/** 012 * AbstractHybsGAChromosomeのサンプル実装クラスです。 013 * HybsGAObjectImplを利用しています。 014 * 属性値配列(文字列)にタスクの割当先(機械や人)候補 015 * 属性値(実数)にこのタスクにかかる時間 016 * 属性値配列(実数)[0]にこのタスクの納期(開始からの経過時間) 017 * を持たせているという想定です。 018 * このクラスでは次のようにスケジュールを決めます。 019 * 1.候補のうち、一番タスクが積まれていないものに前から積む 020 * 2.同じであればリストの先頭の方に割り当てられる 021 * 3.納期オーバーの場合は評価関数の値が小さくなるようにする 022 * 023 */ 024public class HybsScheduleChromosome extends AbstractHybsGAChromosome { 025 026 /** 027 * コンストラクタ。 028 */ 029 public HybsScheduleChromosome() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 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 final Map<String,Double> machineList = new HashMap<>(); //名前は機械リストだが、人でも良い 048 final Map<String, List<String>> taskSchedule = new HashMap<>(); 049 050 // 実際にスケジュールの積み上げを行い、納期遅れの合計を出します 051 // 6.9.8.0 (2018/05/28) 変数手直し 052// double nokisum = 0.0; 053// nokisum = makeSchedule( representation, machineList, taskSchedule ); 054 final double 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; // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 060// } 061 062 // リストから最大値を取得する(出てくる順番は問わない) 063 // 6.9.8.0 (2018/05/28) 処理手直し 064 final double maxWork = Collections.max( machineList.values() ); 065 066 return 1 / ( maxWork + nokisum*nokisum); //納期遅れが多くなるとどんどん値が小さくなるように評価する 067 } 068 069 /** 070 * HybsGAObjectImplを利用して前からスケジュールを積み上げていきます。 071 * 072 * @og.rev 6.8.2.3 (2017/11/10) Doubleインスタンス作成方法の変更。 073 * 074 * @param representation 染色体表現 075 * @param machineList マシンに対する積み上げ工数のリスト。(書き込まれるのでfinalにしない) 076 * @param taskSchedule マシンに対して、前からタスクをセットするリスト。(書き込まれるのでfinalにしない) 077 * @return 納期遅れの累計 078 */ 079 public double makeSchedule( final List<HybsGAObject> representation , final Map<String,Double> machineList, final Map<String, List<String>> taskSchedule){ 080 HybsGAObjectImpl chrom; 081 double nokisum = 0.0; 082 083 for ( int i=0; i<representation.size(); i++){ 084 chrom = (HybsGAObjectImpl)representation.get(i); 085 086 final String[] machines = chrom.getAttrStrArray(); 087 // ここでスケジュールを当てはめていく 088 final double noki = chrom.getAttrArray()[0]; 089 String hitMachine = null; 090 double work=999999999; 091 // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop 092 for( final String mach : machines ){ 093 if(!machineList.containsKey( mach )){ 094 machineList.put( mach, Double.valueOf(0) ); // 6.8.2.3 (2017/11/10) 095 taskSchedule.put( mach, new ArrayList<String>() ); 096 } 097 098 if( machineList.get(mach) < work){ 099 work = machineList.get(mach); 100 hitMachine = mach; 101 } 102 } 103// for( int j=0; j<machines.length; j++ ){ 104// if(!machineList.containsKey( machines[j] )){ 105// machineList.put( machines[j], Double.valueOf(0) ); // 6.8.2.3 (2017/11/10) 106// taskSchedule.put( machines[j], new ArrayList<String>() ); 107// } 108// 109// if( machineList.get(machines[j]) < work){ 110// work = machineList.get(machines[j]); 111// hitMachine = machines[j]; 112// } 113// } 114 115 machineList.put( hitMachine, Double.valueOf(work + chrom.getAttr()) ); // 総工数 6.8.2.3 (2017/11/10) 116 taskSchedule.get( hitMachine ).add( chrom.getName() ); // 割りついたタスクリスト 117 118 if( work + chrom.getAttr() > noki ){ 119 nokisum += noki - work + chrom.getAttr(); // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 120 } 121 } 122 return nokisum; 123 } 124 125 /** 126 * 自身のクラスを新たに作成するメソッド。 127 * 128 * ここではオプションデータはクローンせずに参照で渡しています。 129 * (計算では利用していません) 130 * 131 * @param repr 染色体表現 132 * @return 作成された自分自身のクラス 133 */ 134 @Override 135 public AbstractHybsGAChromosome newFixedLengthChromosome(final List<HybsGAObject> repr) { 136 final HybsScheduleChromosome rtn = new HybsScheduleChromosome(repr); 137 rtn .setOptionData( optionData ); 138 return rtn; 139 } 140 141 /** 142 * 染色体表現のチェック。 143 * 144 * @param repr HybsGAObjectのリスト 145 */ 146 @Override 147 protected void checkValidity(final List<HybsGAObject> repr) throws InvalidRepresentationException { 148 // Listの中身のチェックをする箇所。必要であれば記述する 149 } 150}