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);
        }
Ejemplo n.º 3
0
        //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);
        }
Ejemplo n.º 4
0
        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;
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
            }
        }
Ejemplo n.º 8
0
        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);
        }