/// <summary>
        /// read in the road network from the file
        /// </summary>
        /// <param name="roadnetworkFilename"></param>specifies the path to the filename of road network
        /// <returns></returns>
        public static RoadNetwork ReadRoadNetwork(string roadnetworkFilename)
        {
            Console.WriteLine("start to read the road network.");
            FileInfo     fRead       = new FileInfo(roadnetworkFilename);
            var          totalSize   = fRead.Length;
            var          fs          = fRead.OpenRead();
            StreamReader sr          = new StreamReader(fs);
            long         completeOld = 0;


            int nodeNum = Convert.ToInt32(sr.ReadLine());

            // add the node one by one
            List <Node> nodes     = new List <Node>();
            int         countNode = 0;

            while (countNode < nodeNum)
            {
                string[] items = sr.ReadLine().Split(new char[] { '\t' });
                Node     node  = new Node(Convert.ToInt32(items[0]), new LatLong(Convert.ToDouble(items[1]), Convert.ToDouble(items[2])));
                nodes.Add(node);
                long complete = fs.Position * 10 / totalSize;
                if (complete != completeOld)
                {
                    Console.WriteLine(complete * 10 + "% completed!");
                }
                completeOld = complete;
                countNode++;
            }

            //add the edge one by one
            int         edgeNum   = Convert.ToInt32(sr.ReadLine());
            List <Edge> edges     = new List <Edge>();
            int         countEdge = 0;

            while (sr.Peek() > 0)
            {
                string[] items     = sr.ReadLine().Split(new char[] { '\t' });
                string[] points    = sr.ReadLine().Split(new char[] { ',' });
                int      startID   = Convert.ToInt32(items[0]);
                int      endID     = Convert.ToInt32(items[1]);
                double   length    = Convert.ToDouble(items[2]);
                int      roadClass = Convert.ToInt32(items[3]);
                switch (roadClass)
                {
                case 41000:
                    roadClass = 0;
                    break;

                case 42000:
                    roadClass = 1;
                    break;

                case 51000:
                    roadClass = 2;
                    break;

                case 52000:
                    roadClass = 3;
                    break;

                case 53000:
                    roadClass = 4;
                    break;

                case 54000:
                    roadClass = 5;
                    break;

                case 43000:
                    roadClass = 6;
                    break;

                case 44000:
                    roadClass = 7;
                    break;

                case 45000:
                    roadClass = 8;
                    break;

                case 47000:
                    roadClass = 9;
                    break;

                case 49:
                    roadClass = 10;
                    break;

                case 100:
                    roadClass = 11;
                    break;

                default:
                    break;
                }
                int level     = Convert.ToInt32(items[9]);
                int direction = Convert.ToInt32(items[4]);
                int formway   = Convert.ToInt32(items[5]);
                int urban     = Convert.ToInt32(items[6]);
                int maxLanes  = Convert.ToInt32(items[7]);
                int maxSpeed  = Convert.ToInt32(items[8]);

                List <LatLong> pointLatlong = new List <LatLong>();
                foreach (var p in points)
                {
                    string[] subs = p.Split(new char[] { ' ' });
                    pointLatlong.Add(new LatLong(Convert.ToDouble(subs[0]), Convert.ToDouble(subs[1])));
                }

                edges.Add(new Edge(countEdge, startID, endID, length, roadClass, direction, formway, urban, maxLanes, maxSpeed, level, 10, pointLatlong));
                countEdge++;

                long complete = fs.Position * 10 / totalSize;
                if (complete != completeOld)
                {
                    Console.WriteLine(complete * 10 + "% completed!");
                }
                completeOld = complete;
            }


            sr.Close();

            RoadNetwork roadNetwork = new RoadNetwork(nodeNum, edgeNum, nodes, edges);

            return(roadNetwork);
        }
        /// <summary>
        /// read all files regarding to the mobility of the city in all time.
        /// </summary>
        /// <param name="roadNetwork"></param>the road network that use.
        /// <param name="roadMapFilename"></param>specifies the path to the map of mobility edge to the edge of road network.
        /// <param name="speedDirectory"></param>specifies the directory to all the speed information.
        /// <param name="pickDropPointsDirectory"></param>specifies the directory to the pickup and dropoff points.
        /// <returns></returns>
        public static ToTalMobility ReadMobility(RoadNetwork roadNetwork, string roadMapFilename, string speedFilename, string pickDropPointsFilename, string dayName)
        {
            Console.WriteLine("start to read the road map file.");
            StreamReader srMap = new StreamReader(roadMapFilename);
            Dictionary <int, List <int> > edgeRecords = new Dictionary <int, List <int> >();

            while (srMap.Peek() > 0)
            {
                string[] items = srMap.ReadLine().Split(new char[] { '\t' });
                if (Convert.ToInt32(items[1]) >= 0)
                {
                    if (!edgeRecords.ContainsKey(Convert.ToInt32(items[1])))
                    {
                        List <int> oriEdges = new List <int>();
                        oriEdges.Add(Convert.ToInt32(items[0]));
                        edgeRecords.Add(Convert.ToInt32(items[1]), oriEdges);
                    }
                    else
                    {
                        edgeRecords[Convert.ToInt32(items[1])].Add(Convert.ToInt32(items[0]));
                    }
                }
            }
            srMap.Close();

            Console.WriteLine("start to read the speed file.");


            Time[] timeStamps             = new Time[Time.NUMSLOTPERDAY];
            List <PickDropPoint>[] points = new List <PickDropPoint> [Time.NUMSLOTPERDAY];
            List <MobilityEdge>[]  edges  = new List <MobilityEdge> [Time.NUMSLOTPERDAY];
            for (int i = 0; i < Time.NUMSLOTPERDAY; i++)
            {
                points[i] = new List <PickDropPoint>();
                edges[i]  = new List <MobilityEdge>();
            }

            FileInfo     fRead       = new FileInfo(speedFilename);
            var          totalSize   = fRead.Length;
            var          fs          = fRead.OpenRead();
            StreamReader srSpeed     = new StreamReader(fs);
            long         completeOld = 0;

            StreamWriter swSpeed = new StreamWriter(@"D:\Result\Temporary\SpeedDistribution\speed.txt");

            int count = 0;

            while (srSpeed.Peek() > 0)
            {
                string[] items    = srSpeed.ReadLine().Split(new char[] { ' ' });
                int      edgeID   = Convert.ToInt32(items[0]);
                int      timeSlot = Convert.ToInt32(items[1]) / 2;
                if (Convert.ToInt32(items[1]) == 1)
                {
                    ;
                }
                double avgs        = Convert.ToDouble(items[2]);
                int    numVehicles = Convert.ToInt32(items[4]);
                if (numVehicles < 0)
                {
                    numVehicles = 0;
                }
                double stds  = Convert.ToDouble(items[3]);
                int    year  = Convert.ToInt32(dayName.Substring(0, 4));
                int    month = Convert.ToInt32(dayName.Substring(4, 2));
                int    day   = Convert.ToInt32(dayName.Substring(6, 2));

                swSpeed.WriteLine(avgs);

                timeStamps[timeSlot] = new Time(year, month, day, timeSlot);
                foreach (var ind in edgeRecords[edgeID])
                {
                    Edge oriEdge = roadNetwork.Edges[ind];
                    edges[timeSlot].Add(new MobilityEdge(oriEdge.EdgeID, oriEdge.StartID, oriEdge.EndID, oriEdge.Length, oriEdge.RoadClass,
                                                         oriEdge.Direction, oriEdge.FormWay, oriEdge.Urban, oriEdge.MaxLanes, oriEdge.MaxSpeed, oriEdge.Level,
                                                         oriEdge.AttributeNum, oriEdge.Points, avgs, numVehicles, stds));
                }

                long complete = fs.Position * 10 / totalSize;
                if (complete != completeOld)
                {
                    Console.WriteLine(complete * 10 + "% completed!");
                }
                completeOld = complete;
                count++;
            }
            srSpeed.Close();
            swSpeed.Close();

            Console.WriteLine("start to read the pickdroppoint directory.");
            StreamReader srPoint = new StreamReader(pickDropPointsFilename);

            while (srPoint.Peek() > 0)
            {
                string[] items = srPoint.ReadLine().Split(new char[] { ' ', ':', '/' });
                int      hour  = Convert.ToInt32(items[3]);
                int      min   = Convert.ToInt32(items[4]);
                //int timeSlot = (min <= 30) ? (hour * 2) : (hour * 2 + 1);
                int     timeSlot = hour;
                LatLong location = new LatLong(Convert.ToDouble(items[6]), Convert.ToDouble(items[7]));
                points[timeSlot].Add(new PickDropPoint(location, Convert.ToInt32(items[8])));
            }
            srPoint.Close();


            //start to built the totalModality
            Mobility[] mobilities = new Mobility[Time.NUMSLOTPERDAY];
            for (int i = 0; i < Time.NUMSLOTPERDAY; i++)
            {
                if (timeStamps[i] != null)
                {
                    mobilities[i] = new Mobility(edges[i], points[i], timeStamps[i]);
                }
            }
            ToTalMobility totalModality = new ToTalMobility(roadNetwork.Nodes, mobilities);

            return(totalModality);
        }
        public static void RetrieveLabelSubset4(string cityDataDirectory, string cityFeatureDirectory, int timeSlot, int normType)
        {
            string roadFilename        = Path.Combine(cityDataDirectory, @"roadnetwork\Road_Network_2014.txt");
            string roadFeatureFilename = Path.Combine(cityFeatureDirectory, @"roadNetworkFeature_0.015.txt");
            string poiFeatureFilename  = Path.Combine(cityFeatureDirectory, @"cityPOIFeature_0.015.txt");
            string aqiDirectory        = Path.Combine(cityFeatureDirectory, @"aqiFeature\0.015\");
            string mtlDirectory        = Path.Combine(cityFeatureDirectory, @"meterologyFeature\mode0\0.015\");
            string mobilityDirectory   = Path.Combine(cityFeatureDirectory, @"mobilityFeature\original\timeSlot24\0.015\");

            RoadNetwork roadNetwork = IO.ReadRoadNetwork(roadFilename);
            Grid        grid        = new Grid(roadNetwork.MinPoint, roadNetwork.MaxPoint, 0.015);

            //int numDays1 = new DirectoryInfo(aqiDirectory).GetDirectories().Count();
            //int numDays2 = new DirectoryInfo(mtlDirectory).GetDirectories().Count();
            //int numDays3 = new DirectoryInfo(mobilityDirectory).GetDirectories().Count();
            //int numDays = Math.Min(numDays1, Math.Min(numDays2, numDays3));

            CoupledDL.GraphInput       graphInput = new CoupledDL.GraphInput(timeSlot, 93, 4, roadFeatureFilename, poiFeatureFilename, mtlDirectory, mobilityDirectory, aqiDirectory, grid);
            CoupledDL.Graph.HyperGraph graph      = graphInput.ReadGraphFromFiles3(normType);

            int numFeature = graph.Nodes[2].Count();

            List <double>[] meterologyFeature = new List <double> [numFeature];
            List <double>[] mobilityFeature   = new List <double> [numFeature];
            List <double>[] roadFeature       = new List <double> [numFeature];
            List <double>[] poiFeature        = new List <double> [numFeature];
            List <double>[] aqiLabel          = new List <double> [numFeature];
            List <double>[] metGridIndex      = new List <double> [numFeature];
            for (int n = 0; n < numFeature; n++)
            {
                meterologyFeature[n] = new List <double>();
                roadFeature[n]       = new List <double>();
                poiFeature[n]        = new List <double>();
                aqiLabel[n]          = new List <double>();
                mobilityFeature[n]   = new List <double>();
                metGridIndex[n]      = new List <double>();
            }

            int count = 0;
            int i     = 0;

            foreach (var node in graph.Nodes[2]) //meterology
            {
                int roadIndex = -1;
                foreach (var road in graph.Nodes[0])
                {
                    if (node.GridIndex == road.GridIndex)
                    {
                        roadIndex = graph.Nodes[0].IndexOf(road);
                        break;
                    }
                }
                int poiIndex = -1;
                foreach (var poi in graph.Nodes[1])
                {
                    if (poi.GridIndex == node.GridIndex)
                    {
                        poiIndex = graph.Nodes[1].IndexOf(poi);
                        break;
                    }
                }
                if (roadIndex >= 0 && poiIndex >= 0)
                {
                    meterologyFeature[i] = node.Data;
                    mobilityFeature[i]   = graph.Nodes[3][count].Data;
                    roadFeature[i]       = graph.Nodes[0][roadIndex].Data;
                    poiFeature[i]        = graph.Nodes[1][poiIndex].Data;
                    aqiLabel[i].Add(node.Label);
                    metGridIndex[i].Add(node.GridIndex);
                    i++;
                }
                count++;
                if (count != i)
                {
                    Console.WriteLine();
                }
            }

            string outputDir = cityFeatureDirectory + @"\labeledSubset4\" + timeSlot.ToString("D2");

            if (!Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }
            string filename0 = Path.Combine(outputDir, "road.txt");
            string filename1 = Path.Combine(outputDir, "poi.txt");
            string filename2 = Path.Combine(outputDir, "meterology.txt");
            string filename3 = Path.Combine(outputDir, "label.txt");
            string filename4 = Path.Combine(outputDir, "mobility.txt");
            string filename5 = Path.Combine(outputDir, "metGridIndex.txt");

            IO.WriteFeature(roadFeature, filename0);
            IO.WriteFeature(poiFeature, filename1);
            IO.WriteFeature(meterologyFeature, filename2);
            IO.WriteFeature(mobilityFeature, filename4);
            IO.WriteFeature(aqiLabel, filename3);
            IO.WriteFeature(metGridIndex, filename5);
        }