public static void print(LinkedList <RcpspJob> globalList, bool withLambda = false) { double bestCore = TabuSearch.calScheduleCore(globalList, withLambda); LinkedListNode <RcpspJob> recursiveNode = globalList.First; Console.WriteLine("total cost is " + bestCore); Console.WriteLine("jobnr\t\tduaration\t\tstarttime\t\tsucessors"); while (recursiveNode != null) { Console.Write(recursiveNode.Value.id + "\t\t\t\t\t" + recursiveNode.Value.startTime + "\t\t" + recursiveNode.Value.duration + "\t\t"); foreach (RcpspJob suces in recursiveNode.Value.successors) { Console.Write(suces.id + "\t"); } Console.WriteLine(); recursiveNode = recursiveNode.Next; } }
//禁忌处理,弹出,比较全局最优 public static double solve(LinkedList <RcpspJob> globalList, bool withLambda = false) { //生成初始排序和初始解,作为当前最优 getInitScheduleByMIT(globalList); double globalBestScore = calScheduleCore(globalList, withLambda); //将当前初始解赋值给全局最优解队列 LinkedList <RcpspJob> projJobs = new LinkedList <RcpspJob>(); LinkedListNode <RcpspJob> copyRecusive = globalList.First; while (copyRecusive != null) { projJobs.AddLast(copyRecusive.Value); copyRecusive = copyRecusive.Next; } //定义当前领域计算的最优解,初始赋值为全局最优 double currentBestScore = globalBestScore; int numberIter = maxIterationNum; //长度确定的禁忌表,不足用null对象填充;对禁忌表的操作 LinkedList <NeighborSwap> tabuList = TabuSearch.initTabuList(TabuSearch.tabuListSize); while ((--numberIter) > 0) { #if DEBUG Console.Write("执行第 " + (maxIterationNum - numberIter + 1) + "次遍历:"); print(projJobs); #endif TabuSearch.numberIter++; //获取邻居最好的禁忌长度 LinkedList <NeighborSwap> bestNeighborSwap = getBestNeighborBySwap(projJobs, withLambda); //是否优于globalBestScore,是,查询在不在禁忌表中,在的话放到开头,不在加到开头;否,查询非禁忌最优解 LinkedListNode <NeighborSwap> recursiveNode = bestNeighborSwap.First; if (recursiveNode != null && recursiveNode.Value.score < globalBestScore) { #if DEBUG Console.WriteLine("best than global score: swap (" + recursiveNode.Value.from.id + "," + recursiveNode.Value.to.id + ") and core is " + recursiveNode.Value.score); #endif //置换 swapNeighbor(projJobs, projJobs.Find(recursiveNode.Value.from), projJobs.Find(recursiveNode.Value.to)); //赋值全局最优和当前最优 globalBestScore = currentBestScore = recursiveNode.Value.score; //赋值该列表为全局最优列表 copyRecusive = projJobs.First; globalList.Clear(); while (copyRecusive != null) { globalList.AddLast(copyRecusive.Value); copyRecusive = copyRecusive.Next; } //更新禁忌表,如果在禁忌表中,将其从列表中移出并加入到最后;如果不存在,直接加到最后 LinkedListNode <NeighborSwap> findNode = tabuList.Find(recursiveNode.Value); if (findNode != null) { tabuList.Remove(findNode); tabuList.AddLast(findNode); } else { tabuList.RemoveFirst(); tabuList.AddLast(recursiveNode.Value); } } else { //从前到后遍历当前最优解,查找是否在禁忌表中,如果不在,加入到禁忌表最后,并且置换,更新局部最优,但是不更新全局最优; //查到,遍历下一个;当遍历完成都未满足,则最后差一个空的。 bool hasLocatedValue = false; while (recursiveNode != null) { if (!tabuList.Contains(recursiveNode.Value)) { #if DEBUG Console.WriteLine("find no in tabulist: swap (" + recursiveNode.Value.from.id + "," + recursiveNode.Value.to.id + ") and core is " + recursiveNode.Value.score); #endif hasLocatedValue = true; tabuList.RemoveFirst(); tabuList.AddLast(recursiveNode.Value); currentBestScore = recursiveNode.Value.score; swapNeighbor(projJobs, projJobs.Find(recursiveNode.Value.from), projJobs.Find(recursiveNode.Value.to)); break;//直接返回 } recursiveNode = recursiveNode.Next; } if (!hasLocatedValue) { tabuList.RemoveFirst(); tabuList.AddLast(new NeighborSwap(null, null, 0)); } } #if DEBUG Console.Write("current list is :("); foreach (RcpspJob job in projJobs) { Console.Write(job.id + ","); } Console.WriteLine(")"); Console.Write("tabuList is :"); foreach (NeighborSwap swap in tabuList) { if (swap.from != null && swap.to != null) { Console.Write("(" + swap.from.id + "," + swap.to.id + ")"); } } Console.WriteLine(); #endif } //执行最后,返回全局最优 return(globalBestScore); }
/// <summary> /// 将所有船舶按划分情况进行合并,坞修替换成划分内组合的坞修大任务,并需求一个坞修资源,然后形成一个新的总项目,进行禁忌搜索 /// </summary> /// <param name="projectPartition"></param> /// <param name="everyCombBestProj"></param> /// <returns></returns> public static RcspspProject calPartitionBestScoreByTabuSearch(List <List <RcspspProject> > projectPartition, Dictionary <String, RcspspProject> everyCombBestProj, bool withMIT = false) { // RcspspProject singleProject = new RcspspProject(); singleProject.BestSocre = int.MaxValue; RcpspJob zeroJob = new RcpspJob(); zeroJob.id = "0"; //zeroJob.isWX = true; zeroJob.isVirtual = true; zeroJob.project = "0"; singleProject.Jobs.AddFirst(zeroJob); //旧Job和复制的新Job的对应表 Dictionary <RcpspJob, RcpspJob> copyMapping = new Dictionary <RcpspJob, RcpspJob>(); RcpspResource resWx = new RcpspResource(); resWx.max_capacity = 1; resWx.renewable = true; singleProject.Resources.AddLast(resWx); //资源添加紧前紧后会更改原有的job,因此需要复制Job,资源和资源使用不会更改resource内容,不用复制,然后除去非坞修任务,添加最前和最后 foreach (List <RcspspProject> projComb in projectPartition) { //先形成字符串() String projCombStr = null; foreach (RcspspProject proj in projComb) { if (projCombStr == null) { projCombStr += proj.ProjectId; } else { projCombStr += "," + proj.ProjectId; } } projCombStr = "(" + projCombStr + ")"; singleProject.BestCombStr += projCombStr; //生成总坞修任务 RcspspProject wxProj = everyCombBestProj[projCombStr]; if (wxProj == null) { throw new Exception("total outer cal " + projCombStr + " cannot find WXCombProject"); } string wxId = null; foreach (RcpspJob job1 in wxProj.Jobs) { if (wxId == null) { wxId = "(" + job1.id + "," + job1.project + ")"; } else { wxId += "→(" + job1.id + "," + job1.project + ")"; } } RcpspJob wxJob = new RcpspJob(); wxJob.id = wxId; wxJob.duration = wxProj.BestSocre; wxJob.addResourceDemand(resWx, 1); wxJob.project = projCombStr; wxJob.isWX = true; singleProject.Jobs.AddLast(wxJob); //再遍历一遍,逐个任务替换并新加到singleProject foreach (RcspspProject proj in projComb) { foreach (RcpspJob job in proj.Jobs) { //if (job.isWX)//坞修任务,不处理 //{ // //如果其紧前为非坞修,要加入到大任务中 //} if (job.isVirtual)//项目的开始和结束虚拟任务都去除,用新的替换 { continue; } RcpspJob newJob = job.isWX?wxJob:job.cloneJob(); //处理紧前关系 foreach (RcpspJob preJob in job.predecessors) { if (preJob.isWX)//坞修的替换成大坞修任务 { //自身就是大坞修任务,不需要处理,自身不是大坞修任务,添加到大坞修任务的紧前关系 if (!newJob.isWX) { newJob.addPredecessor(wxJob); } } else if (preJob.isVirtual) //虚拟的替换成总虚拟节点 { newJob.addPredecessor(zeroJob); } else { //既不是虚拟也不是坞修任务的紧前关系,添加到紧前关系中,此处当前包含坞修 newJob.addPredecessor(copyMapping[preJob]);//正常的查找对应的新任务,添加进入紧前队列 } } copyMapping.Add(job, newJob); if (!newJob.isWX)//坞修大任务已经添加过一遍 { singleProject.Jobs.AddLast(newJob); } } } } //处理整体,对没有紧后任务的添加虚拟结束节点 RcpspJob lastJob = new RcpspJob(); lastJob.id = Convert.ToString(singleProject.Jobs.Count); //lastJob.isWX = true; lastJob.isVirtual = true; lastJob.project = "0"; foreach (RcpspJob job in singleProject.Jobs) { if (job.successors.Count <= 0) { lastJob.addPredecessor(job); } else if (job.predecessors.Count <= 0) { job.addPredecessor(zeroJob); } } singleProject.Jobs.AddLast(lastJob); //计算最优时间 if (withMIT) { singleProject.BestSocre = TabuSearch.getInitScheduleByMIT(singleProject.Jobs, true); } else { singleProject.BestSocre = TabuSearch.solve(singleProject.Jobs, true); } return(singleProject); }
static void Main(string[] args) { //Dictionary<string, int> did = new Dictionary<string, int>(); //did.Add("sad", 11); //Console.WriteLine("d is " + did["sad"] + " and d1 is " + did["sad1"]); //int i = 1023; //int j = i / 100; //int k = i % 100; //Console.WriteLine("d is " + i / 100 + " and d1 is " + k); if (args.Length < 1) { Console.WriteLine(" please input multi-projects file"); return; } string fileName = args[0]; //string fileName = "F:\\VSProject\\TabuSearch\\PSP\\bin\\Release\\000.mp";//args[0]; RcpspSolver solve = new RcpspSolver(); solve = RcpspParser.parseMultiProjFile(fileName); //solve.TotalWuWeight = 30; //solve.ProjectList.AddLast(new RcspspProject("0", 10)); //solve.ProjectList.AddLast(new RcspspProject("1", 10)); //solve.ProjectList.AddLast(new RcspspProject("2", 15)); //solve.ProjectList.AddLast(new RcspspProject("3", 5)); //solve.ProjectList.AddLast(new RcspspProject("4", 5)); ////产生所有可行划分和所有划分组合 solve.generateAllPossiblePartation(); ////计算所有组合的最优时间和最优分组 solve.calcAllCombMultiProcess(); foreach (string str in solve.EveryCombBestProj.Keys) { RcspspProject proj = solve.EveryCombBestProj[str]; Console.WriteLine("comb core " + str + "is " + proj.BestSocre + " and list is : "); Console.Write(" "); foreach (RcpspJob job in proj.Jobs) { Console.Write("(" + job.id + "__" + job.project + "__" + job.duration + ")"); } Console.WriteLine(); } RcspspProject bestproj = solve.calAllPartitionScore(); Console.WriteLine("all project end time is "); foreach (RcspspProject proj in solve.ProjectList) { if (proj.Jobs.Count > 1) { RcpspJob lastJob = proj.Jobs.Last.Previous.Value; Console.Write(" " + (lastJob.startTime + lastJob.duration)); } } Console.WriteLine(); Console.WriteLine("best core is " + bestproj.BestSocre + " and partition is " + bestproj.BestCombStr); Console.Write("this List is : "); foreach (RcpspJob job in bestproj.Jobs) { //Console.Write("[" + job.id + "__" + job.project + "__" + job.startTime+"__"+job.duration + "]"); //foreach(RcspspProject proj in solve.ProjectList){ //} if (job.isWX) { RcspspProject wxProject = solve.EveryCombBestProj[job.project]; foreach (RcpspJob wxJob in wxProject.Jobs) { addJob2Dic(solve.ProjectList, wxJob, job.startTime); } } else { addJob2Dic(solve.ProjectList, job); } } //TabuSearch.printGUI(bestproj.Jobs); Console.WriteLine("total time is " + TabuSearch.calScheduleCore(bestproj.Jobs, true)); foreach (RcspspProject proj in solve.ProjectList) { Console.WriteLine("Project " + proj.ProjectId); foreach (RcpspJob projJob in proj.Jobs) { Console.WriteLine(projJob.id + "\t" + projJob.startTime + "\t" + (projJob.startTime + projJob.duration)); } } return; }
/// <summary> /// 将组合的项目形成一个单项目,并且计算任务的最优排列和最优解,不要使用引用ref或者out,会引起子任务异常 /// </summary> public static RcspspProject calCombBestScoreByTabuSearch(String uniqeId, List <RcspspProject> projComb, bool withMIT = false) { RcspspProject singleProject = new RcspspProject(); singleProject.BestSocre = int.MaxValue; RcpspJob zeroJob = new RcpspJob(); zeroJob.id = "0"; zeroJob.isWX = true; zeroJob.isVirtual = true; zeroJob.project = "0"; singleProject.Jobs.AddFirst(zeroJob); singleProject.BestCombStr += uniqeId; //旧Job和复制的新Job的对应表 Dictionary <RcpspJob, RcpspJob> copyMapping = new Dictionary <RcpspJob, RcpspJob>(); //资源添加紧前紧后会更改原有的job,因此需要复制Job,资源和资源使用不会更改resource内容,不用复制,然后除去非坞修任务,添加最前和最后 foreach (RcspspProject proj in projComb) { foreach (RcpspJob job in proj.Jobs) { if (!job.isWX)//只处理坞修任务 { continue; } RcpspJob newJob = job.cloneJob(); //处理紧前关系 foreach (RcpspJob preJob in job.predecessors) { if (preJob.isWX) { newJob.addPredecessor(copyMapping[preJob]); } else { newJob.addPredecessor(zeroJob); } } copyMapping.Add(job, newJob); singleProject.Jobs.AddLast(newJob); //ngleProject// } } //处理整体,对没有紧后任务的添加虚拟结束节点 RcpspJob lastJob = new RcpspJob(); lastJob.id = Convert.ToString(singleProject.Jobs.Count); lastJob.isWX = true; lastJob.isVirtual = true; lastJob.project = "0"; foreach (RcpspJob job in singleProject.Jobs) { if (job.successors.Count <= 0) { lastJob.addPredecessor(job); } } singleProject.Jobs.AddLast(lastJob); //计算最优时间 if (withMIT) { singleProject.BestSocre = TabuSearch.getInitScheduleByMIT(singleProject.Jobs); } else { singleProject.BestSocre = TabuSearch.solve(singleProject.Jobs); } //Thread.Sleep(5000); //Console.WriteLine("uniqeId=" + uniqeId + " ---------"); return(singleProject); }