public StringBuilder translate_single_pairing(Pairing path, ref StringBuilder pathStr, ref SummarySingleDuty summary) { double start_time = 0, end_time = 0; int num_external_days = 0; //MealStatus mealStatus = MealStatus.no; foreach (Arc arc in path.ArcList) { switch (arc.ArcType) { case 2: pathStr.AppendFormat("{0}站{1}分出乘", arc.O_Point.StartStation, arc.D_Point.StartTime); start_time = arc.D_Point.StartTime; break; case 1: pathStr.AppendFormat("{0}[{1}]{2}", arc.O_Point.TrainCode, arc.O_Point.MealStatus, "→"); summary.totalConnect += arc.Cost; break; case 22: pathStr.AppendFormat("{0}[{1}]{2}", arc.O_Point.TrainCode, arc.O_Point.MealStatus, "→"); summary.totalConnect += arc.Cost; summary.externalRest += arc.Cost; num_external_days++; break; case 3: pathStr.AppendFormat("{0}[{1}] {2}站{3}分退乘", arc.O_Point.TrainCode, arc.O_Point.MealStatus, arc.D_Point.EndStation, arc.O_Point.EndTime); end_time = arc.O_Point.EndTime; break; default: break; } //if (arc.O_Point.MealStatus != MealStatus.no) { // pathStr.AppendFormat("[{0}]→", arc.O_Point.MealStatus); //} } summary.totalLength = end_time - start_time; summary.pureCrewTime = summary.totalLength - summary.totalConnect; summary.accumuwork = summary.totalLength - summary.externalRest;// +120 ; pathStr.AppendFormat(" ,总长度, {0},纯乘务时间 {1},总接续时间 {2},外驻时间 {3},总工作时间{4}", summary.totalLength, summary.pureCrewTime, summary.totalConnect, summary.externalRest, summary.accumuwork); pathStr.AppendLine(); return(pathStr); }
public StringBuilder translate_single_pairing(Pairing path, ref StringBuilder pathStr, ref SummarySingleDuty summary) { double start_time = 0, end_time = 0; int num_external_days = 0; foreach (Arc arc in path.Arcs) { switch (arc.ArcType) { case 2: pathStr.AppendFormat("{0}站{1}分出乘", arc.O_Point.StartStation, arc.D_Point.StartTime); start_time = arc.D_Point.StartTime; break; case 1: pathStr.AppendFormat("{0} {1}", arc.O_Point.TrainCode, "→"); summary.totalConnect += arc.Cost; break; case 22: pathStr.AppendFormat("{0} {1}", arc.O_Point.TrainCode, "→"); summary.totalConnect += arc.Cost; summary.externalRest += arc.Cost; num_external_days++; break; case 3: pathStr.AppendFormat("{0} {1}站{2}分退乘", arc.O_Point.TrainCode, arc.D_Point.EndStation, arc.O_Point.EndTime); end_time = arc.O_Point.EndTime; break; default: break; } } summary.totalLength = end_time - start_time; summary.pureCrewTime = summary.totalLength - summary.totalConnect; pathStr.AppendFormat(" 总长度 {0}\t纯乘务时间 {1}\t总接续时间 {2}\t外驻时间 {3}", summary.totalLength, summary.pureCrewTime, summary.totalConnect, summary.externalRest); pathStr.AppendLine(); return(pathStr); }
//TODO:添加多列 public bool FindMultipleNewPColumn(int num_addColumns) { List <Node> topoNodeList = UnProcessed; Node virD = topoNodeList.Last(); negetiveLabels = new List <Label>(); Reduced_Cost = 0; Label label1; int i; //找标号Cost < 0即可 for (i = virD.LabelsForward.Count - 1; i >= 0; i--) { label1 = virD.LabelsForward[i]; if (label1.AccumuCost < 0) { negetiveLabels.Add(label1); } } if (negetiveLabels.Count == 0) //检验数均大于0,原问题最优 { return(false); } num_addColumns = Math.Min(num_addColumns, negetiveLabels.Count); //TODO:TopN排序,只想最多添加N列,则只需找出TopN即可 //先调用方法全部排序吧 negetiveLabels = negetiveLabels.OrderBy(labelCost => labelCost.AccumuCost).ToList(); Reduced_Cost = negetiveLabels[0].AccumuCost;//固定为最小Cost //reduced_costs = new double[num_addColumns]; New_Columns = new List <Pairing>(num_addColumns); //局部变量 int realistic_trip_num = NetWork.num_Physical_trip; Node virO = topoNodeList[0]; Arc arc; //newMultiAji = new int[num_addColumns, realistic_trip_num];//全部元素默认为0 for (i = 0; i < num_addColumns; i++) { label1 = negetiveLabels[i]; //reduced_costs[i] = label1.AccumuCost; New_Column = new Pairing(); New_Column.Arcs = new List <Arc>(); New_Column.CoverMatrix = new int[realistic_trip_num]; New_Column.Cost = label1.AccumuCost; New_Column.Coef = 1440; int pathday = 1; arc = label1.PreEdge; while (!arc.O_Point.Equals(virO)) { New_Column.Arcs.Insert(0, arc); if (arc.O_Point.LineID > 0) { New_Column.CoverMatrix[arc.O_Point.LineID - 1] = 1; } pathday = arc.ArcType == 22 ? pathday + 1 : pathday; label1 = label1.PreLabel; arc = label1.PreEdge; } New_Column.Arcs.Insert(0, arc); New_Column.Coef *= pathday; New_Columns.Add(New_Column); } return(true); }
public void FindNewPath() { List <Node> topoNodeList = UnProcessed; Node virD = topoNodeList.Last(); //终点的确定是否可以更加普适(少以Index为索引) Label label1; Label label2; int i; //找标号Cost属性值最小的,改变弧长后,Cost即为reduced cost, //而主问题的Cj为 reduced cost + sum(trip.price), //但在迭代过程中Cj=1440*days #region //可利用Linq查询 //label1 = virD.LabelsForward.Aggregate((l1, l2) => l1.AccumuCost < l2.AccumuCost ? l1 : l2); //label1 = (from l in virD.LabelsForward // let minCost = virD.LabelsForward.Max(m => m.AccumuCost) // where l.AccumuCost == minCost // select l).FirstOrDefault(); #endregion label1 = virD.LabelsForward[0]; for (i = 1; i < virD.LabelsForward.Count; i++) { //想当然了!!常规来吧,别想着骚 //label1 = virD.LabelsForward[i - 1].AccumuCost < virD.LabelsForward[i].AccumuCost ? // virD.LabelsForward[i - 1] : virD.LabelsForward[i]; label2 = virD.LabelsForward[i]; if (label1.AccumuCost > label2.AccumuCost) { label1 = label2; } } //Reduced_Cost = label1.AccumuCost; //2019-1-27 New_Column = new Pairing(); New_Column.Arcs = new List <Arc>(); int realistic_trip_num = NetWork.num_Physical_trip;//(nodeList.Count - 2) / CrewRules.MaxDays; //newAji = new int[realistic_trip_num]; //for (i = 0; i < realistic_trip_num; i++) { newAji[i] = 0; } New_Column.CoverMatrix = new int[realistic_trip_num]; New_Column.Cost = label1.AccumuCost; //2019-2-1 New_Column.Coef = 1440; //double sum_tripPrice = 0; int pathday = 1; Node virO = topoNodeList[0]; Arc arc; arc = label1.PreEdge; while (!arc.O_Point.Equals(virO)) { New_Column.Arcs.Insert(0, arc); //sum_tripPrice += arc.O_Point.Price; //newAji[arc.O_Point.LineID - 1] = 1; if (arc.O_Point.LineID > 0) { New_Column.CoverMatrix[arc.O_Point.LineID - 1] = 1;//虚拟起终点弧的处理 } label1 = label1.PreLabel; arc = label1.PreEdge; pathday = arc.ArcType == 22 ? pathday + 1 : pathday; } New_Column.Arcs.Insert(0, arc); //New_Path.Cost = Reduced_Cost + sum_tripPrice; New_Column.Coef *= pathday; }
Pairing FindFeasiblePairings(Node trip) { Pairing loopPath = new Pairing();//output loopPath.Arcs = new List <Arc>(); int i, j; int minF = 0, minB = 0; Label labelF, labelB; Arc arc; Double AccumuDrive, T3, C; double MAX = 666666; Double Coef = MAX; for (i = 0; i < trip.LabelsForward.Count; i++) { labelF = trip.LabelsForward[i]; for (j = 0; j < trip.LabelsBackward.Count; j++) { labelB = trip.LabelsBackward[j]; AccumuDrive = labelF.AccumuDrive + labelB.AccumuDrive - trip.Length; T3 = labelF.AccumuWork + labelB.AccumuWork - trip.Length; C = labelF.AccumuCost + labelB.AccumuCost - trip.Length; //求初始解时,Cost即为非乘务时间,即目标函数,而在列生成迭代中,非也(因为对偶乘子) if (AccumuDrive <= CrewRules.PureCrewTime && T3 <= CrewRules.TotalCrewTime && Coef >= C) //find minmal cost { minF = i; minB = j; Coef = C; } } } if (Coef < MAX) { labelF = trip.LabelsForward[minF]; labelB = trip.LabelsBackward[minB]; loopPath.Cost = Coef; arc = labelF.PreEdge; while (arc.O_Point.ID != 0) { loopPath.Arcs.Insert(0, arc); labelF = labelF.PreLabel; arc = labelF.PreEdge; } loopPath.Arcs.Insert(0, arc); arc = labelB.PreEdge; while (arc.D_Point.ID != 1) { loopPath.Arcs.Add(arc); labelB = labelB.PreLabel; arc = labelB.PreEdge; } loopPath.Arcs.Add(arc); } if (loopPath.Arcs.Count == 0) { loopPath = default(Pairing); } return(loopPath); }
Pairing FindFeasiblePairings(Node trip) //寻找合适的交路,计算累加量 { Pairing loopPath = new Pairing(); //output loopPath.Arcs = new List <Arc>(); int i, j; int minF = 0, minB = 0;//forward backword Label labelF, labelB; Arc arc; Double AccumuWorkday, T3, C; double MAX = 666666; Double Coef = MAX; for (i = 0; i < trip.LabelsForward.Count; i++) { labelF = trip.LabelsForward[i]; for (j = 0; j < trip.LabelsBackward.Count; j++) { labelB = trip.LabelsBackward[j]; if (labelF.BaseOfCurrentPath.Station != labelB.BaseOfCurrentPath.Station)//???????????????????????? //???????????????????????????????? { continue; } AccumuWorkday = labelF.AccumuWorkday + labelB.AccumuWorkday - trip.TypeofWorkorRest; if (trip.TypeofWorkorRest == 1) //首先判断这一天的作休类型 { T3 = labelF.AccumuWork + labelB.AccumuWork - trip.Length; //总乘务时间 } else { T3 = labelF.AccumuWork + labelB.AccumuWork; //工作时间 } C = labelF.AccumuCost + labelB.AccumuCost; //C-cost;貌似不用加length???????????????????? //求初始解时,Cost即为非乘务时间,即目标函数,而在列生成迭代中,非也(因为对偶乘子) if ( //AccumuWorkday <= trip.NumberofWorkday &&//T3 <= CrewRules.TotalCrewTime&& Coef >= C) //find minmal cost { minF = i; minB = j; Coef = C; } } } if (Coef < MAX) //Coef-cj // 这部分还有待修改 { labelF = trip.LabelsForward[minF]; labelB = trip.LabelsBackward[minB]; loopPath.Coef = 0;//1440; int pathday = 1; loopPath.accumuwork = labelF.AccumuWork + labelB.AccumuWork; loopPath.ObjCoef = Net.GetObjCoef(loopPath.accumuwork, loopPath.Coef); arc = labelF.PreEdge; while (arc.O_Point.ID != 0) { //pathday = arc.ArcType == 22 ? pathday + 1 : pathday; loopPath.Coef += arc.Cost; loopPath.Arcs.Insert(0, arc); labelF = labelF.PreLabel; arc = labelF.PreEdge; } loopPath.Arcs.Insert(0, arc); arc = labelB.PreEdge; while (arc.D_Point.ID != -1) { //pathday = arc.ArcType == 22 ? pathday + 1 : pathday; loopPath.Coef += arc.Cost; loopPath.Arcs.Add(arc); labelB = labelB.PreLabel; arc = labelB.PreEdge; } loopPath.Arcs.Add(arc); if (loopPath.Arcs.First().D_Point.DayofRoute != 0) { throw new Exception("ERROR:该path的第一条弧的末端点非身份节点"); } loopPath.crewID = loopPath.Arcs.First().D_Point.CrewID; //赋值身份节点 } if (loopPath.Arcs.Count == 0) { loopPath = default(Pairing); } return(loopPath); }
public void Build_RMP_YY(InitialSolution IS)//主问题的建模 { initialPath_num = IS.PathSet.Count; trip_num = TripList.Count; realistic_trip_num = NetWork.num_Physical_trip; A_Matrix = IS.A_Matrix; DvarSet = new List <INumVar>(); //x CoefSet = new List <double>(); //cij ObjCoefSet = new List <double>(); PathSet = new List <Pairing>(); //列池 CoefSet = IS.Coefs; //IS初始解 PathSet = IS.PathSet; ObjCoefSet = IS.ObjCoefs; foreach (var p in PathSet) { ColumnPool.Add(p); } masterModel = new Cplex(); Obj = masterModel.AddMinimize(); //Constraint = new IRange[realistic_trip_num]; Ct_cover = new IRange[NUMBER_CREW]; Ct_crewNum = new IRange[5][]; //默认每条交路为5天 ct_nb = new List <IRange>(); /**按行建模**/ //vars and obj function int i, j; for (j = 0; j < initialPath_num; j++) //定义决策变量和目标函数 { INumVar dvar = masterModel.NumVar(0, 1, NumVarType.Float); //INumVar-cplex里面的,定义决策变量。后面括号中的意思是定义var是0-1之间的浮点值 dvar.Name = "crew_" + PathSet[j].Arcs.First().D_Point.CrewID + "_" + j; DvarSet.Add(dvar); Obj.Expr = masterModel.Sum(Obj.Expr, masterModel.Prod(CoefSet[j], DvarSet[j]));//后面的小括号里面是一个cij*xj,大括号里面的是累计,包括之前的expr } /*constraints*/ //ct:每条交路每条担当的人数满足要求 #region //该条约束不需要,因为输入已经决定了,只要有可行解,该条约束必然满足 /*for (i = 0; i < 5; i++)//对每一天 * { * INumExpr expr = masterModel.NumExpr(); * Dictionary<int, List<int>> route_paths_map = new Dictionary<int, List<int>>(); * for (j = 0; j < initialPath_num; j++) //对每天的工作链分类 * { * if (A_Matrix[j][i] == 0) { * continue; * } * if (!route_paths_map.ContainsKey(A_Matrix[j][i])) { * route_paths_map.Add(A_Matrix[j][i], new List<int>()); * } * route_paths_map[A_Matrix[j][i]].Add(j); * } * * Ct_crewNum[i] = new IRange[route_paths_map.Count]; * foreach (var routePathsPair in route_paths_map) { //对第i天的每条交路 * foreach (var xj in routePathsPair.Value) * { * expr = masterModel.Sum(expr, DvarSet[xj]); * } * * Ct_crewNum[i][routePathsPair.Key-1] = masterModel.AddGe(expr, 1); //20191004 一条交路1个人 TODO * string name = "day_" + i + "_route_" + routePathsPair.Key; * Ct_crewNum[i][routePathsPair.Key-1].Name = name; * * ct_nb.Add(Ct_crewNum[i][routePathsPair.Key - 1]); * } * } */ #endregion // ct:每个乘务员只能有一条工作链 Dictionary <int, List <int> > crewID_paths_map = new Dictionary <int, List <int> >(); for (j = 0; j < initialPath_num; j++) { Pairing path = PathSet[j]; int crew_id = path.crewID; if (!crewID_paths_map.ContainsKey(crew_id)) { crewID_paths_map.Add(crew_id, new List <int>()); } crewID_paths_map[crew_id].Add(j); } if (crewID_paths_map.Count != NUMBER_CREW) { throw new System.Exception("乘务员数量有误"); } foreach (var crewID_paths_pair in crewID_paths_map) { INumExpr expr = masterModel.NumExpr(); foreach (var xj in crewID_paths_pair.Value) { expr = masterModel.Sum(expr, DvarSet[xj]); } Ct_cover[crewID_paths_pair.Key - 1] = masterModel.AddEq(expr, 1); } }
public StringBuilder translate_single_pairing(Pairing path, ref StringBuilder pathStr, ref SummarySingleDuty summary) { double start_time = 0, end_time = 0; int num_external_days = 0; string status = ""; pathStr.AppendFormat("{0}属于{1}号交路,其工作链是", path.Arcs.First().D_Point.Name, path.Arcs.First().D_Point.RoutingID); for (int i = 1; i < path.Arcs.Count - 1; i++) { Arc arc = path.Arcs[i]; status = arc.D_Point.TypeofWorkorRest == 1 ? "作" : "息"; pathStr.AppendFormat("({0}_{1}, {2})", arc.D_Point.Name, status, path.workVector[i - 1], "→"); summary.totalConnect += arc.Cost; } #region //MyRegion /* * foreach (Arc arc in path.Arcs) * { * switch (arc.ArcType)///弧的类型:1-接续弧,2-出乘弧,3-退乘弧, 20-虚拟起点弧,30-虚拟终点弧 * //弧的类型:1-接续弧, 2-虚拟起点弧,3-虚拟终点弧 * { * case 2: * pathStr.AppendFormat("{0}属于{1}号交路,其工作链是", arc.D_Point.Name, arc.D_Point.RoutingID); * break; * case 1: * status = arc.D_Point.TypeofWorkorRest == 1 ? "作" : "息"; * pathStr.AppendFormat("({0}_{1}, {2})", arc.D_Point.Name , status, path.workVector[], "→"); * summary.totalConnect += arc.Cost; * break; * * case 3: * break; #region * //case 2: * // pathStr.AppendFormat("{0}站{1}分出乘", arc.O_Point.StartStation, arc.D_Point.StartTime); * // start_time = arc.D_Point.StartTime; * // break; * //case 1: * // pathStr.AppendFormat("{0} {1}", arc.O_Point.TrainCode, "→"); * // summary.totalConnect += arc.Cost; * // break; * //case 22: * // pathStr.AppendFormat("{0} {1}", arc.O_Point.TrainCode, "→"); * // summary.totalConnect += arc.Cost; * // summary.externalRest += arc.Cost; * // num_external_days++; * // break; * //case 3: * // pathStr.AppendFormat("{0} {1}站{2}分退乘", arc.O_Point.TrainCode, arc.D_Point.EndStation, arc.O_Point.EndTime); * // end_time = arc.O_Point.EndTime; * // break; #endregion * default: * break; * } * }*/ #endregion //summary.totalLength = end_time - start_time; //summary.pureCrewTime = summary.totalLength - summary.totalConnect; //pathStr.AppendFormat(" 总长度 {0}\t纯乘务时间 {1}\t总接续时间 {2}\t外驻时间 {3}", // summary.totalLength, summary.pureCrewTime, summary.totalConnect, summary.externalRest); pathStr.AppendLine(); return(pathStr); }