/// <summary> /// 构建列车弧 /// </summary> /// <param name="arcCount"></param> private void create_Line_T_S_Arcs(ref int arcCount) { for (int i = 0; i < T_S_NodeList.Count - 1; i++) { for (int j = i + 1; j < i + 2 /*T_S_NodeList.Count*/; j++) { // 因为在创建并添加点的时候,同一Line的出发点和到达点是先后创建添加的,所以内层不用循环 T_S_Node startPoint = T_S_NodeList[i]; T_S_Node endPoint = T_S_NodeList[j]; if (startPoint.LineID == endPoint.LineID && startPoint.PointType == 1 && endPoint.PointType == 2 && ((startPoint.TimeCode < 1440 && endPoint.TimeCode < 1440) || (startPoint.TimeCode >= 1440 && endPoint.TimeCode >= 1440))) { T_S_Arc t_s_arc = new T_S_Arc(); t_s_arc.Init_db(startPoint, endPoint, arcCount, startPoint.LineID, startPoint.RountingID, startPoint.TrainCode, startPoint.ID, endPoint.ID, startPoint.StaCode, endPoint.StaCode, startPoint.TimeCode, endPoint.TimeCode, 1);//1——运行弧 T_S_ArcList.Add(t_s_arc); startPoint.Out_T_S_ArcList.Add(t_s_arc); arcCount++; } } } }
public void Init_db(T_S_Node startPoint_, T_S_Node endPoint_, int id_, int lineID_, int routingID_, string trainCode_, int startPointID_, int endPointID_, string startStation_, string endStation_, int startTime_, int endTime_, int arcType_) { StartPoint = startPoint_; EndPoint = endPoint_; iD = id_; lineID = lineID_; rountingID = routingID_; trainCode = trainCode_; startPointID = startPointID_; endPointID = endPointID_; startStaCode = startStation_; endStaCode = endStation_; startTimeCode = startTime_; endTimeCode = endTime_; arcType = arcType_; len = endTimeCode - startTimeCode; }
public void Init_db(int id, int prevID, int lineID, int routingID, string trainCode, string station, int timeCode, int pointType, string OStation, int superID, int prevSuperID, T_S_S_Node prevNode, T_S_Node superPoint, T_S_Node prevSuperPoint) { this.iD = id; this.prevID = prevID; this.lineID = lineID; this.rountingID = routingID; this.trainCode = trainCode; this.staCode = station; this.timeCode = timeCode; this.pointType = pointType; this.OStation = OStation; this.superPointID = superID; this.prevSuperID = prevSuperID; this.PrevNode = prevNode; this.SuperPoint = superPoint; this.PrevSuperPoint = prevSuperPoint; }
public void CreateT_S_S_Network_db(/*CrewRule crewRule*/) { Debug.Assert(BasicTimeRules.MinConnTime != -1); List <T_S_S_Node> allStateNodes = new List <T_S_S_Node>(); Queue <T_S_S_Node> queue = new Queue <T_S_S_Node>(); initVirStartNode(ref allStateNodes, ref queue); //List<T_S_S_Node> tempDNodeList = new List<T_S_S_Node>(); //Dictionary<int, T_S_S_Node> IDToNodeDict = new Dictionary<int, T_S_S_Node>(); //foreach (var startNode in allStateNodes) { // IDToNodeDict.Add(startNode.ID, startNode); //} int debug_count = 100000; int debug_iter = 0; int nodeCount = CrewBaseList.Count * 2; //其余时空状态点的编号从乘务基地虚拟起终点之后开始 T_S_S_Node top_node; while (queue.Count > 0) { //if (--debug_count < 0) { // debug_count = 100000; // debug_iter++; // Console.WriteLine("current Queue.Count is [{0}]", queue.Count); // Console.WriteLine("debug iter is [{0}]", debug_iter); //} top_node = queue.Dequeue(); //Console.WriteLine(Logger.stateNodeInfoToStr(top_node, OutputMode.console)); //if (debug_iter >= 10) { // if (debug_count < 3000) { // Console.WriteLine("cur debug count is [{0}]", debug_count); // } //} T_S_Node cur_super_point = top_node.SuperPoint; List <T_S_Arc> out_T_S_ArcList = cur_super_point.Out_T_S_ArcList; for (int i = 0; i < out_T_S_ArcList.Count; i++) { T_S_Arc cur_t_s_arc = out_T_S_ArcList[i]; // debug //if (top_node.PassLine.Contains(30) // && top_node.PassLine.Contains(143) // //&& top_node.PassLine.Contains(64) // //&& top_node.PassLine.Contains(157) // && cur_t_s_arc.EndTimeCode == 1029 // && cur_t_s_arc.ArcType == 21) { // Console.WriteLine("top_node.PenaltyMealViolate:" + top_node.PenaltyMealViolate); //} //end debug T_S_S_Node extendStateNode = new T_S_S_Node(); extendStateNode.Resources = new Resource(lineList.Count); if (!FeasibleDriveTime(top_node, cur_t_s_arc, ref extendStateNode.Resources)) { continue; } if (!FeasibleDayCrewTime(top_node, cur_t_s_arc, ref extendStateNode.Resources)) { continue; } // 交路退乘点必须与出乘点相同 (必须回基地的约束) if (cur_t_s_arc.ArcType == 32 && cur_t_s_arc.EndStaCode != top_node.OStation) { continue; } // 用餐软约束 // 必须是非运行弧,才可能可以用餐 if (cur_t_s_arc.ArcType != 1) { handleMealConstraint(top_node, cur_t_s_arc, ref extendStateNode); // NOTE:可以处理一下,若当前弧用餐成功,则标记为用餐弧 } else { extendStateNode.Resources.SetLunchStatus(top_node.Resources.LunchStatus); extendStateNode.Resources.SetDinnerStatus(top_node.Resources.DinnerStatus); } // extendStartNode基本属性赋值 extendStateNode.Init_db(nodeCount, top_node.ID, cur_t_s_arc.LineID, cur_t_s_arc.RountingID, cur_t_s_arc.TrainCode, cur_t_s_arc.EndStaCode, cur_t_s_arc.EndTimeCode, cur_t_s_arc.ArcType, top_node.OStation, cur_t_s_arc.EndPointID, cur_super_point.ID, top_node, cur_t_s_arc.EndPoint, cur_super_point); // 还有其他属性 // 1 途径运行线 extendStateNode.PassLine.AddRange(top_node.PassLine); if (cur_t_s_arc.ArcType == 1) { extendStateNode.PassLine.Add(cur_t_s_arc.LineID); extendStateNode.Resources.LinesVisitedArray[cur_t_s_arc.LineID - 1] += 1; } // 2 起终点的编号 if (cur_t_s_arc.ArcType == 31) { extendStateNode.Price = 1440; Debug.Assert(extendStateNode.PenaltyMealViolate == 0); } else if (cur_t_s_arc.ArcType == 32) { extendStateNode.ID = BaseStationToODIDDict[extendStateNode.StaCode][1]; extendStateNode.Price = 0; --nodeCount; // 终点有自己的编号,所以此次不用增加nodeCount; Debug.Assert(extendStateNode.PenaltyMealViolate == 0); } else if (cur_t_s_arc.ArcType == 33) { extendStateNode.ID = BaseStationToODIDDict[extendStateNode.StaCode][1]; extendStateNode.Price = virtualRoutingCost; --nodeCount; // 终点有自己的编号,所以此次不用增加nodeCount; Debug.Assert(extendStateNode.PenaltyMealViolate == 0); } else { extendStateNode.Price = cur_t_s_arc.Len;// + extendStateNode.PenaltyMealViolate; //后续对弧再赋值Penalty } // 比较标号优劣 //for (int stateIdx = cur_t_s_arc.EndPoint.StateNodeSet.Count; stateIdx >= 0; stateIdx--) { //} top_node.Out_T_S_S_NodeList.Add(extendStateNode); allStateNodes.Add(extendStateNode); queue.Enqueue(extendStateNode); ++nodeCount; //if (cur_t_s_arc.ArcType != 32 && cur_t_s_arc.ArcType != 33) { // IDToNodeDict.Add(extendStateNode.ID, extendStateNode); //} //else { // tempDNodeList.Add(extendStateNode); //} } // end of loop "out_T_S_ArcList" } // end of loop "while" // 找出所有可行的状态点(即可以到达虚拟终点的状态点) #region //基于回溯 //T_S_S_NodeList = new List<T_S_S_Node>(); //foreach (T_S_S_Node note in tempDNodeList) { // int d = note.PrevID; // do { // if (IDToNodeDict.ContainsKey(d)) { // IDToNodeDict[d].Isfeasible = 1; // T_S_S_NodeList.Add(IDToNodeDict[d]); // d = IDToNodeDict[d].PrevID; // } // } // while (d != -1); //} //T_S_S_NodeList.AddRange(tempDNodeList); //T_S_S_NodeList.Sort(T_S_S_Node_AscByTime.nodeAsc); //int virODNum = CrewBaseList.Count * 2; //int newIDCount = virODNum; //foreach (var node in T_S_S_NodeList) { // if (node.ID >= virODNum) { // node.ID = newIDCount; // ++newIDCount; // } //} //foreach (var node in T_S_S_NodeList) { // if (node.PrevID >= 0) { // node.PrevID = node.PrevNode.ID; // } //} #endregion keepAllFeasibleStateNode(allStateNodes); // 根据可行状态点建立时空状态弧 createT_S_S_Arcs(); } // end of function CreateT_S_S_Network_db
/// <summary> /// 构建出退乘弧,包括虚拟乘务组出退乘弧,即停驻弧 /// </summary> /// <param name="arcCount"></param> private void create_OnAndOff_T_S_Arcs(ref int arcCount) { #region 创建出退乘弧 // 只需要一次遍历,因为目的就是把位于基地所在站的stationNode与基地起终点相连 for (int i = 0; i < T_S_NodeList.Count; i++) { T_S_Node stationPoint = T_S_NodeList[i]; T_S_Node baseStartPoint = null; T_S_Node baseEndPoint = null; bool isBaseStation = false; foreach (var crewbase in CrewBaseList) { if (stationPoint.StaCode == crewbase.StaCode) { isBaseStation = true; baseStartPoint = T_S_NodeList[crewbase.VirStartPointID - 1]; baseEndPoint = T_S_NodeList[crewbase.VirEndPointID - 1]; break; } } if (!isBaseStation) { continue; } if (stationPoint.PointType == 1 && stationPoint.TimeCode < 1440) { T_S_Arc t_s_arc = new T_S_Arc(); t_s_arc.Init_db(baseStartPoint, stationPoint, arcCount, 0, stationPoint.RountingID, stationPoint.TrainCode, baseStartPoint.ID, stationPoint.ID, stationPoint.StaCode, stationPoint.StaCode, 0, stationPoint.TimeCode, 31);//31——出乘弧 T_S_ArcList.Add(t_s_arc); baseStartPoint.Out_T_S_ArcList.Add(t_s_arc); arcCount++; } if (stationPoint.PointType == 2) { T_S_Arc t_s_arc = new T_S_Arc(); t_s_arc.ArcType = 32;//32——退乘弧 t_s_arc.Init_db(stationPoint, baseEndPoint, arcCount, 0, 0, stationPoint.TrainCode, stationPoint.ID, baseEndPoint.ID, stationPoint.StaCode, stationPoint.StaCode, stationPoint.TimeCode, 1440, 32);//32——退乘弧 if (t_s_arc.StartTimeCode > 1440) { t_s_arc.EndTimeCode = 2880; } T_S_ArcList.Add(t_s_arc); stationPoint.Out_T_S_ArcList.Add(t_s_arc); arcCount++; } } // 创建虚拟停驻弧,即虚拟乘务组出乘弧 foreach (CrewBase crewbase in CrewBaseList) { T_S_Node startPoint = T_S_NodeList[crewbase.VirStartPointID - 1]; T_S_Node endPoint = T_S_NodeList[crewbase.VirEndPointID - 1]; T_S_Arc t_s_arc = new T_S_Arc(); t_s_arc.Init_db(startPoint, endPoint, arcCount, 0, 0, "", crewbase.VirStartPointID, crewbase.VirEndPointID, crewbase.StaCode, crewbase.StaCode, 0, 1440, //若是两天会有些变化 33); //33——虚拟乘务组出退乘弧 T_S_ArcList.Add(t_s_arc); startPoint.Out_T_S_ArcList.Add(t_s_arc); arcCount++; } #endregion }
/// <summary> /// 创建日间连接弧和夜间连接弧 /// </summary> /// <param name="arcCount"></param> /// <param name="minConnTime"></param> /// <param name="maxConnTime"></param> private void create_Connect_T_S_Arcs(ref int arcCount, int minConnTime, int maxConnTime) { Dictionary <string, List <T_S_Node> > StationToPointDict = new Dictionary <string, List <T_S_Node> >(); foreach (var point in T_S_NodeList) { if (point.PointType == 3 || point.PointType == 4) { continue; } if (!StationToPointDict.ContainsKey(point.StaCode)) { StationToPointDict.Add(point.StaCode, new List <T_S_Node>()); } StationToPointDict[point.StaCode].Add(point); } foreach (var pointset in StationToPointDict.Values) { pointset.Sort(T_S_Node_AscByTime.pointAsc); for (int i = 0; i < pointset.Count; i++) { T_S_Node startPoint = pointset[i]; if (startPoint.PointType == 1) { continue; // 连接弧的起点必须是到达点 } for (int j = i + 1; j < pointset.Count; j++) { // 因为排序了,所以后面的node j必然不早于前面的node i,所以可以直接 i + 1 T_S_Node endPoint = pointset[j]; if (endPoint.PointType == 2) { continue; // 连接弧的终点必须是出发点 } int len = endPoint.TimeCode - startPoint.TimeCode; if (len < minConnTime) { continue; } else if (len > maxConnTime) { break; } else { // 不考虑多天的情况,暂且仅考虑1天 // 故在此可以直接创建弧 T_S_Arc t_s_arc = new T_S_Arc(); t_s_arc.Init_db(startPoint, endPoint, arcCount, startPoint.LineID, startPoint.RountingID, startPoint.TrainCode, startPoint.ID, endPoint.ID, startPoint.StaCode, endPoint.StaCode, startPoint.TimeCode, endPoint.TimeCode, 21);//21——日间连接弧 T_S_ArcList.Add(t_s_arc); startPoint.Out_T_S_ArcList.Add(t_s_arc); arcCount++; } } } } }
public void LoadData_csv(int Days, string timetableFile, string crewbaseFile, string crewFile, string stationFile) { string f1 = timetableFile; string f2 = crewbaseFile; string f3 = crewFile; string f4 = stationFile; int j; string[] str = new string[7]; StreamReader csv = new StreamReader(f1, Encoding.Default); string row = csv.ReadLine(); row = csv.ReadLine(); //Dictionary<string, bool> StationMap = new Dictionary<string, bool>(); LineList = new List <Line>(); T_S_NodeList = new List <T_S_Node>(); while (row != null) { str = row.Split(','); Line line = new Line(); line.ID = Convert.ToInt32(str[0]); line.LineID = Convert.ToInt32(str[0]); line.TrainCode = Convert.ToString(str[1]); line.RountingID = Convert.ToInt32(str[6]); line.DepStaCode = Convert.ToString(str[2]); line.DepTimeCode = Convert.ToInt32(str[4]); line.ArrStaCode = Convert.ToString(str[3]); line.ArrTimeCode = Convert.ToInt32(str[5]); line.LagMultiplier = 0.0; line.NumSelected = 0; LineList.Add(line); for (j = 0; j < Days; j++) { T_S_Node t_s_node1 = new T_S_Node(); t_s_node1.ID = (Convert.ToInt32(str[0]) * 2 - 1); t_s_node1.LineID = Convert.ToInt32(str[0]); t_s_node1.RountingID = Convert.ToInt32(str[6]); t_s_node1.TrainCode = Convert.ToString(str[1]); t_s_node1.StaCode = Convert.ToString(str[2]); t_s_node1.TimeCode = Convert.ToInt32(str[4]) + 1440 * j; t_s_node1.PointType = 1;//1——始发点,2——终到点 T_S_NodeList.Add(t_s_node1); T_S_Node t_s_node2 = new T_S_Node(); t_s_node2.ID = (Convert.ToInt32(str[0]) * 2); t_s_node2.LineID = Convert.ToInt32(str[0]); t_s_node2.RountingID = Convert.ToInt32(str[6]); t_s_node2.TrainCode = Convert.ToString(str[1]); t_s_node2.StaCode = Convert.ToString(str[3]); t_s_node2.TimeCode = Convert.ToInt32(str[5]) + 1440 * j; t_s_node2.PointType = 2;//1——始发点,2——终到点 T_S_NodeList.Add(t_s_node2); row = csv.ReadLine(); } } csv.Close(); //CrewBase CrewBaseList = new List <CrewBase>(); csv = new StreamReader(f2, Encoding.Default); row = csv.ReadLine(); row = csv.ReadLine(); while (row != null) { str = row.Split(','); #region 录入虚拟起终点 T_S_Node t_s_node1 = new T_S_Node(); t_s_node1.ID = T_S_NodeList.Count + 1; t_s_node1.LineID = 0; t_s_node1.RountingID = 0; t_s_node1.TrainCode = ""; t_s_node1.StaCode = Convert.ToString(str[1]); t_s_node1.TimeCode = 0; t_s_node1.PointType = 3;//1——始发点,2——终到点,3——虚拟起点 T_S_NodeList.Add(t_s_node1); base_start_pointList.Add(t_s_node1); T_S_Node t_s_node2 = new T_S_Node(); t_s_node2.ID = T_S_NodeList.Count + 1; t_s_node2.LineID = 0; t_s_node2.RountingID = 0; t_s_node2.TrainCode = ""; t_s_node2.StaCode = Convert.ToString(str[1]); t_s_node2.TimeCode = 0; t_s_node2.PointType = 4;//1——始发点,2——终到点,4——虚拟终点 T_S_NodeList.Add(t_s_node2); base_end_pointList.Add(t_s_node2); #endregion CrewBase crewbase = new CrewBase(); crewbase.ID = Convert.ToInt32(str[0]); crewbase.StaCode = Convert.ToString(str[1]); crewbase.PhyCrewCapacity = Convert.ToInt32(str[2]); crewbase.VirCrewCapacity = Convert.ToInt32(str[3]); crewbase.VirStartPointID = T_S_NodeList.Count - 1; crewbase.VirEndPointID = T_S_NodeList.Count; //crewbase.VirStartPointID = Convert.ToInt32(Dt.Rows[i]["时空网起点标号"]); //crewbase.VirEndPointID = Convert.ToInt32(Dt.Rows[i]["时空网终点标号"]); crewbase.OIDinTSS = Convert.ToInt32(str[4]); crewbase.DIDinTSS = Convert.ToInt32(str[5]); CrewBaseList.Add(crewbase); if (!BaseStationToODIDDict.ContainsKey(crewbase.StaCode)) { BaseStationToODIDDict.Add(crewbase.StaCode, new int[2] { crewbase.OIDinTSS, crewbase.DIDinTSS }); } else { throw new Exception("读取基地数据错误!!"); } row = csv.ReadLine(); } csv.Close(); //Crew csv = new StreamReader(f3, Encoding.Default); row = csv.ReadLine(); CrewList = new List <Crew>(); while (!csv.EndOfStream) { row = csv.ReadLine(); str = row.Split(','); Crew crew = new Crew(); crew.ID = Convert.ToInt32(str[0]); crew.OutCost = Convert.ToDouble(str[1]); crew.RemainCost = Convert.ToDouble(str[2]); CrewList.Add(crew); } //station StationList = new List <Station>(); csv = new StreamReader(f4, Encoding.Default); row = csv.ReadLine(); row = csv.ReadLine(); while (row != null) { str = row.Split(','); Station station = new Station(); station.ID = Convert.ToInt32(str[0]); station.StaCode = str[1]; station.ReMainCrew = Convert.ToInt32(str[2]); StationList.Add(station); row = csv.ReadLine(); } }