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; 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}