/// <summary> /// 通过多任务计算所有组合的坞修最优时间好排序 /// </summary> public void calcAllCombMultiProcess() { //使用task进行多进程异步计算所有的工作 List <Task <RcspspProject> > tasks = new List <Task <RcspspProject> >(); int num = everyComb.Keys.Count; //每一个combo组合建立一个任务 foreach (String str in everyComb.Keys) { if (everyComb[str] == null) { return; } tasks.Add(Task <RcspspProject> .Factory.StartNew(() => { return(calCombBestScoreByTabuSearch(str, everyComb[str])); })); } //等待所有任务结束 Task.WaitAll(tasks.ToArray()); //为计算结果进行赋值 foreach (Task <RcspspProject> task in tasks) { RcspspProject project = task.Result; everyCombBestProj[project.BestCombStr] = project; } }
/// <summary> /// 将每一个划分中的项目非坞修和坞修大任务形成一个单项目,计算任务的最优解。然后提取所有组合中的最优解 /// </summary> public RcspspProject calAllPartitionScore() { int num = allPartition.Count; List <Task <RcspspProject> > tasks = new List <Task <RcspspProject> >(); //每一个combo组合建立一个任务 foreach (List <List <RcspspProject> > projectPartition in this.allPartition) { tasks.Add(Task <RcspspProject> .Factory.StartNew(() => { return(calPartitionBestScoreByTabuSearch(projectPartition, this.everyCombBestProj)); })); } //等待所有任务结束 Task.WaitAll(tasks.ToArray()); //为计算结果进行赋值 double allPartitionBestScore = double.MaxValue; RcspspProject bestPartitionProj = null; foreach (Task <RcspspProject> task in tasks) { RcspspProject project = task.Result; //#if DEBUG Console.WriteLine("best core is " + project.BestSocre + " and partition is " + project.BestCombStr); Console.Write("this List is : "); foreach (RcpspJob job in project.Jobs) { Console.Write("[" + job.id + "__" + job.project + "__" + job.duration + "]"); } Console.WriteLine(); //#endif if (allPartitionBestScore > project.BestSocre) { allPartitionBestScore = project.BestSocre; bestPartitionProj = project; } } return(bestPartitionProj); }
public static RcpspSolver parseMultiProjFile(string fileName) { RcpspSolver solver = new RcpspSolver(); if (!fileName.EndsWith(".mp")) { solver.IsMultiProject = false; } solver.IsMultiProject = true; string directoryPath = fileName.Substring(0, fileName.LastIndexOf("\\")); StreamReader fileSR = new StreamReader(fileName); string readLineStr = null; int lineNumber = 0; int projNum = 0; int projIndex = 0; int resNum = 0; int perProjLine = 1; Regex numRegex = new Regex(@"[-+]?\d*(\.(?=\d))?\d+"); while ((readLineStr = fileSR.ReadLine()) != null) { if (lineNumber == 0) { //第0行总吨位 solver.TotalWuWeight = Convert.ToInt32(numRegex.Match(readLineStr).Value); } else if (lineNumber == 1) { //资源数量 resNum = Convert.ToInt32(numRegex.Match(readLineStr).Value); } else if (lineNumber == 2) { //资源详情 MatchCollection match1 = numRegex.Matches(readLineStr); foreach (Match g in match1) { RcpspResource res = new RcpspResource(); res.renewable = true; res.max_capacity = Convert.ToInt32(g.Value); solver.ResourceList.AddLast(res); resNum--; if (resNum <= 0) { break; } } } else if (lineNumber == 3) { //第1行项目数量 projNum = Convert.ToInt32(numRegex.Match(readLineStr).Value); } else if (lineNumber > 3 || lineNumber < (3 + projNum * perProjLine))// { //依次为文件,每个文件每个文件解析 string smFileName = readLineStr.Trim(new char[] { ' ', '\t', '\r' }); RcspspProject proj = generateFromSMFile(directoryPath + "\\" + smFileName, solver); proj.ProjectId = Convert.ToString(projIndex + 1); solver.ProjectList.AddLast(proj); projIndex++; } lineNumber++; } return(solver); }
/// <summary> /// 从从*.sm文件构造Project,添加一个已经构造的solver构造多项目 /// </summary> /// <param name="fileName"></param> /// <param name="solver"></param> /// <returns></returns> public static RcspspProject generateFromSMFile(string fileName, RcpspSolver solver) { RcspspProject proj = new RcspspProject(); LinkedList <RcpspResource> resourceList = solver.IsMultiProject ? solver.ResourceList : proj.Resources; proj.Resources = solver.ResourceList; LinkedList <RcpspJob> jobList = proj.Jobs; StreamReader fileSR = new StreamReader(fileName); string readLineStr = null; LoadStatus loadState = LoadStatus.HEADER_SECTION; long lineNumber = 0; //获取数字的正则表达式,包[-]2[.32] Regex numRegex = new Regex(@"[-+]?\d*(\.(?=\d))?\d+"); while ((readLineStr = fileSR.ReadLine()) != null) { lineNumber++; readLineStr = readLineStr.TrimStart(new char[] { ' ', '\t', '\r' }); if (readLineStr.StartsWith("**") || readLineStr.StartsWith("--")) { continue; } switch (loadState) { case LoadStatus.HEADER_SECTION: { if (readLineStr.StartsWith("file")) { proj.BaseFile = readLineStr.Substring(readLineStr.IndexOf(":")).Trim(); //项目baseFile } else if (readLineStr.StartsWith("init")) { string numberStr = numRegex.Match(readLineStr).Value; proj.RandomSeed = Convert.ToInt32(numberStr); // } else if (readLineStr.StartsWith("projects") || readLineStr.StartsWith("jobs")) { loadState = LoadStatus.PROJECT_SECTION; goto case LoadStatus.PROJECT_SECTION; } else { throw new Exception("File Format error at line " + lineNumber + "!"); } } break; case LoadStatus.PROJECT_SECTION: { if (readLineStr.StartsWith("projects")) { string numberStr = numRegex.Match(readLineStr).Value; //项目编号 proj.ProjectId = numberStr; } else if (readLineStr.StartsWith("jobs")) { int indexOfM = readLineStr.IndexOf(":"); string numberStr = numRegex.Match(readLineStr.Substring(indexOfM)).Value; //获取项目内任务数量 proj.TaskNumber = Convert.ToInt32(numberStr); int index = 0; while (index < proj.TaskNumber) { RcpspJob job = new RcpspJob(); job.project = proj.ProjectId; job.id = Convert.ToString(index + 1); job.sourceProj = proj; if (index == 0 || index == proj.TaskNumber - 1) { job.isVirtual = true; } if (index == 1) { job.isFirst = true; } if (index == proj.TaskNumber - 2) { job.isLast = true; } jobList.AddLast(job); index++; } } else if (readLineStr.StartsWith("horizon")) { string numberStr = numRegex.Match(readLineStr).Value; proj.Horizon = Convert.ToInt32(numberStr); } else if (readLineStr.StartsWith("RESOURCES")) { } else if (readLineStr.StartsWith("weight")) { proj.Weight = Convert.ToInt32(numRegex.Match(readLineStr).Value); } else if (readLineStr.StartsWith("lambda")) { proj.Lambda = Convert.ToDouble(numRegex.Match(readLineStr).Value); } else if (readLineStr.Contains("- renewable")) { string numberStr = numRegex.Match(readLineStr).Value; proj.RenewableResourceNumber = Convert.ToInt32(numberStr); int index = proj.RenewableResourceNumber; if (!solver.IsMultiProject) { //不处理 while (index > 0) { RcpspResource res = new RcpspResource(); res.renewable = true; solver.ResourceList.AddLast(res); index--; } } } else if (readLineStr.Contains("- nonrenewable")) { string numberStr = numRegex.Match(readLineStr).Value; proj.NonrenewableResourceNumber = Convert.ToInt32(numberStr); //int index = this._nonrenewableResourceNumber; //while (index < 0) //{ // RcpspResource res = new RcpspResource(); // res.renewable = false; // solver.ResourceList.AddLast(res); // index--; //} } else if (readLineStr.Contains("- doubly constrained")) { string numberStr = numRegex.Match(readLineStr).Value; proj.DoubleConstResourceNumber = Convert.ToInt32(numberStr); } else if (readLineStr.StartsWith("PROJECT INFORMATION")) { loadState = LoadStatus.PROJECT_INFO_SECTION; goto case LoadStatus.PROJECT_INFO_SECTION; } else if (readLineStr.StartsWith("PRECEDENCE")) { loadState = LoadStatus.PRECEDENCE_SECTION; goto case LoadStatus.PRECEDENCE_SECTION; } else if (readLineStr.StartsWith("REQUESTS/DURATIONS")) { loadState = LoadStatus.REQUEST_SECTION; goto case LoadStatus.REQUEST_SECTION; } else if (readLineStr.StartsWith("RESOURCEAVAILABILITIES")) { loadState = LoadStatus.RESOURCE_SECTION; goto case LoadStatus.RESOURCE_SECTION; } else { throw new Exception("File Format error at line " + lineNumber + "!"); } } break; case LoadStatus.PROJECT_INFO_SECTION: { if (readLineStr.StartsWith("pronr.")) { } else if (readLineStr.StartsWith("PRECEDENCE")) { loadState = LoadStatus.PRECEDENCE_SECTION; goto case LoadStatus.PRECEDENCE_SECTION; } else if (readLineStr.StartsWith("REQUESTS/DURATIONS")) { loadState = LoadStatus.REQUEST_SECTION; goto case LoadStatus.REQUEST_SECTION; } else if (readLineStr.StartsWith("RESOURCEAVAILABILITIES")) { loadState = LoadStatus.RESOURCE_SECTION; goto case LoadStatus.RESOURCE_SECTION; } else if (readLineStr.StartsWith("PROJECT INFORMATION")) { } else { //MatchCollection matchColl = numRegex.Matches(readLineStr); //int index = 0; //foreach (Match g in matchColl) //{ // index++; // if (index == 0) // { // //项目号 // } // else if (index == 1) // { // //任务数 // } // else if (index == 2) // { // //rel.date // } // else if (index == 3) // { // //duedate // } // else if (index == 4) // { // //tardcost // } // else if (index == 5) { // //MPM-Time // } //} } } break; case LoadStatus.PRECEDENCE_SECTION: { if (readLineStr.StartsWith("REQUESTS/DURATIONS")) { loadState = LoadStatus.REQUEST_SECTION; goto case LoadStatus.REQUEST_SECTION; } else if (readLineStr.StartsWith("RESOURCEAVAILABILITIES")) { loadState = LoadStatus.RESOURCE_SECTION; goto case LoadStatus.RESOURCE_SECTION; } else if (readLineStr.StartsWith("jobnr.")) { // } else if (readLineStr.StartsWith("PRECEDENCE")) { // } else { MatchCollection matchColl = numRegex.Matches(readLineStr); int index = 0; int numProd = 0; RcpspJob job = null; foreach (Match g in matchColl) { int num = Convert.ToInt32(g.Value);; if (index == 0) { //任务数 job = jobList.ElementAt(num - 1); if (job == null) { throw new Exception("REQUESTS/DURATIONS not exist job nr. " + num); } index++; } else if (index == 1) { //mode if (job != null) { job.isWX = num == 1 ? true : false; } index++; } else if (index == 2) { //紧前任务数量 index++; numProd = num; if (num == 0) { break; } } else if (index == 3) { RcpspJob predJob = jobList.ElementAt(num - 1); if (predJob == null) { throw new Exception("Predecessor No. is error" + num); } job.addPredecessor(predJob); numProd--; if (numProd <= 0) { break; } } else { //if(numProd>0)throw new Exception("Predecessors num is not correct!"); } } } } break; case LoadStatus.REQUEST_SECTION: { if (readLineStr.StartsWith("jobnr.") || readLineStr.StartsWith("REQUESTS/DURATIONS")) { } else if (readLineStr.StartsWith("RESOURCEAVAILABILITIES")) { loadState = LoadStatus.RESOURCE_SECTION; goto case LoadStatus.RESOURCE_SECTION; } else if (readLineStr.StartsWith("PRECEDENCE")) { } else { MatchCollection matchColl = numRegex.Matches(readLineStr); int index = 0; RcpspJob job = null; foreach (Match g in matchColl) { if (index == 0) { int num = Convert.ToInt32(g.Value); //任务数 job = jobList.ElementAt(num - 1); if (job == null) { throw new Exception("REQUESTS/DURATIONS not exist job nr. " + num); } index++; } else if (index == 1) { int num = Convert.ToInt32(g.Value); //不处理 index++; } else if (index == 2) { //duration double num = Convert.ToDouble(g.Value); index++; if (job != null) { job.duration = num; } } else { //不判断资源超界了 int num = Convert.ToInt32(g.Value); if (num > 0) { RcpspResource res = resourceList.ElementAt(index - 3); if (res != null) { job.addResourceDemand(res, num); } } index++; } } } } break; case LoadStatus.RESOURCE_SECTION: { if (readLineStr.StartsWith("PRECEDENCE")) { loadState = LoadStatus.PRECEDENCE_SECTION; goto case LoadStatus.PRECEDENCE_SECTION; } else if (readLineStr.StartsWith("REQUESTS/DURATIONS")) { loadState = LoadStatus.REQUEST_SECTION; goto case LoadStatus.REQUEST_SECTION; } else if (readLineStr.StartsWith("RESOURCEAVAILABILITIES")) { // } else { MatchCollection matchColl = numRegex.Matches(readLineStr); if (!solver.IsMultiProject) { // int index = 0; foreach (Match g in matchColl) { index++; if (index == 0) { //任务数 } } } } } break; case LoadStatus.RESOURCE_MIN_SECTION: { } break; case LoadStatus.PARSING_FINISHED: break; case LoadStatus.ERROR_FOUND: break; default: break; } } //solver.ProjectList.AddLast(proj); return(proj); }
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; }
public static void generateProj(RcspspProject spspProject) { int[] resCap = { 3, 4, 2, 3, 6 }; for (int i = 0; i < 5; i++) { RcpspResource resource = new RcpspResource(); resource.max_capacity = resCap[i]; spspProject.Resources.AddLast(resource); } int numberJobs = 22; int[] durations = { 0, 10, 8, 20, 4, 8, 4, 10, 6, 12, 5, 22, 13, 4, 10, 8, 2, 16, 25, 8, 2, 0 }; int[,] resUsed = { { 0, 0, 0, 0, 0 }, //0 { 2, 0, 2, 1, 0 }, //1 { 0, 1, 0, 2, 5 }, //2 { 1, 0, 2, 0, 0 }, //3 { 0, 0, 0, 3, 5 }, //4 { 0, 2, 0, 0, 2 }, //5 { 0, 2, 1, 0, 0 }, //6 { 2, 0, 2, 0, 0 }, //7 { 1, 0, 0, 2, 5 }, //8 { 0, 1, 0, 0, 2 }, //9 { 0, 0, 0, 3, 0 }, //10 { 1, 0, 0, 0, 0 }, //11 { 2, 2, 0, 0, 0 }, //12 { 0, 0, 2, 3, 0 }, //13 { 0, 0, 0, 1, 4 }, //14 { 1, 0, 0, 1, 3 }, //15 { 0, 0, 0, 1, 2 }, //16 { 2, 3, 0, 0, 0 }, //17 { 1, 0, 2, 0, 0 }, //18 { 0, 2, 0, 3, 0 }, //19 { 0, 3, 0, 0, 6 }, //20 { 0, 0, 0, 0, 0 } //21 }; int [][] pp = new int[22][]; pp[0] = new int[] { 0 }; //1 pp[1] = new int[] { 0 }; //2 pp[2] = new int[] { 1 }; //3 pp[3] = new int[] { 0 }; //4 pp[4] = new int[] { 3 }; //5 pp[5] = new int[] { 2, 4 }; //6 pp[6] = new int[] { 0 }; //7 pp[7] = new int[] { 6 }; //8 pp[8] = new int[] { 7 }; //9 pp[9] = new int[] { 7 }; //10 pp[10] = new int[] { 8, 9 }; //11 pp[11] = new int[] { 0 }; //12 pp[12] = new int[] { 11 }; //13 pp[13] = new int[] { 11 }; //14 pp[14] = new int[] { 12, 13 }; //15 pp[15] = new int[] { 14 }; //16 pp[16] = new int[] { 0 }; //17 pp[17] = new int[] { 16 }; //18 pp[18] = new int[] { 0 }; //19 pp[19] = new int[] { 17, 18 }; //20 pp[20] = new int[] { 19 }; //21 pp[21] = new int[] { 5, 10, 15, 20 }; //22 for (int j = 0; j < numberJobs; j++) { RcpspJob job = new RcpspJob(); job.id = Convert.ToString(j); job.duration = durations[j]; for (int resN = 0; resN < 5; resN++) { if (resUsed[j, resN] > 0) { job.addResourceDemand(spspProject.Resources.ElementAt(resN), resUsed[j, resN]); } } for (int preIndex = 0; preIndex < pp[j].Length; preIndex++) { if (pp[j][preIndex] != j) { job.addPredecessor(spspProject.Jobs.ElementAt(pp[j][preIndex])); } } spspProject.Jobs.AddLast(job); } }
public static void generateRandomProj(RcspspProject spspProject) { Random rd = new Random(); for (int i = 0; i < 5; i++) { RcpspResource resource = new RcpspResource(); resource.max_capacity = rd.Next(1, 10); spspProject.Resources.AddLast(resource); } RcpspJob zeroJob = new RcpspJob(); zeroJob.duration = 0; zeroJob.id = "0"; spspProject.Jobs.AddLast(zeroJob); //初始Job,每一个job都有不允许建立的关系,即前置已经建立的关系,存放起来Dictionary<Job,Job>存在 LinkedList <Edge> existEdges = new LinkedList <Edge>(); int numberJobs = 5; int durationMax = 11; for (int j = 1; j < numberJobs + 1; j++) { RcpspJob job = new RcpspJob(); job.id = Convert.ToString(j); //检查可以生成的边的数量 int edgeCount = 0; LinkedListNode <RcpspJob> node = spspProject.Jobs.First; while (node != null) { //检测是否不允许 bool isAllow = true; //遍历列表 foreach (Edge ed in existEdges) { if (ed.from == job && ed.to == node.Value) { isAllow = false; break; } } if (!isAllow) { continue; } //是否生成 if (rd.Next(0, 2) > 0) { edgeCount++; job.addPredecessor(node.Value); Edge edThis = new Edge(); edThis.from = job; edThis.to = node.Value; existEdges.AddLast(edThis); //将前置的所有不允许加入当前的 LinkedListNode <Edge> lastNode = existEdges.Last; while (lastNode != null) { Edge ed = lastNode.Value; if (ed.from == node.Value) { Edge edNew = new Edge(); edNew.from = job; edNew.to = ed.to; existEdges.AddLast(edNew); } lastNode = lastNode.Previous; } } node = node.Next; } if (edgeCount == 0) { job.addPredecessor(spspProject.Jobs.First.Value); existEdges.AddLast(new Edge(job, spspProject.Jobs.First.Value)); } if (j == numberJobs - 1) { job.duration = 0; } else { job.duration = rd.Next(1, durationMax); //随机资源使用 for (int i = 0; i < 5; i++) { RcpspResource resource = spspProject.Resources.ElementAt(i); int resourceDemand = rd.Next(0, resource.max_capacity + 1); if (resourceDemand > 0) { job.addResourceDemand(resource, resourceDemand); } } } spspProject.Jobs.AddLast(job); } //添加最后工序 RcpspJob lastJob = new RcpspJob(); lastJob.duration = 0; lastJob.id = Convert.ToString(numberJobs + 1); //所有没有紧后任务的工序都设一条到该点的边 for (LinkedListNode <RcpspJob> recuNode = spspProject.Jobs.First; recuNode != null; recuNode = recuNode.Next) { if (recuNode.Value.successors.Count <= 0) { lastJob.addPredecessor(recuNode.Value); } } spspProject.Jobs.AddLast(lastJob); }
/// <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); }
/// <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); }