码迷,mamicode.com
首页 > 编程语言 > 详细

公交调度-车次链编制贪心算法

时间:2015-09-23 13:31:09      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:

---恢复内容开始---

  1 package cn.edu.karel.work.public_transit_problem;
  2 
  3 import java.io.File;
  4 import java.io.FileNotFoundException;
  5 import java.io.FileReader;
  6 import java.io.IOException;
  7 import java.util.ArrayList;
  8 import java.util.List;
  9 
 10 /**
 11  * GreedSolute类
 12  * 
 13  * @author Karel Zuo
 14  * @time 2015.6.4
 15  * @version 1.0
 16  * @description 贪心算法求解公交时刻表和车次链问题
 17  */
 18 public class GreedSolute {
 19     /** 发车时刻表数据 */
 20     static File forward = new File("D:/mycode/Eclipse/Bus Scheduel Problem/scheduel1/ForwardScheduel/start time.txt");
 21     static File backward = new File("D:/mycode/Eclipse/Bus Scheduel Problem/scheduel1/BackScheduel/start time.txt");
 22     static int sum = 0;
 23     
 24     public static void main(String[] args) throws IOException{
 25         /** 创建时刻表 */
 26         Scheduel scheduel = new Scheduel();
 27         inputForward(scheduel);
 28         inputBackward(scheduel);
 29         
 30         /** 固定行车计划 */
 31         ArrayList<TrainsitChain> chain = creatFixedPlan(scheduel);
 32         
 33         /** 可变行车计划 */
 34         //chain = creatVariablePlan(scheduel,chain);
 35     }
 36     
 37     /**
 38      * 将发车时刻表中的所有车次按照 FIFO规则排序
 39      * 
 40      * @param scheduel 发车时刻表
 41      * @return list 排序后的车次序号列表
 42      */
 43     public static ArrayList<Integer> sortScheduel(Scheduel scheduel){
 44         /** 排序后的车次序号列表 */
 45         ArrayList<Integer> list = new ArrayList<Integer>();
 46         
 47         int i = 0;
 48         int j = 0;
 49         int k = 0;
 50         while(i<scheduel.tranListForward.size() && j<scheduel.tranListBack.size())
 51         {
 52             if(scheduel.tranListForward.get(i).arriveTime <= scheduel.tranListBack.get(j).arriveTime)
 53             {
 54                 list.add(k, scheduel.tranListForward.get(i).id);
 55                 i++;
 56             }
 57             else
 58             {
 59                 list.add(k, scheduel.tranListBack.get(j).id);
 60                 j++;
 61             }
 62             k++;
 63         }
 64         while(i<scheduel.tranListForward.size())
 65         {
 66             list.add(k++, scheduel.tranListForward.get(i++).id);
 67         }
 68         while(j<scheduel.tranListBack.size())
 69         {
 70             list.add(k++, scheduel.tranListBack.get(j++).id);
 71         }
 72         return list;
 73     }
 74     
 75     /** 
 76      * 贪心算法搜索出剩余车次中最长的车次链
 77      * 
 78      * @param list 按照FIFO规则排序后的车次的列表
 79      * @param scheduel 用于搜索车次链的发车时刻表
 80      * @return chain 搜索到的车次链
 81      */
 82     public static TrainsitChain searchChain(ArrayList<Integer> list,Scheduel scheduel){
 83         TrainsitChain chain = new TrainsitChain();
 84         
 85         /** 以当前剩余车次中的第一个车次为该车次链的首个车次*/
 86         int index = list.get(0);
 87         int len = scheduel.tranListForward.size();
 88         if(index >= len ){
 89             index -= len;
 90             chain.addTransit(scheduel.tranListBack.get(index));
 91         }else{
 92             chain.addTransit(scheduel.tranListForward.get(index));
 93         }
 94         list.remove(0);
 95         
 96         /**遍历当前剩余车次搜索到最长车次链 */
 97         int i=0;
 98         while(i<list.size())
 99         {
100             int next = list.get(i);
101             int l = chain.theChain.size();
102             /** 判断该车次是上行还是下行 */
103             if(next >= len)
104             {
105                 next -= len;
106                 if(scheduel.tranListBack.get(next).getStartTime() >= chain.end){
107                     /** 车次链上前后辆车次行驶方向不同 */
108                     if(chain.theChain.get(l-1).isForward){
109                         chain.addTransit(scheduel.tranListBack.get(next));
110                         list.remove(i);
111                     }
112                     else
113                         i++;
114                 }
115                 else
116                     i++;
117             }
118             else{
119                 if(scheduel.tranListForward.get(next).getStartTime() >= chain.end)
120                 {
121                     if(!chain.theChain.get(l-1).isForward){
122                         chain.addTransit(scheduel.tranListForward.get(next));
123                         list.remove(i);
124                     }
125                     else
126                         i++;
127                 }
128                 else
129                     i++;
130             }
131         }    
132         return chain;
133     }
134     
135     /**
136      * 读取上行数据
137      * @throws IOException 
138      */
139     public static void inputForward(Scheduel scheduel) throws IOException{
140         try{
141             int i = 0;
142             FileInputStream fis = new FileInputStream(forward);
143             InputStreamReader isr = new InputStreamReader(fis);
144             @SuppressWarnings("resource")
145             LineNumberReader lnr = new LineNumberReader(isr);
146             String s = null;
147             while ((s = lnr.readLine()) != null) {
148                 int data = Integer.parseInt(s.trim());
149                 Transit t = new Transit();
150                 t.setID(i);
151                 t.setStartTime(data);
152                 t.setArriveTime(data+Transit.RUN_FOWARD_TIME);
153                 t.setForward(true);
154                 if(i!=0)
155                     t.setAdjust(scheduel.tranListForward.get(i-1));
156                 scheduel.addTransitForward(t);
157                 i++;              
158             }
159         }catch(FileNotFoundException e){
160             e.printStackTrace();
161         }
162         System.out.println("上行数据:  ");
163         System.out.println(scheduel.tranListForward.size());
164     }
165     
166     /**
167      * 读取下行数据
168      * @throws IOException 
169      */
170     public static void inputBackward(Scheduel scheduel) throws IOException{
171         try{
172             int i = 0;
173             int len = scheduel.tranListForward.size();
174             FileInputStream fis = new FileInputStream(backward);
175             InputStreamReader isr = new InputStreamReader(fis);
176             @SuppressWarnings("resource")
177             LineNumberReader lnr = new LineNumberReader(isr);
178             String s = null;
179             while ((s = lnr.readLine()) != null) {
180                 int data = Integer.parseInt(s.trim());
181                 Transit t = new Transit();
182                 t.setID(i+len);
183                 t.setStartTime(data);
184                 t.setArriveTime(data+Transit.RUN_BACK_TIME);
185                 t.setForward(false);
186                 scheduel.addTransitBack(t);
187                 if(i!=0)
188                     t.setAdjust(scheduel.tranListBack.get(i-1));
189                 i++;              
190             }
191         }catch(FileNotFoundException e){
192             e.printStackTrace();
193         }
194         System.out.println("下行数据:  ");
195         System.out.println(scheduel.tranListBack.size());
196     }
197     
198     /**
199      * 根据当前时刻表,不作改动,计算固定行车计划
200      * 
201      * @param scheduel 当前时刻表
202      * @return chainList 固定行车计划车次链集合
203      */
204     public static ArrayList<TrainsitChain> creatFixedPlan(Scheduel scheduel){
205         ArrayList<TrainsitChain> chainList = new ArrayList<TrainsitChain>();
206         ArrayList<Integer> trainsitList = new ArrayList<Integer>();
207         trainsitList = sortScheduel(scheduel);
208         while(!trainsitList.isEmpty())
209         {
210             chainList.add(searchChain(trainsitList,scheduel));
211         }
212         System.out.println("车次链数目(最小车队规模): "+chainList.size());
213         
214         int n = chainList.size();
215         int i;
216         for( i=0;i<n;i++)
217         {
218             int m = chainList.get(i).theChain.size();
219             System.out.println("车次链:"+ (i+1) +"的组成:");
220             System.out.println();
221             for(int j=0;j<m;j++)
222             {
223                 System.out.print(chainList.get(i).theChain.get(j).getStartTime()+"("+chainList.get(i).theChain.get(j).getIsForward()+")"+" , ");
224             }
225             System.out.println();
226         }
227         
228         return  chainList;
229     }
230     
231     /**
232      * 在允许范围内调整发车时刻得到可变行车计划
233      * @param scheduel 行车计划
234      * @param plan 固定行车计划
235      * @return chain 可变行车计划
236      */
237     public static ArrayList<TrainsitChain> creatVariablePlan(Scheduel scheduel, ArrayList<TrainsitChain> plan){
238         sum++;
239         System.out.println("********************** 可变行车计划 *******************************");
240 //        System.out.println("********************** 原始发车时刻表 *******************************");
241 //        for(Transit t:scheduel.tranListForward)
242 //            System.out.println("ID:  " + t.getID() + "   发车时间:" + t.getStartTime() );
243 //        for(Transit t:scheduel.tranListBack)
244 //            System.out.println("ID:  " + t.getID() + "   发车时间:" + t.getStartTime() );
245         
246         ArrayList<TrainsitChain> chain;
247         
248         /** 计算n值,找到最大点 */
249         int last = scheduel.tranListForward.size();
250         for(Transit t:scheduel.tranListForward){
251             for(Transit s:scheduel.tranListBack){
252                 if(s.getStartTime() >= t.getArriveTime()){
253                     if(s.getArriveTime() >= scheduel.tranListForward.get(last-1).getStartTime())
254                         t.setN(scheduel.tranListForward.get(last-1).getID() - t.getID() + 1);
255                     for(Transit o:scheduel.tranListForward){
256                         if(o.getStartTime() >= s.getArriveTime()){
257                             t.setN(o.getID() - t.getID());
258                             break;
259                         }
260                     }
261                     break;
262                 }
263             }
264         }
265         int size = scheduel.tranListBack.size();
266         for(Transit t:scheduel.tranListBack){
267             for(Transit s:scheduel.tranListForward){
268                 if(s.getStartTime() >= t.getArriveTime()){
269                     if(s.getArriveTime() >= scheduel.tranListBack.get(size-1).getStartTime())
270                         t.setN(scheduel.tranListBack.get(size-1).getID() - t.getID() + 1);
271                     for(Transit o:scheduel.tranListBack){
272                         if(o.getStartTime() >= s.getArriveTime()){
273                             t.setN(o.getID() - t.getID());
274                             break;
275                         }
276                     }
277                     break;
278                 }
279             }
280         }
281         int max = 0, maxID = 0;
282         for(Transit t:scheduel.tranListForward){
283             if(t.getN() > max){
284                 max = t.getN();
285                 maxID = t.getID();
286             }
287         }
288         for(Transit t:scheduel.tranListBack){
289             if(t.getN() > max){
290                 max = t.getN();
291                 maxID = t.getID();
292             }
293         }
294         
295 //        System.out.println("********************** N值表 *******************************");
296 //        for(Transit t:scheduel.tranListForward)
297 //            System.out.println("ID:  " + t.getID() +  "   发车时间:" + t.getStartTime()+ "   N 值:" + t.getN() );
298 //        for(Transit t:scheduel.tranListBack)
299 //            System.out.println("ID:  " + t.getID() +  "   发车时间:" + t.getStartTime()+ "   N 值:" + t.getN() );
300         
301 //        System.out.println("最大N值:" + max + " " + "最大N值点:" + maxID);
302         /** 调整发车时间 */
303         Transit first;
304         if(maxID < scheduel.tranListForward.size())
305             first = scheduel.tranListForward.get(maxID);
306         else
307             first = scheduel.tranListBack.get(maxID-scheduel.tranListForward.size());
308         Scheduel s = adjustScheduel(scheduel,first);
309         //System.out.println("*******************  " + s.tranListBack.get(14-s.tranListForward.size()).getArriveTime() + "*****************");
310 
311         /** 搜索车次链 */
312         chain = creatFixedPlan(s);
313             
314         /** 判断是否继续搜索 */
315 //        System.out.println(" ");
316 //        System.out.println("  可变行车计划:  ");
317 //        System.out.println("可变计划最小车队规模: " + chain.size());
318 //        System.out.println(" ");
319 //        System.out.println("可变行车计划:");
320         int n = chain.size();
321         int i;
322         for( i=0;i<n;i++)
323         {
324             int m = chain.get(i).theChain.size();
325 //            System.out.println("车次链:"+ (i+1) +"的组成:");
326 //            System.out.println();
327             for(int j=0;j<m;j++)
328             {
329                 //System.out.print(chain.get(i).theChain.get(j).getStartTime()+"("+chain.get(i).theChain.get(j).getIsForward()+")"+" , ");
330             }
331             //System.out.println();
332         }
333         
334         /** 再求解一次调整之后的计算n值,找到最大点 */
335         int last1 = scheduel.tranListForward.size();
336         for(Transit t:scheduel.tranListForward){
337             for(Transit s1:scheduel.tranListBack){
338                 if(s1.getStartTime() >= t.getArriveTime()){
339                     if(s1.getArriveTime() >= scheduel.tranListForward.get(last1-1).getStartTime())
340                         t.setN(scheduel.tranListForward.get(last1-1).getID() - t.getID() + 1);
341                     for(Transit o:scheduel.tranListForward){
342                         if(o.getStartTime() >= s1.getArriveTime()){
343                             t.setN(o.getID() - t.getID());
344                             break;
345                         }
346                     }
347                     break;
348                 }
349             }
350         }
351         int size1 = scheduel.tranListBack.size();
352         for(Transit t:scheduel.tranListBack){
353             for(Transit s1:scheduel.tranListForward){
354                 if(s1.getStartTime() >= t.getArriveTime()){
355                     if(s1.getArriveTime() >= scheduel.tranListBack.get(size1-1).getStartTime())
356                         t.setN(scheduel.tranListBack.get(size1-1).getID() - t.getID() + 1);
357                     for(Transit o:scheduel.tranListBack){
358                         if(o.getStartTime() >= s1.getArriveTime()){
359                             t.setN(o.getID() - t.getID());
360                             break;
361                         }
362                     }
363                     break;
364                 }
365             }
366         }
367         int max1 = 0;
368         int maxID1 = 0;
369         for(Transit t:scheduel.tranListForward){
370             if(t.getN() > max1){
371                 max1 = t.getN();
372                 maxID1 = t.getID();
373             }
374         }
375         for(Transit t:scheduel.tranListBack){
376             if(t.getN() > max1){
377                 max1 = t.getN();
378                 maxID1 = t.getID();
379             }
380         }
381 ////        System.out.println("调整之后最大N:" + max1);
382 ////        System.out.println("********************** 调整之后的N值表 *******************************");
383 //        for(Transit t:s.tranListForward)
384 //            System.out.println("ID:  " + t.getID() +  "   发车时间:" + t.getStartTime()+ "   N 值:" + t.getN() );
385 //        for(Transit t:s.tranListBack)
386 //            System.out.println("ID:  " + t.getID() +  "   发车时间:" + t.getStartTime()+ "   N 值:" + t.getN() );
387         int newN = 0;
388         if(maxID >= scheduel.tranListForward.size())
389             newN = scheduel.tranListBack.get(maxID-s.tranListForward.size()).getN();
390         else 
391             newN = scheduel.tranListForward.get(maxID).getN();
392         System.out.println("调整之后原最大N——new:" + newN);
393         if(max1 > newN ){
394             chain = creatVariablePlan(s,chain);
395         }
396         else{
397             System.out.println("求解结束!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
398         }
399         return chain;
400     }
401     
402     /**
403      * 允许范围内调整时刻表缩减单条线路最小车队规模
404      * 
405      * @param scheduel 初始时刻表
406      * @param plan 固定行车计划
407      * @param t 开始调整的初始车次
408      * @return adj_scheduel 调整后的时刻表
409      */
410     public static Scheduel adjustScheduel(Scheduel scheduel, Transit t){
411         
412         final int RUNTIME_FORWARD = Transit.RUN_FOWARD_TIME;
413         final int RUNTIME_BACK = Transit.RUN_BACK_TIME;
414         
415         /** 获取初始车次的ID */
416         int id = t.getID();
417 //        System.out.println("查找到的初始车次序号:" + t.getID() +"发车时间:"+ t.getStartTime());
418         
419         int a = t.getArriveTime() - t.adjust;
420 //        System.out.println("初始车次的最早发车后到达末站的时刻:" + a);
421         int b = 0;
422         if(id >= scheduel.tranListForward.size()){//初始车次位于下行方向
423 //            System.out.println("初始值位于上行方向,T(j-1)位于下行方向");
424             id = id - scheduel.tranListForward.size();
425             
426             /** 寻找初始车次的第一个可行车次链上的下一个车次 */
427             int num = 0;
428             for(Transit e: scheduel.tranListForward){
429                 if((e.getStartTime()+e.getAdjust()) >= a){
430 //                    System.out.println("下一个可行车次:" + e.getArriveTime());
431                     num = e.getID();
432                     b = e.getStartTime();
433                     if(b >= a){
434                         t.setStartTime(t.getStartTime()-t.getAdjust());
435                         t.setArriveTime(t.getStartTime() + 15);
436                         for(Transit o: scheduel.tranListBack){
437                             if(o.getStartTime()+o.getAdjust() >= e.getArriveTime()){
438                                 if(o.getStartTime() < e.getArriveTime()){
439                                     o.setStartTime(o.getStartTime()+o.getAdjust());
440                                     o.setArriveTime(o.getStartTime() + 15);
441                                     o.adjust = 0;
442 //                                    System.out.println("调整 ID:" + o.getID() + "的值为: " + o.getStartTime() );
443                                 }
444                             }
445                         }
446                     }
447                     else{
448                         e.setStartTime(e.getStartTime()+e.getAdjust());
449                         e.setArriveTime(e.getStartTime() + 15);
450                         e.adjust = 0;
451 //                        System.out.println("调整 ID:" + e.getID() + "的值为: " + e.getStartTime() );
452                         if(t.getArriveTime() < e.getStartTime()){
453                             t.setStartTime(t.getStartTime()-t.getAdjust());
454                             t.setArriveTime(t.getStartTime() + 15);
455 //                            System.out.println("调整 ID:" + t.getID() + "的值为: " + t.getStartTime() );
456                         }
457                     }
458                     break;
459                 }
460             }
461         }
462         else{//初始车次位于上行方向
463             /** 寻找初始车次的第一个可行车次链上的下一个车次 */
464             int num = 0;
465             for(Transit e: scheduel.tranListForward){
466                 if((e.getStartTime()+e.getAdjust()) >= a){
467                     num = e.getID();
468                     b = e.getStartTime();
469                     if(b >= a){
470                         t.setStartTime(t.getStartTime()-t.getAdjust());
471                         t.setArriveTime(t.getStartTime() + 15);
472                         for(Transit o: scheduel.tranListBack){
473                             if(o.getStartTime()+o.getAdjust() >= e.getArriveTime()){
474                                 if(o.getStartTime() < e.getArriveTime()){
475                                     o.setStartTime(o.getStartTime()+o.getAdjust());
476                                     o.setArriveTime(o.getStartTime() + 15);
477                                     o.adjust = 0;
478                                 }
479                             }
480                         }
481                     }
482                     else{
483                         e.setStartTime(e.getStartTime()+e.getAdjust());
484                         e.setArriveTime(e.getStartTime() + 15);
485                         e.adjust = 0;
486                         if(t.getArriveTime() < e.getStartTime()){
487                             t.setStartTime(t.getStartTime()-t.getAdjust());
488                             t.setArriveTime(t.getStartTime() + 15);
489                         }
490                     }
491                     break;
492                 }
493             }
494         }
495         return scheduel;
496     }
497 }
498 
499 /**
500  * TrainsitChain类
501  * 
502  * @author Karel Zuo
503  * @time 2015.6.7
504  * @version 1.0
505  * @description 该类是车次链类,一个车次链由可以被同一辆车执行的所有车次组成
506  */
507 public class TrainsitChain {
508     
509     /** 车次链上第一个车次的发车时刻 */
510     float first = 0;
511     /** 车次链上最后一辆车到站时间 */
512     float end = 0;
513     /** 车次链上每一个车次的集合 */
514     ArrayList<Transit> theChain = new ArrayList<>();
515     
516     /** 
517      * 添加车次到车次链
518      * @param transit 车次
519      */
520     public void addTransit(Transit transit){
521         if(first == 0){
522             first = transit.startTime;
523             end = transit.arriveTime;
524             theChain.add(transit);
525         }
526         else{
527             end = transit.arriveTime;
528             theChain.add(transit);
529         }
530     }
531 }
532 
533 public class Scheduel {
534     
535     /** 上行时刻表的所有车次集合 */
536     ArrayList<Transit> tranListForward = new ArrayList<Transit>();
537     /** 下行行时刻表的所有车次集合 */
538     ArrayList<Transit> tranListBack = new ArrayList<Transit>();
539     
540     /**
541      * @param trainsit 车次对象
542      */
543     public void addTransitForward(Transit tansit){
544         this.tranListForward.add(tansit);
545     }
546     
547     /**
548      * @param trainsit 车次对象
549      */
550     public void addTransitBack(Transit tansit){
551         this.tranListBack.add(tansit);
552     }
553     
554     /**
555      * @return tranListForward 上行车次集合
556      */
557     public List<Transit> getTranListForeard(){
558         return this.tranListForward;
559     }
560     
561     /**
562      * @return tranListBack 下行车次集合
563      */
564     public List<Transit> getTranListBack(){
565         return this.tranListBack;
566     }
567 }
568 
569 /**
570  * 车次类
571  * 
572  * @author Karel Zuo
573  * @time 2015.6.4
574  * @version 1.0
575  * @description 该类用于表示一个车次的全部信息
576  */
577 public class Transit {
578     /** 上行方向运行时间 */
579     public final static int RUN_FOWARD_TIME = 59;//65;
580     /** 下行方向运行时间 */
581     public final static int RUN_BACK_TIME = 62;//58;
582     /** 车辆运行方向 */
583     boolean isForward;
584     /** 发车时间 */
585     int startTime;
586     /** 到站时间 */
587     int arriveTime;
588     /** 车次ID */
589     int id;
590     /** 发车时间允许调整范围 */
591     int adjust = 0;
592     /** 车次的n值 */
593     int N = 0;
594     
595     /** 
596      * @return startTime 发车时间
597      */
598     public int getStartTime(){
599         return this.startTime;
600     }
601     
602     /** 
603      * @return arriveTime 到站时间
604      */
605     public int getArriveTime(){
606         return this.arriveTime;
607     }
608     
609     /** 
610      * @return id 车次id
611      */
612     public int getID(){
613         return this.id;
614     }
615     
616     /** 
617      * @return isForward 车辆运行方向
618      */
619     public boolean getIsForward(){
620         return this.isForward;
621     }
622     
623     /**
624      * @param adjust 发车时刻允许调整范围
625      */
626     public int getAdjust(){
627         return this.adjust;
628     }
629     
630     /**
631      * @param N 该车次的N值
632      */
633     public int getN(){
634         return this.N;
635     }
636     
637     /** 
638      * @param time 设置的发车时间
639      */
640     public void setStartTime(int time){
641         this.startTime = time;
642     }
643     
644     /** 
645      * @param time 设置的到站时间
646      */
647     public void setArriveTime(int time){
648         this.arriveTime = time;
649     }
650     
651     /** 
652      * @param id 车次序号
653      */
654     public void setID(int id){
655         this.id = id;
656     }
657     
658     /** 
659      * @param isForward 车次运行方向
660      */
661     public void setForward(boolean isForward){
662         this.isForward = isForward;
663     }
664     
665     /**
666      * @param t 车次链上相连的前一个车次
667      */
668     public void setAdjust(Transit t){
669         int adjust = 0;//this.startTime - t.getStartTime();
670         if(adjust < 10)
671             adjust = (int)(0.7*adjust);
672         else if(adjust < 20)
673             adjust = (int)(0.5*adjust);
674         else if(adjust < 40)
675             adjust = (int)(0.4*adjust);
676         else
677             adjust = (int)(0.3*adjust);
678         this.adjust = adjust;
679     }
680     
681     /** 
682      * @param time 设置的发车时间
683      */
684     public void setN(int N){
685         this.N = N;
686     }
687 }

 

---恢复内容结束---

公交调度-车次链编制贪心算法

标签:

原文地址:http://www.cnblogs.com/zuoyouchen/p/4831925.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!