public void StartSimulation() { try { for (int RoundCount = 1; RoundCount <= 20; RoundCount++) { TotalDistanceOfUserWalk = 0; TotalDistanceOfBikeRides = 0;; AvailableBikesInTruck = 0; TotoalNumberOfbikesForPickup = 0; EventID = 1; GlobalTime = 0; ReadData(RoundCount); List <FutureEvent> FutureEventList = new List <FutureEvent>(); int MissRequestCount = 0; int HitRequestCount = 0; int RebalancingCount = 0; // For each cell in the list creat events and add new events to the FutureEventList //Read stations data from XML file System.Data.DataTable dtStationCells = new System.Data.DataTable(); dtStationCells.ReadXmlSchema(StationLocating.strRootResaultPath + "stationsSchema.xml"); dtStationCells.ReadXml(StationLocating.strRootResaultPath + "stations.xml"); double total1 = 0; foreach (System.Data.DataRow dr in dtStationCells.Rows) { double neareststationDistance; int neareststationindex = FindNearestStation(Convert.ToDouble(dr["Latitude"]), Convert.ToDouble(dr["Longitude"]), out neareststationDistance); StationList[neareststationindex].Weight += Convert.ToDouble(dr["Weight"]) * neareststationDistance; StationList[neareststationindex].totalWeight += Convert.ToDouble(dr["Weight"]); StationList[neareststationindex].RequestCount++; } foreach (System.Data.DataRow dr in dtStationCells.Rows) { double neareststationDistance; int neareststationindex = FindNearestStation(Convert.ToDouble(dr["Latitude"]), Convert.ToDouble(dr["Longitude"]), out neareststationDistance); StationList[neareststationindex].Weight += Convert.ToDouble(dr["Weight"]) * neareststationDistance; StationList[neareststationindex].totalWeight += Convert.ToDouble(dr["Weight"]); StationList[neareststationindex].RequestCount++; } foreach (var item in StationList) { item.Weight = item.Weight / item.totalWeight; Console.WriteLine(string.Format("Station Index : {0} Weight : {1} Request : {2}", item.Index, item.Weight, item.RequestCount)); item.RequestCount = 0; } Console.WriteLine("--------------------------------------------------*"); PrintStationStatus(); foreach (System.Data.DataRow dr in dtStationCells.Rows) { Troschuetz.Random.Distributions.Discrete.PoissonDistribution rnd = new Troschuetz.Random.Distributions.Discrete.PoissonDistribution(); rnd.Lambda = 100 - Convert.ToDouble(dr["Weight"]); int t = 0; while (t < 1440) // OneDay = 1440 minute { t += rnd.Next() * 5; FutureEventList.Add(new FutureEvent(EventID++, t, EventType.CustomerRequest, Convert.ToDouble(dr["Latitude"]), Convert.ToDouble(dr["Longitude"]))); } } //for (int GlobalTime = 0; GlobalTime < 1440; GlobalTime++) //{ // foreach (var item in FutureEventList.Where(e => e.StartTime == GlobalTime).OrderBy(e => e.EventId).ToList()) // { // Console.WriteLine(string.Format("ID: {0} Start: {1} Lat:{2} Long:{3}", item.EventId, item.StartTime, item.Latitud, item.Longitud)); // } //} for (int GlobalTime = 0; GlobalTime < 1440; GlobalTime++) { List <FutureEvent> events = FutureEventList.Where(e => e.StartTime == GlobalTime).OrderBy(e => e.EventId).ToList(); //List<FutureEvent> events = FutureEventList.OrderBy(e => new { e.StartTime, e.EventId }).ToList(); foreach (FutureEvent fe in events) { Random rndNextStation = new Random(); #region CustomerRequest Event if (fe.EventType == EventType.CustomerRequest) { double NearestStationDistance = 0;// (km) int NearestStationIndex = FindNearestStation(fe.Latitud, fe.Longitud, out NearestStationDistance); if (NearestStationIndex == -1) { MissRequestCount++; } else { FutureEvent ne = new FutureEvent(); ne.StationIndex = NearestStationIndex; ne.StartTime = fe.StartTime + Convert.ToInt32(Math.Round((NearestStationDistance / WalkSpeed) * 60, 0)); // t = s / v -> time = distance / speed , Average speed of walking for age of 20-50 is 3.6 km/h ne.EventType = EventType.BikeRentStart; FutureEventList.Add(ne); } } #endregion #region BikeRentStart Event else if (fe.EventType == EventType.BikeRentStart) { // If there is no Available Bike then Add Miss Count And go to next event if (StationList[fe.StationIndex].AvailebleBikes <= 0) { MissRequestCount++; PrintStationStatus(); continue; } HitRequestCount++; StationList[fe.StationIndex].AvailebleBikes -= 1; StationList[fe.StationIndex].RequestCount++; Console.WriteLine("1 Bike Pickedup from station " + fe.StationIndex); //Find Next Station based on Movement Probility Matrix double NextStationProbibility = rndNextStation.Next(0, 100) / 100.0; int NextStationIndex = -1; double tempTotalProbility = 0; for (int j = 0; j < MovementProbilityMatrix.Width; j++) { //x >= 1 && x <= 100 if (NextStationProbibility >= tempTotalProbility && NextStationProbibility < tempTotalProbility + MovementProbilityMatrix[fe.StationIndex, j]) { NextStationIndex = j; break; } else { tempTotalProbility += MovementProbilityMatrix[fe.StationIndex, j]; } } MovementCountMatrix[fe.StationIndex, NextStationIndex] += 1; FutureEvent ne = new FutureEvent(); ne.EventType = EventType.BikeRentFinish; ne.StationIndex = NextStationIndex; double DistanceToNextStation = StationList[fe.StationIndex].GetDistanceFromPosition(StationList[NextStationIndex].Latitude, StationList[NextStationIndex].Longitude); TotalDistanceOfBikeRides += DistanceToNextStation; ne.StartTime = fe.StartTime + Convert.ToInt32(Math.Round((DistanceToNextStation / BikeSpeed) * 60, 0)); // t = s / v -> time = distance / speed , Average speed of bikes is 15 km/h FutureEventList.Add(ne); if (StationList[fe.StationIndex].AvailebleBikes <= 0) { FutureEvent re = new FutureEvent(); re.EventType = EventType.Rebalancing; re.StationIndex = fe.StationIndex; re.StartTime = fe.StartTime + 1; FutureEventList.Add(re); } } #endregion #region BikeRentFinish Event else if (fe.EventType == EventType.BikeRentFinish) { StationList[fe.StationIndex].AvailebleBikes += 1; Console.WriteLine("1 Bike withdraw in station " + fe.StationIndex); if (StationList[fe.StationIndex].AvailebleBikes >= StationList[fe.StationIndex].Capasity) { FutureEvent re = new FutureEvent(); re.EventType = EventType.Rebalancing; re.StationIndex = fe.StationIndex; re.StartTime = fe.StartTime + 1; FutureEventList.Add(re); } } #endregion #region Rebalancing Event else if (fe.EventType == EventType.Rebalancing) { //?? Reblancing To which stations should be done? one station or multiple station ? //e.StartTime = DateTime.Now; // #### distance and duration to next station Should be determined in here //e.Distance = 0; // #### distance and duration to next station Should be determined in here RebalancingCount++; foreach (var item in StationList) //Pickup Extra Bikes from each station { if (item.AvailebleBikes > item.NumberOfBikes) { int NumberOfbikesForPickup = item.AvailebleBikes - item.NumberOfBikes; Console.WriteLine(NumberOfbikesForPickup.ToString() + " Bike Pickedup from station " + item.Index.ToString() + " for rebalancing" + " AvailebleBikes:" + item.AvailebleBikes + " NumberOfBikes: " + item.NumberOfBikes); TotoalNumberOfbikesForPickup += NumberOfbikesForPickup; AvailableBikesInTruck += NumberOfbikesForPickup; item.AvailebleBikes = item.NumberOfBikes; } } foreach (var item in StationList.OrderByDescending(s => s.NumberOfBikes - s.AvailebleBikes)) // withdraw bilke in each station which is needed { if (AvailableBikesInTruck > 0) { if (item.AvailebleBikes < item.NumberOfBikes) { if (AvailableBikesInTruck >= item.NumberOfBikes - item.AvailebleBikes) { AvailableBikesInTruck -= item.NumberOfBikes - item.AvailebleBikes; Console.WriteLine((item.NumberOfBikes - item.AvailebleBikes).ToString() + " Bike withdraw in station " + item.Index.ToString() + " for rebalancing" + " AvailebleBikes:" + item.AvailebleBikes + " NumberOfBikes: " + item.NumberOfBikes); item.AvailebleBikes = item.NumberOfBikes; } else { Console.WriteLine(AvailableBikesInTruck.ToString() + " Bike withdraw in station " + item.Index.ToString() + " for rebalancing" + " AvailebleBikes:" + item.AvailebleBikes + " NumberOfBikes: " + item.NumberOfBikes); item.AvailebleBikes = AvailableBikesInTruck; AvailableBikesInTruck -= AvailableBikesInTruck; } } } } } #endregion } } foreach (var item in StationList) { Console.WriteLine(string.Format("Station Index : {0} Weight : {1} Request : {2}", item.Index, item.Weight, item.RequestCount)); } #region Export Resault xlResaultDataSheet.Cells[1, 10] = "TotalDistanceOfUserWalk"; xlResaultDataSheet.Cells[1, 11] = "TotalDistanceOfBikeRides"; xlResaultDataSheet.Cells[1, 12] = "MissRequestCount"; xlResaultDataSheet.Cells[1, 13] = "HitRequestCount"; xlResaultDataSheet.Cells[1, 14] = "NumberOfBikesMoved"; xlResaultDataSheet.Cells[1, 15] = "RebalancingCount"; xlResaultDataSheet.Cells[RoundCount + 1, 10] = TotalDistanceOfUserWalk; xlResaultDataSheet.Cells[RoundCount + 1, 11] = TotalDistanceOfBikeRides; xlResaultDataSheet.Cells[RoundCount + 1, 12] = MissRequestCount; xlResaultDataSheet.Cells[RoundCount + 1, 13] = HitRequestCount; xlResaultDataSheet.Cells[RoundCount + 1, 14] = TotoalNumberOfbikesForPickup; xlResaultDataSheet.Cells[RoundCount + 1, 15] = RebalancingCount; xlStationsDataSheet.Cells[10, 1] = "SimulationRequestCount"; foreach (var item in StationList) { xlStationsDataSheet.Cells[10, item.Index + 2] = item.RequestCount; } Console.WriteLine("MovementProbilityMatrix : ------------------------------- " + RoundCount.ToString()); MovementProbilityMatrix.PrintMatrix(); Console.WriteLine("MovementCountMatrix : ------------------------------- " + RoundCount.ToString()); MovementCountMatrix.PrintMatrix(); MovementCountMatrix.FillMatrixWithEqalTotal(); #endregion } xlWorkBook.SaveAs(StationLocating.strRootResaultPath + "StationsData3.xls"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }