+ All Categories
Home > Documents > Executive Summary - Princeton Universityorfe.princeton.edu/~alaink/Theses/2013/Independent...

Executive Summary - Princeton Universityorfe.princeton.edu/~alaink/Theses/2013/Independent...

Date post: 13-May-2018
Category:
Upload: vuongdieu
View: 217 times
Download: 2 times
Share this document with a friend
77
Junior Independent Work: Uncongested Mobility for All New Jersey’s Area-wide autonomous Taxi System Alice Lin ‘14 Adviser: Professor Alain Kornhauser Operations Research and Financial Engineering
Transcript

Junior Independent Work:

Uncongested Mobility for AllNew Jersey’s Area-wide autonomous Taxi

System

Alice Lin ‘14Adviser: Professor Alain Kornhauser

Operations Research and Financial EngineeringPrinceton UniversityTuesday, May 7, 2013

Table of ContentsEXECUTIVE SUMMARY...........................................................................................................................1

INTRODUCTION.....................................................................................................................................1

WARREN COUNTY..................................................................................................................................5

RIDESHARE ANALYSIS.............................................................................................................................7

FLEET SIZE...........................................................................................................................................14

GRAPHICS............................................................................................................................................16

APPENDIX A.........................................................................................................................................18RELEVANT CODE......................................................................................................................................... 18

Executive Summary

Junior Independent Work:

Uncongested Mobility for AllNew Jersey’s Area-wide autonomous Taxi

System

Alice Lin ‘14Adviser: Professor Alain Kornhauser

Operations Research and Financial EngineeringPrinceton UniversityTuesday, May 7, 2013

My independent work continues the work of Princeton’s ORF 467 Transportation Analysis Fall 2012 course, where the goal was to evaluate an autonomous taxi system in the state of New Jersey by looking at the potential of casual ride sharing (thereby reducing congestion, negative environmental impacts, and excess energy consumption). I have chosen one county to focus specifically on (namely Warren County). This report will look specifically into Warren’s overall potential for ride sharing, simulating it to fit real world assumptions as best as possible with the given data. It will then give a tentative number for minimum fleet size in Warren. Computer graphics that simulate the autonomous taxis are also included.

Introduction

Ultimate GoalsFor years, ORF 467 has been designing and analyzing State-wide PRT networks for New Jersey. Networks that consisted of roughly 10,000 stations interconnected by 10,000 miles of guideway used by 750,000 PRT vehicles capable of providing high-quality, non-stop, demand responsive service to 90% of the 30 million trips made in New Jersey on a typical day. Capital costs were optimistically estimated to be of the order of $150B and operating costs being arguably less than the marginal operating cost of today’s car. Unfortunately the demand analyses were crippled by demand data insufficiently précises enough spatially to properly evaluate the walk disutility associated with accessing the precise station locations nor sufficiently precise temporally to properly ascertain the ride-share, and thus efficiency opportunity, of demand-responsive PRT service.

The Fall 2011 ORF 467 class began addressing the demand data shortcomings by building an individual’s activity-based trip synthesizer, Synthesizing Individual Trip Travel Demand in New Jersey. This trip synthesizer, enhanced by Talal Mufti in his MSR thesis, Chris Brownell in his ORFE BSE thesis and the Fall 2012 ORF 467 class, generates demographic characteristics for each of the 8,791,894 individuals living in 118,654 census blocks that comprise New Jersey. Each individual’s demographic signature is used to draw from appropriate distributions the individual’s daily travel tour behavior as well the specific name and address of every establishment visited by each individual on a typical day. The spatial specificity of the census blocks characterizes the spatial accuracy of the home end of home-based trips. Geo-coded addresses of the non-home end(s) of each trip complete the spatial specificity. Arrival time and duration distributions for each type of establishment (school, workplace, restaurant, etc.) are used to randomly select precise departure times, in seconds-from-midnight, for every trip segment to provide the desired temporal specificity. For completeness, trips made by out-of-state residents working in New Jersey are also synthesized to yield a detailed spatial and temporal representation of the more than 30 million trips made to or from locations in New Jersey on a typical weekday.

The other “non-starter” of Area-Wide PRT is its dependence on an extensive dedicated guideway infrastructure required to interconnect all of the stations. While PRT stations can be readily be integrated in facilities that would embrace the premier accessibility and clientele connectivity afforded by such stations and residential areas tend to have centralized open space that make ideal station locations, the guideways are the real challenge. It is cost prohibitive to place them out of sight underground and considered unsafe to place at-grade. Overhead, while expensive, is technologically feasible, but architecturally and societally unacceptable. Architects have yet to be creative enough to design overhead guideways that are neighborhood friendly and no one wants an elevated guideway going anywhere near their bedroom window. Case closed!However, the advent autonomous vehicles, like Prospect 12 or the Google car, presents the opportunity to address both shortcomings of PRT and have the opportunity to deliver PRT-like, and consequently auto-like, mobility to all throughout New Jersey. Consider an aTaxi (autonomousTaxi) system comprising of autonomous automated vehicles operating from designated aTaxi stands located throughout New Jersey at places similar to that of PRT stations whereby aTaxis would travel between aTaxi stands using New Jersey’s existing road and highway infrastructure. Since aTaxis are being designed to operate automatically in traffic with human-operated vehicles while not requiring any change in the existing roadway infrastructure, such a system can readily begin to operate effectively with but a single pair of aTaxi stands. From this beginning, additional aTaxi stands can readily be located/built where ever there exists sufficient customer demand. As aTaxi stands are added, the mobility afforded grows more quickly, especially at first because of the network connectivity effects, while only requiring the addition of aTaxi stands and not interconnecting guideway. This will allow the system to grow and evolve naturally. Much later, a point of diminishing return will undoubtedly be reached but this point seems to be so close to service for all that service for all can be offered at a very small additional cost. Importantly, the system has the opportunity to grow naturally or “virally” from austere beginning to serve much if not all of New Jersey.

While autonomous vehicles can evolve to be simply chauffeured versions of our existing cars, providing an even high form of mobility, in that they emancipate us from the driving function and make travelling substantially safer, they continue to carry the detrimental availability, congestion, environmental and energy side-effects of the existing automobile. Assembling a fleet of these vehicles offering on-demand mobility between aTaxi stands conveniently located nearby essentially anywhere anyone wants to go from and to in New Jersey may attract the patronage of enough customers to take many, if not most cars off the roads, especially during times when roadways are congested. If he demand is high and concentrated enough to allow for substantial casual sharing of aTaxi rides, then more manually driven cars would be taken off of congested roads than are being replaced by aTaxis, thus not only addressing the automobile’s detrimental attribute availability, but also reducing congestion, environmental impact and energy consumption.

Report’s GoalsReasonable data that represents individual trips (as described above) have already been generated by other individuals also looking into the aTaxi problem. This report looks specifically at the feasibility of an aTaxi system by evaluating ride sharing potential in the county of Warren using the trip data files generated for Warren. To make this evaluation more physically applicable to situations in the real world, conditions such as delay departure, common destinations, and path-linked pick-ups are introduced. A minimum fleet size for Warren will then be determined using the data generated from ride sharing evaluations. Another goal of this report is to simulate the dynamics of an aTaxi system through computer graphics. This is intended to show relevant statistics such as which parts of the county generate the most trips (and at what time of the day) as well as information on the number of taxi trips that each individual taxi potentially completes.

Warren County

Brief Summary3 Letter Abbreviation: WAR

FIPS code: 41

Population size: 108,692

Population density: 303/sq mi

Total area: 362.86 sq miLand: 356.92 sq miWater: 5.94 sq mi

Important/Large cities: Phillipsburg (largest city)

Features of Warren: Its largest city, Phillipsburg, contains the Phillipsburg School District, a public school service that educates students from pre-kindergarten through the last year of high school. One of its largest schools is Phillipsburg High School, which gives high school level education to students from Phillipsburg as well as five other neighboring communities.

Map of Warren County Phillipsburg’s location in Warren

Relevant County Statistics

Warren Summary DataItem valueArea (sq miles) 303# of pixels generating at least 1 trip 1,023# of pixels generating at least 1 taxi trip

1,023

Area of pixels (sq miles) 255.75% “Open Space” 15.59%# of All Trips 291,888# of Walk Trips 18,933# of IntraPixel Trips 3,653# of Taxi Trips 269,302Average Trip Length (all trips) 23.88 milesMedian Trip Length (all trips) 21 milesAverage Trip Length (taxi trips) 25.83 miles Median Trip Length (taxi trips) 24 miles*All Trip Lengths are Manhattan Distances between pixel centroids.* Only the Taxi Trips (269,203 in total) are relevant in this report.

Taxi Trip Distributions

Ride Share Analysis

Common Destinations

For any aTaxi stand (or pixel) during any time of the day, the Ride Share Potential is described by the distribution of the number of normalized aTaxis dispatched during the appropriate time of day, versus the occupancy of the dispatched vehicles (the number of customers that arrive at an aTaxiStand destined to Common ride sharing Destinations (CD) within a fixed Dispatch Delay (DD) time interval). These customers are served by a common aTaxi. Generally speaking, as CD increases, Ride Share Potential increases, but the quality of service subsequently decreases. Similarly, as DD increases, the Ride Share Potential also increases, but the quality of service decreases.

To evaluate the ride sharing potential, we read in each passenger trip in order of the passenger’s arrival at their origin pixel. Ride sharing is simulated by taking the time of the next arriving passenger, dispatching all waiting

Individual Taxi Stand: Phillipsburg High School

Pixel Rank (in terms of taxi trips generated): 15

Pixel (Y,X): (248,44)

# of Taxi Trips Generated: 2878

Average Taxi Trip Length: 33.51 miles

Median Taxi Trip Length: 44.5 miles

aTaxis that have exceeded their DD, recording their occupancy at time of dispatch, and scanning the yet-to-be-dispatched aTaxis for a CD match. If a CD is found, we then direct this arriving passenger to the CD matched aTaxi, thus increasing its occupancy by one and delaying this passenger’s departure time to the departure time of this aTaxi (which was set to be DD minutes after the first occupant’s original departure time). If a CD is not found, then we direct the passenger to occupy a new waiting aTaxi, set its destination to that of this first passenger and delay this passenger’s and this aTaxi’s departure time by DD. We do this for all trips in the data file.

As CD increases, we also have to take into account the fact that with the arrival of a new passenger trip, an existing waiting taxi could potentially be assigned a new CD, so that there are one or more mid-stops for this taxi. For instance, if CD = 2, then we could potentially have a taxi that drops off the first batch of passengers at the first destination and then goes on to drop off the second batch of passengers at the second (and final) destination. The assumption for creating a new CD for an existing waiting taxi is to add on a new CD if this does not increase the taxi distance travelled by more than 20%, for each leg of the trip.

In other words:Read in Trip File:Given for all trips: Trip’s origin arrival Time (OT), origin Pixel (OP), destination Pixel (DP)Sort all trips by OP, then OT, then DPFor all trips with same OP: Read in Trip i: Look through the list of waiting Taxis that have yet to be dispatched: Dispatch Taxis that have exceeded their DD (taxi->departure Time is less than trip->OT)

If a CD with Taxi j’s existing CD’s is found: assign Trip i to Taxi jIf a CD with Taxi j’s existing CD’s is not found: If Taxi j already has the max # of CD’s it can partake: go on to next Taxi If Taxi j does not have the max # of CD’s it can partake: Determine if adding in a new CD=DP is within the 20% assumption: If Distance(origin->CD(1)->…->CD(n))/Distance(origin->CD(1)->…->CD(n-1)) <= 1.2 And Distance(origin->CD(1)->…->CD(n-1))/Distance(origin->CD(1)->…->CD(n-2)) <= 1.2 …

And Distance(origin->CD(1)->CD(2))/Distance(origin->CD(1)) <= 1.2:Then assign OP as a new CD for Taxi j and assign Trip i to Taxi j

Else:Go on to next Taxi

If no Taxi’s can take this trip: have Trip i occupy a new Taxi with a departure time equal to the passenger’s arrival time + DD add this new Taxi to the waiting taxis list(The resulting DepartedTaxis.csv file contains all relevant information on the dispatch taxis. This file will later be used to determine fleet size.)

This is without path-linked pickups. Later on, this feature will also be added.

All of Warren County, All Day:Total Person Trips: 269,302Total Person Trip Miles: 13,911,834Person Trip Miles (PTM)Ataxi Trip Miles (ATM)

Person Trip Miles / aTaxi Trip Miles (PTM/ATM) represent ride share potential. In other words, as ride sharing potential increases, the total number of taxi miles travelled in the system much decrease, holding person trip miles constant. As evident from the above PTM/ATM numbers, the general trend for DD is that as DD increases, so does ride sharing potential. The general trend for CD is that as CD increase, so does ride sharing potential.

Without Path-linked Pickups, however, this simulation is not very realistic in regards to what would happen in a real world aTaxi System for CD > 1. As such, in all further analysis, the system enables pickups along the way for all taxis.

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.04982 1.07023 1.08534 1.09785 1.1082

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.23912 1.32373 1.37874 1.42125 1.4543

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.30732 1.43413 1.52134 1.58935 1.6452

Path-linked PickupsPath-linked Pickups is simulated by seeing if at the time that a taxi arrives at an intermediate CD, there is a person trip that could be added to this taxi. If CD = 1, then pickups will have no effect on the simulation. If CD > 1, however, then several changes are implemented in the simulation code to take in the pickup-along-the-way effect. In the code, each taxi only stops at an intermediate CD for exactly DD seconds. This taxi would “pick up” a passenger if that person arrives at this intermediate CD within those DD seconds and has a destination that corresponds to one of the later CD’s that the taxi will ultimately stop at.

Instead of sorting the trips from the trip file by OP, then OT, and then DP, path-linked pickups sorts the trips by OT, then OP, and then DP. Whereas without pickups we could ignore a waiting taxi if this taxi’s origin pixel does not equal the trip’s origin pixel, we now have to take into account the fact that the taxi could pick up this trip along the way. As such, sorting first by OP and then deleting all taxis from the waiting taxi list when the OP changes to another is no longer appropriate. Now, we can only delete a waiting taxi from the list when the taxi’s arrival time at its penultimate CD + DD (the result of this would be the taxi’s departure time from the penultimate CD to its final CD) is before the person trip’s origin time.

In other words:Read in Trip File:Given for all trips: Trip’s origin arrival Time (OT), origin Pixel (OP), destination Pixel (DP)Sort all trips by OT, then OP, then DP Read in Trip i: Look through the list of waiting Taxis that have yet to be dispatched: Dispatch Taxis that have exceeded their DD (taxi->penultimate CD Arrival Time + DD is less than trip->OT) If Trip i and Taxi j have the same origin pixel (basically same process as without pickups):

If a CD with Taxi j’s existing CD’s is found: assign Trip i to Taxi jIf a CD with Taxi j’s existing CD’s is not found: If Taxi j already has the max # of CD’s it can partake: go on to next Taxi If Taxi j does not have the max # of CD’s it can partake: Determine if adding in a new CD=DP is within the 20% assumption: If Distance(origin->CD(1)->…->CD(n))/Distance(origin->CD(1)->…->CD(n-1)) <= 1.2 And Distance(origin->CD(1)->…->CD(n-1))/Distance(origin->CD(1)->…->CD(n-2)) <= 1.2 …

And Distance(origin->CD(1)->CD(2))/Distance(origin->CD(1)) <= 1.2:Then assign OP as a new CD for Taxi j and assign Trip i to Taxi j

Else:Go on to next Taxi

Else (if Trip i and Taxi j do not have the same origin pixel)If Taxi j has a CD that matches Trip i’s OP and Taxi j has a later CD that matches Trip i’s DP and Trip i’s OT is between the interval of time that Taxi j is at the prior CD (j’s arrival time to the prior CD and j’s departure time from the prior CD, which is equal to its arrival time + DD): Assign this Trip i to Taxi j

If no Taxi’s can take this trip: have Trip i occupy a new Taxi with a departure time equal to the passenger’s arrival time + DD add this new Taxi to the waiting taxis list

(The resulting DepartedTaxis.csv file contains all relevant information on the dispatch taxis. This file will later be used to determine fleet size.)

Due to the harder to achieve condition for deleting waiting taxis, however, the waiting taxi list becomes extremely long and the simulation runs extremely slowly. To speed up this process, I introduced a mapping process into the simulation code. Instead of keeping one extremely long waiting taxi list that each trip has to potentially look through, I keep several waiting taxi lists that are organized in a way so that for each trip, we only have to look at lists that contain relevant waiting taxis. To do this, I would need the range of Y pixels and X pixels for the trip file (right now, the range for Y in the code is initialized from 0 to 350 and the range for X in the code is initialized from 0 to 250). There would potentially be a waiting taxis list for each individual station in the trip file. A newly created taxi is added to the list for it’s first passenger’s OP. If this taxi gets put with a new CD, then this taxi is also added to the list for the CD that the taxi goes to first. For instance, a taxi that goes from OP->CD(1)->CD(2)->CD(3)->CD(4) would be in the waiting taxis list for OP, CD(1), CD(2), and CD(3). It would not be in the list for CD(4) since it is not going anywhere after CD(4) and thus obviously cannot pick up any more passengers at CD(4). A trip would look only through the list for its OP and would ignore all the other lists.

This mapping process speeds up the ride share simulation considerably for pickups-along-the-way. Although some complicated mapping (and sometimes unreadable code) went into this process, the final result was worth the trouble since it reduces a 10 minute simulation process to approximately 2 minutes or less. Later on, this mapping idea will also be used for determining Fleet Size, also speeding up that process considerably.

All of Warren County, All Day:Total Person Trips: 269,302Total Person Trip Miles: 13,911,834Person Trip Miles (PTM)Ataxi Trip Miles (ATM)

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.24252 1.32893 1.38454 1.42795 1.4615

With path-linked pickups implemented, we see a general increase in ride sharing potential. However, this increase, although very evident, seems to be rather small. As CD increases, however, the increase in ride sharing potential between a simulation without pickups and a simulation with pickups also increases. This is reasonable since the potential for pickups along the way increases when there are more mid-destinations.

Despite the rather small increases in the ride sharing potential, however, it is still very evident that between the small time interval (DD) when a taxi stops at a mid-destination, there are person trips that arrive looking to go to one of the destinations that this taxi will later go to. Without pickups implemented, another taxi would have had to be dispatched for the person trip(s).

Pixel(248,44): Phillipsburg High School

Pixel(248,44), All Day:Total Person Trips: 2,878Total Person Trip Miles: 192,873Person Trip Miles (PTM)Ataxi Trip Miles (ATM)

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.31192 1.44143 1.53044 1.60045 1.6566

Pixel(248,44), 3:53 to 4:30 PM:Total Person Trips: 1,590Total Person Trip Miles: 77,723Person Trip Miles (PTM)Ataxi Trip Miles (ATM)

From the above, one can see that the time of day also determines the ride share potential. For Phillipsburg High, for instance, the interval of time when the high school lets out has a substantially higher ride share potential than the entire day.

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.41382 1.58413 1.71694 1.80515 1.8788

DD (minutes)

Person Trip Miles / Taxi Trip Miles

1 1.50962 1.69573 1.88434 1.98935 2.1652

Fleet Size

To determine a minimum fleet size for an aTaxi system, I upheld several assumptions. First, a state-wide New Jersey autonomous taxi system may be viewed as a “closed” system. In other words, all taxi trips take place from one taxi stand in New Jersey to another taxi stand in New Jersey, as opposed to it going to or from a taxi stand outside of New Jersey. It would be reasonable to assume this since taxis drop off passengers at train stations that can subsequently go out of state. Due to this, a taxi would potentially never need to venture outside of the terrain of New Jersey. As such, I will determine the minimum fleet size for Warren County (think of it as a miniature New Jersey) based only on the trips that originate in and end in Warren.

At first, my simulation did not allow empty taxis to travel between stations. This yielded rather high fleet sizes ,and on average, each taxi would only complete two taxi trips per day. This assumption was as such rather unrealistic.

To make this simulation more realistic, I also included the fact that empty waiting taxis could travel between stations so that a station in demand could simply call a taxi from a neighboring station that is not as in demand. However, we would only know that a station is in demand when a passenger in need arrives at a station. As such, my idea involved dispatching an available from a neighboring station only if it could reach the station in need within DD, before the passenger needs to leave.

Another idea that I implemented into this was to a system where the person would call in some time (say 5 or 10 minutes) before he/she arrives at the station. This gives more leeway to which stations can dispatch an available taxi, since it may be possible that all immediate neighbors of this station in need also have no available taxis when the person first arrives.

To speed up my simulation for fleet size determination, I again implemented the mapping process described above for path-linked pickups. This considerably sped up the code.

Warren County (with trips that originate and end in Warren):Total Trips: 57480Total Trip Miles: 701865

People call in 0 minutes before they arrive at station:

CD = 1

DD (minutes)

PTM /ATM Minimum Fleet Size

1 1.0863 190632 1.1259 138923 1.1585 106124 1.1840 87435 1.2064 7521

CD = 2

People call in 10 minutes before they arrive at station:

CD = 2

From the above simulations, we see the following relationships:

As CD increases, the minimum fleet size decreases. As DD increases, the minimum fleet size decreases. Similarly, as the number of minutes before the person arrives at the station that he/she calls increases, so does the minimum fleet size. It should also be noted that as DD and “calling-the-station” time before arriving at the station increase, the total empty vehicle miles travelled (empty vehicles travelling from a station less to in demand to a station more in demand) also increases.

Computer Graphics Simulation

My computer graphics simulation of the taxis in motion shows each station (taxi stand) as a green sphere, as seen below. There are some black spaces in some parts, but these are stations where either no trips are generated or, at least, this particular “closed” system trip file (without trips that go outside of Warren) does not have. However, overall, it is easily identifiable as the shape of Warren County.

DD (minutes)

PTM / ATM Minimum Fleet Size

1 1.1934 169172 1.2710 117473 1.3295 89254 1.3760 72195 1.4150 6161

DD (minutes)

PTM / ATM Minimum Fleet Size

1 1.1934 58692 1.2710 51053 1.3295 46804 1.3760 43555 1.4150 4163

The simulation runs through the entire DepartedTaxis.csv file and determines a fleet size at the end of the simulation. So as the viewer doesn’t have to sit there all day to view this, the simulation runs through the entire course of a whole day in 24 minutes. In other words, real time 1 hour corresponds to simulation time 1 minute.

The simulation graphics may also be shown without the stations (since they may sometimes obstruct the viewer’s view). As seen on the right image, all the dots represent an aTaxi in the fleet for Warren. The color of the taxi corresponds to how many taxi trips this taxi has completed. The darker the color, the more taxi trips that the taxi has completed.

Appendix A

Relevant Code (all in C++)RideShare.h:

#include <vector>using namespace std;

const int Y_RANGE = 350;const int X_RANGE = 250;

struct Route;

struct Stop {Stop(void);

int destinationY;int destinationX;int occupancy;int arrivalTime;

};

struct ATaxi {ATaxi(void);~ATaxi(void);

void mySort(vector<Route *> routes);int routeIndex;/*struct compareDistance{

int index;int destinations;bool operator () (const Route *first, const Route *second);

};*/

int originX;int originY;int departureTime;//int waitingATaxis;int miles;/*vector<int> destinationY;vector<int> destinationX;vector<int> occupancy;vector<int> arrivalTime;*/void mySort_Stops();vector<Stop *> stops;ATaxi *prev;ATaxi *next;int currentDestinations;int number;//vector<int> origin_distances;

/*****************************************************************/vector<vector<int>> map;vector<vector<ATaxi *>> neighbors;/*****************************************************************/

};

struct Trip {

Trip(int originY, int originX, int originTime, int destY, int destX, int manhattanMiles);

int originY;int originX;int originTime;int destY;int destX;int manhattanMiles;

};

struct Route {Route(int numberOfStops);

//int index;int numberOfStops;vector<int> distances;int circuityAllowed;vector<int> stops;

};

//void createATaxi(void);//void deleteATaxi(void);

struct RideShare {RideShare(int DepartureDelay, int CommonDestination, int PickUp);~RideShare(void);

void RideShareAnalysis(const char *filename);int CheckExistingTaxis_NoPickUp(Trip *trip);int CheckExistingTaxis_PickUp(Trip *trip);int CheckExistingTaxis_PickUp_Block(Trip *trip);void CreateTaxi(Trip *trip, int pickup);Trip *CreateTrip(int originY, int originX, int originTime, int destY, int destX,

int manhattanMiles);void mySort_NoPickUp(void);void mySort_PickUp(void);

ATaxi *first;ATaxi *last;

/*******************************************************************************************/

vector<vector<ATaxi *>> lists;void DeleteTaxi(ATaxi *a);vector<vector<ATaxi *>> last_in_list;void AddTaxi(ATaxi *taxi, int DY, int DX);int pickup;

/*******************************************************************************************/

int waitingTaxis;int DepartureDelay;int CommonDestination;FILE *DepartedTaxis;int totalDepartedTaxis;int totalTrips;int currentOriginY;int currentOriginX;vector<Trip *> trips;

vector<vector<Route *>> routes;int alreadyGenerated;int totalTaxiMiles;int totalTripMiles;int totalTaxisCreated;

};

RideShare.cpp:

#include <stdio.h>#include "RideShare.h"#include <algorithm>#include <stdlib.h>#include <time.h>

/*int main(int argc, const char* argv[]){

clock_t t;t = clock();

int DD;int CD;int PickUp;sscanf(argv[2],"%d",&PickUp);sscanf(argv[3],"%d",&DD);sscanf(argv[4],"%d",&CD);

RideShare *rs = new RideShare(DD,CD,PickUp); rs->RideShareAnalysis(argv[1]);

fprintf(stdout,"Total Trips: %d\n", rs->totalTrips);fprintf(stdout, "Total Departed Taxis: %d\n", rs->totalDepartedTaxis);fprintf(stdout,"Total Trip Miles: %d\n",rs->totalTripMiles);fprintf(stdout,"Total Taxi Miles: %d\n",rs->totalTaxiMiles);//int avo = rs->totalTripMiles/rs->totalTaxiMiles;//fprintf(stdout,"%4.2f\n",avo);

delete rs;

t = clock() - t;printf ("It took me %d clicks (%f seconds).\n",t,((float)t)/CLOCKS_PER_SEC);

}*/

RideShare::RideShare(int DD, int CD, int PickUp){

waitingTaxis = 0;DepartureDelay = DD*60;CommonDestination = CD;totalDepartedTaxis = 0;totalTrips = 0;first = NULL;last = NULL;currentOriginY = 0;currentOriginX = 0;totalTaxiMiles = 0;totalTripMiles = 0;totalTaxisCreated = 0;

/////////////////////////////////////////////////

//routes.resize(CD - 1);alreadyGenerated = 1;/////////////////////////////////////////////////

/*************************************************/lists.resize(Y_RANGE); // resize to range of the Y'slast_in_list.resize(Y_RANGE);for (int i = 0; i < Y_RANGE; i++){

lists[i].resize(X_RANGE);last_in_list[i].resize(X_RANGE);

}

for(int i = 0; i < Y_RANGE; i++){

for (int j = 0; j < X_RANGE; j++){

lists[i][j] = NULL;last_in_list[i][j] = NULL;

}}pickup = PickUp;/*************************************************/

// Open file DepartedTaxis = fopen("DepartedTaxis.csv", "w"); if (!DepartedTaxis) { fprintf(stderr, "Unable to open file %s\n", "DepartedTaxis.csv"); }}

RideShare::~RideShare(void){

// Delete taxis// already done in other functions

// delete tripsfor (int i = 0; i < totalTrips; i++){

Trip *trip = trips[i];//fprintf(stderr, "%d,%d,%d,%d,%d\n", trip->originY, trip->originX, trip-

>originTime, trip->destY, trip->destX); delete trip;}

// delete routesfor (unsigned int i = 0; i < routes.size(); i++){

for (unsigned int j = 0; j < routes[i].size(); j++){

Route *r = routes[i][j];delete r;

}}

}

bool SortByOriginY_NoPickUp(const Trip *first, const Trip *second){

if (first->originY < second->originY) {

return true; } return false;}

bool SortByOriginX_NoPickUp(const Trip *first, const Trip *second){ if (first->originY == second->originY) { if (first->originX < second->originX)

{ return true;

} return false; } return first->originY < second->originY;}

bool SortByOriginTime_NoPickUp(const Trip *first, const Trip *second){

if (first->originY == second->originY){

if (first->originX == second->originX){

if (first->originTime < second->originTime){

return true;}return false;

}return first->originX < second->originX;

}return first->originY < second->originY;

}

bool SortByDestY_NoPickUp(const Trip *first, const Trip *second){

if (first->originY == second->originY){

if (first->originX == second->originX){

if (first->originTime == second->originTime){

if (first->destY < second->destY){

return true;}return false;

}return first->originTime < second->originTime;

}return first->originX < second->originX;

}return first->originY < second->originY;

}

bool SortByDestX_NoPickUp(const Trip *first, const Trip *second){

if (first->originY == second->originY){

if (first->originX == second->originX){

if (first->originTime == second->originTime){

if (first->destY == second->destY){

if (first->destX < second->destX){

return true;}return false;

}return first->destY < second->destY;

}return first->originTime < second->originTime;

}return first->originX < second->originX;

}return first->originY < second->originY;

}

void RideShare::mySort_NoPickUp(void){

// first sort by OriginY sort(trips.begin(), trips.end(), SortByOriginY_NoPickUp);

// sort by originX given that the array has been sorted by originY sort(trips.begin(), trips.end(), SortByOriginX_NoPickUp);

// sort by originTime given that the array has been sorted by originY and originX sort(trips.begin(), trips.end(), SortByOriginTime_NoPickUp);

// sort by destY given that the array has been sorted by originY, originX, and originTime sort(trips.begin(), trips.end(), SortByDestY_NoPickUp);

// sort by destX given that the array has been sorted by originY, originX, originTime, and destY sort(trips.begin(), trips.end(), SortByDestX_NoPickUp);}

bool SortByOriginTime_PickUp(const Trip *first, const Trip *second){ if (first->originTime < second->originTime) {

return true; } return false;}

bool SortByOriginY_PickUp(const Trip *first, const Trip *second){ if (first->originTime == second->originTime) {

if (first->originY < second->originY) {

return true; }

return false; } return first->originTime < second->originTime;}

bool SortByOriginX_PickUp(const Trip *first, const Trip *second){

if (first->originTime == second->originTime){

if (first->originY == second->originY){

if (first->originX < second->originX){

return true;}return false;

}return first->originY < second->originY;

}return first->originTime < second->originTime;

}

bool SortByDestY_PickUp(const Trip *first, const Trip *second){

if (first->originTime == second->originTime){

if (first->originY == second->originY){

if (first->originX == second->originX){

if (first->destY < second->destY){

return true;}return false;

}return first->originX < second->originX;

}return first->originY < second->originY;

}return first->originTime < second->originTime;

}

bool SortByDestX_PickUp(const Trip *first, const Trip *second){

if (first->originTime == second->originTime){

if (first->originY == second->originY){

if (first->originX == second->originX){

if (first->destY == second->destY){

if (first->destX < second->destX){

return true;}return false;

}return first->destY < second->destY;

}return first->originX < second->originX;

}return first->originY < second->originY;

}return first->originTime < second->originTime;

}

void RideShare::mySort_PickUp(void){

// first sort by OriginY sort(trips.begin(), trips.end(), SortByOriginTime_PickUp);

// sort by originX given that the array has been sorted by originY sort(trips.begin(), trips.end(), SortByOriginY_PickUp);

// sort by originTime given that the array has been sorted by originY and originX sort(trips.begin(), trips.end(), SortByOriginX_PickUp);

// sort by destY given that the array has been sorted by originY, originX, and originTime sort(trips.begin(), trips.end(), SortByDestY_PickUp);

// sort by destX given that the array has been sorted by originY, originX, originTime, and destY sort(trips.begin(), trips.end(), SortByDestX_PickUp);}

void RideShare::RideShareAnalysis(const char *filename){

// Open file FILE *fp; if (!(fp = fopen(filename, "r"))) { fprintf(stderr, "Unable to open file %s\n", filename); }

char buffer[124];while (fgets(buffer, 123, fp)) //!= NULL{

totalTrips++;

char *bufferp = buffer;

int pointer;int homeCounty;int originCounty;int originY; //int originX; //int originTime; //int destCounty;int destY; //int destX; //int destTime; //

int manhattanMiles; //sscanf(bufferp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &pointer, &homeCounty,

&originCounty, &originY, &originX, &originTime, &destCounty, &destY, &destX, &destTime, &manhattanMiles);

totalTripMiles = totalTripMiles + manhattanMiles;CreateTrip(originY, originX, originTime, destY, destX, manhattanMiles);

}

// Close file fclose(fp);

// sort trips by OY, OX, OT, DY, DXif (pickup == 0) mySort_NoPickUp();if (pickup != 0) mySort_PickUp();

for (unsigned int i = 0; i < trips.size(); i++){

if (pickup == 1 && CheckExistingTaxis_PickUp(trips[i]) == 0){

CreateTaxi(trips[i], pickup);}if (pickup == 0 && CheckExistingTaxis_NoPickUp(trips[i]) == 0){

CreateTaxi(trips[i], pickup);}if (pickup == 2 && CheckExistingTaxis_PickUp_Block(trips[i]) == 0){

CreateTaxi(trips[i], pickup);}

}

if (pickup == 0){

while (first != NULL){

ATaxi *a = first;//fprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",first-

>originY, first->originX, first->departureTime, waitingTaxis, first->miles, first->destinationY[0], first->destinationX[0], first->occupancy[0], first->arrivalTime[0]);

//write to filefprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d",first->originY,

first->originX, first->departureTime, waitingTaxis, first->miles, first->stops[0]->destinationY, first->stops[0]->destinationX, first->stops[0]->occupancy, first->stops[0]->arrivalTime);

for (int i = 1; i < CommonDestination; i++){

fprintf(DepartedTaxis, ",%d,%d,%d,%d", first->stops[i]->destinationY, first->stops[i]->destinationX, first->stops[i]->occupancy, first->stops[i]->arrivalTime);

}fprintf(DepartedTaxis, "\n");

totalTaxiMiles = totalTaxiMiles + first->miles;first = first->next;waitingTaxis--;totalDepartedTaxis++;

delete a;

}}else{

for (int i = 0; i < Y_RANGE; i++){

for (int j = 0; j < X_RANGE; j++){

ATaxi *current = lists[i][j];while (current != NULL){

ATaxi *a = current;DeleteTaxi(a);for (unsigned int k = 0; k < current->map.size(); k++){

if (current->map[k][0] == i && current->map[k][1] == j)

{current = current->neighbors[k][1];break;

}}

delete a;}

}}

}

fclose(DepartedTaxis);}

Trip *RideShare::CreateTrip(int originY, int originX, int originTime, int destY, int destX, int manhattanMiles){

// Create trip Trip *trip = new Trip(originY, originX, originTime, destY, destX, manhattanMiles);

// Add to list trips.push_back(trip);

// Return trip return trip;}

bool SortByArrivalTime(const Stop *first, const Stop *second){

if (first->occupancy == 0){

return false;}

if (second->occupancy == 0){

return true;}

if (first->arrivalTime < second->arrivalTime) {

return true; } return false;}

void ATaxi::mySort_Stops(){

// sort stops by arrival timesort(stops.begin(), stops.end(), SortByArrivalTime);

}

void RideShare::DeleteTaxi(ATaxi *a){

// write taxi to filefprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d",a->originY, a->originX, a-

>departureTime, waitingTaxis, a->miles, a->stops[0]->destinationY, a->stops[0]->destinationX, a->stops[0]->occupancy, a->stops[0]->arrivalTime);

for (int i = 1; i < CommonDestination; i++){

fprintf(DepartedTaxis, ",%d,%d,%d,%d", a->stops[i]->destinationY, a->stops[i]->destinationX, a->stops[i]->occupancy, a->stops[i]->arrivalTime);

}fprintf(DepartedTaxis, "\n");

// delete taxi from list and memoryint leftn;int rightn;for (unsigned int i = 0; i < a->map.size(); i++){

// if prev is not NULL, have prev->next point toif (a->neighbors[i][0] != NULL){

for (unsigned int j = 0 ; j < a->neighbors[i][0]->map.size(); j++){

if (a->neighbors[i][0]->map[j][0] == a->map[i][0] && a->neighbors[i][0]->map[j][1] == a->map[i][1])

{leftn = j;break;

}}

}// if next is not NULLif (a->neighbors[i][1] != NULL){

for (unsigned int j = 0; j < a->neighbors[i][1]->map.size(); j++){

if (a->neighbors[i][1]->map[j][0] == a->map[i][0] && a->neighbors[i][1]->map[j][1] == a->map[i][1])

{rightn = j;break;

}}

}

if (a->neighbors[i][0] == NULL && a->neighbors[i][1] == NULL){

lists[a->map[i][0]][a->map[i][1]] = NULL;last_in_list[a->map[i][0]][a->map[i][1]] = NULL;

}else if (a->neighbors[i][0] == NULL && a->neighbors[i][1] != NULL){

a->neighbors[i][1]->neighbors[rightn][0] = NULL;lists[a->map[i][0]][a->map[i][1]] = a->neighbors[i][1];

}else if (a->neighbors[i][0] != NULL && a->neighbors[i][1] == NULL){

a->neighbors[i][0]->neighbors[leftn][1] = NULL;last_in_list[a->map[i][0]][a->map[i][1]] = a->neighbors[i][0];

}else{

//lists[a->map[i][0]][a->map[i][1]] = NULL;a->neighbors[i][0]->neighbors[leftn][1] = a->neighbors[i][1];a->neighbors[i][1]->neighbors[rightn][0] = a->neighbors[i][0];

}}

totalTaxiMiles = totalTaxiMiles + a->miles;waitingTaxis--;totalDepartedTaxis++;

}

int RideShare::CheckExistingTaxis_NoPickUp(Trip *trip){

if (currentOriginY == 0){

currentOriginY = trip->originY;currentOriginX = trip->originX;return 0;

}if (currentOriginY != trip->originY || currentOriginX != trip->originX){

while (first != NULL){

ATaxi *a = first;//fprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",first-

>originY, first->originX, first->departureTime, waitingTaxis, first->miles, first->destinationY[0], first->destinationX[0], first->occupancy[0], first->arrivalTime[0]);

//write to filefprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d",first->originY,

first->originX, first->departureTime, waitingTaxis, first->miles, first->stops[0]->destinationY, first->stops[0]->destinationX, first->stops[0]->occupancy, first->stops[0]->arrivalTime);

for (int i = 1; i < CommonDestination; i++){

fprintf(DepartedTaxis, ",%d,%d,%d,%d", first->stops[i]->destinationY, first->stops[i]->destinationX, first->stops[i]->occupancy, first->stops[i]->arrivalTime);

}fprintf(DepartedTaxis, "\n");

totalTaxiMiles = totalTaxiMiles + first->miles;first = first->next;

waitingTaxis--;totalDepartedTaxis++;delete a;

}if (waitingTaxis != 0){

fprintf(stderr,"Error %d,%d",trip->originY,trip->originX);}first = NULL;last = NULL;currentOriginY = trip->originY;currentOriginX = trip->originX;return 0;

}

ATaxi *current = first;while (current != NULL){

if (current->departureTime < trip->originTime){

//write to filefprintf(DepartedTaxis, "%d,%d,%d,%d,%d,%d,%d,%d,%d",first->originY,

first->originX, first->departureTime, waitingTaxis, first->miles, first->stops[0]->destinationY, first->stops[0]->destinationX, first->stops[0]->occupancy, first->stops[0]->arrivalTime);

for (int i = 1; i < CommonDestination; i++){

fprintf(DepartedTaxis, ",%d,%d,%d,%d", first->stops[i]->destinationY, first->stops[i]->destinationX, first->stops[i]->occupancy, first->stops[i]->arrivalTime);

}fprintf(DepartedTaxis, "\n");

totalTaxiMiles = totalTaxiMiles + current->miles;totalDepartedTaxis++;ATaxi *a = first;first = first->next;current = first;delete a;waitingTaxis--;

}else{

if (CommonDestination == 1){

if (current->stops[0]->destinationY == trip->destY && current->stops[0]->destinationX == trip->destX)

{current->stops[0]->occupancy++;return 1;

}current = current->next;

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

else{

for (int i = 0; i < current->currentDestinations; i++){

if (current->stops[i]->destinationY == trip->destY && current->stops[i]->destinationX == trip->destX)

{current->stops[i]->occupancy++;return 1;

}}

if (current->currentDestinations < CommonDestination){

if (current->currentDestinations == alreadyGenerated){

// generate numbers to be permuted (Cd = 2 is [1 2])

vector<int> permutations;for (int i = 0; i < current->currentDestinations +

1; i++){

permutations.push_back(i+1);}

// find all combinatorial routes (Cd = 2 is [1 2; 2 1])

vector<Route *> routes_i;//int totalRoutes = 0;do {

Route *route = new Route(current->currentDestinations + 1);

for (int j = 0; j < current->currentDestinations + 1; j++)

{route-

>stops.push_back(permutations[j]);}routes_i.push_back(route);//totalRoutes++;

} while (next_permutation(permutations.begin(), permutations.end()));

routes.push_back(routes_i);alreadyGenerated++;

}

int p = current->currentDestinations - 1; //+1 - 2

vector<int> origin_distances;for (int i = 0; i < current->currentDestinations; i++){

origin_distances.push_back(abs(current->originX - current->stops[i]->destinationX)+ abs(current->originY - current->stops[i]->destinationY));

}origin_distances.push_back(abs(current->originX - trip-

>destX) + abs(current->originY - trip->destY));

// find route distancesvector<Route *> possible_routes;int totalPossibleRoutes = 0;for (unsigned int i = 0; i < routes[p].size(); i++){

possible_routes.push_back(routes[p][i]);totalPossibleRoutes++;

// first column element, origin to first destination

int distance = 0;if (routes[p][i]->stops[0] != current-

>currentDestinations + 1){

distance = abs(current->originX - current->stops[routes[p][i]->stops[0] - 1]->destinationX) + abs(current->originY - current->stops[routes[p][i]->stops[0] - 1]->destinationY);

}else{

distance = abs(current->originX - trip->destX) + abs(current->originY - trip->destY);

}for (int j = 0; j < routes[p][i]->numberOfStops; j+

+){

routes[p][i]->distances[j] = distance;}

for (int j = 0; j < current->currentDestinations; j++)

{if ((routes[p][i]->stops[j+1] != current-

>currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(current->stops[routes[p]

[i]->stops[j+1] - 1]->destinationX - current->stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}else if ((routes[p][i]->stops[j+1] ==

current->currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(trip->destX - current-

>stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(trip->destY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}//else if ((routes[i][j+1] != current-

>currentDestinations + 1) && (routes[i][j] == current->currentDestinations + 1))else{

distance = abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationX - trip->destX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - trip->destY);

}for (int k = routes[p][i]->distances.size() -

1; k > j; k--){

routes[p][i]->distances[k] = routes[p][i]->distances[k] + distance;

}

if (routes[p][i]->distances[j + 1] > 1.2*origin_distances[routes[p][i]->stops[j + 1] - 1])

{routes[p][i]->circuityAllowed = 0;

totalPossibleRoutes--;possible_routes.pop_back();break;

}}

if (totalPossibleRoutes == 1){

for (int j = current->currentDestinations; j > 0; j--)

{if (possible_routes[0]->distances[j] >

1.2*origin_distances[possible_routes[0]->stops[j] - 1]){

possible_routes[0]->circuityAllowed = 0;

fprintf(stderr, "error\n");break;

}}

current->stops[current->currentDestinations]->destinationY = trip->destY;

current->stops[current->currentDestinations]->destinationX = trip->destX;

current->stops[current->currentDestinations]->occupancy = 1;

current->miles = possible_routes[0]->distances.back(); // last element of vector

current->stops[possible_routes[0]->stops[0] - 1]->arrivalTime = current->departureTime + 60*possible_routes[0]->distances[0];

for (int j = 1; j < current->currentDestinations + 1; j++)

{current->stops[possible_routes[0]-

>stops[j] - 1]->arrivalTime = current->stops[possible_routes[0]->stops[j-1] - 1]->arrivalTime + 60*(abs(current->stops[possible_routes[0]->stops[j] - 1]->destinationX - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationX) + abs(current->stops[possible_routes[0]->stops[j] - 1]->destinationY - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationY)) + 60;

}current->currentDestinations++;possible_routes.clear();return 1;

}if (totalPossibleRoutes > 1){

fprintf(stderr,"errorb\n");}

}

// sort the distances/*DistanceSort(r, current);*/

/*vector<int> origin_distances;for (int i = 0; i < current->currentDestinations; i++){

origin_distances.push_back(abs(current->originX - current->destinationX[i])+ abs(current->originY - current->destinationY[i]));

}origin_distances.push_back(abs(current->originX - trip-

>destX) + abs(current->originY - trip->destY));*/

// determine circuity/*for (int i = 0; i < totalPossibleRoutes; i++){

possible_routes[i]->circuityAllowed = 1;for (int j = current->currentDestinations; j > 0;

j--){

if (possible_routes[i]->distances[j] > 1.2*origin_distances[possible_routes[i]->stops[j] - 1])

{possible_routes[i]->circuityAllowed =

0;break;

}}

if (possible_routes[i]->circuityAllowed == 1){

// create new stop for taxicurrent->destinationY[current-

>currentDestinations] = trip->destY;current->destinationX[current-

>currentDestinations] = trip->destX;current->occupancy[current-

>currentDestinations] = 1;current->miles = possible_routes[i]-

>distances.back(); // last element of vectorcurrent->arrivalTime[possible_routes[i]-

>stops[0] - 1] = current->departureTime + 60*possible_routes[i]->distances[0];for (int j = 1; j < current-

>currentDestinations + 1; j++){

current->arrivalTime[possible_routes[i]->stops[j] - 1] = current->arrivalTime[possible_routes[i]->stops[j-1] - 1] + 60*(abs(current->destinationX[possible_routes[i]->stops[j] - 1] - current->destinationX[possible_routes[i]->stops[j-1] - 1]) + abs(current->destinationY[possible_routes[i]->stops[j] - 1] - current->destinationY[possible_routes[i]->stops[j-1] - 1])) + 60;

}current->currentDestinations++;return 1;

}}*///fprintf(stderr,"%d\n",totalPossibleRoutes);// create new stop for taxi/*if (totalPossibleRoutes >= 1){

fprintf(stderr, "errora\n");for (int j = current->currentDestinations; j > 0;

j--){

if (possible_routes[0]->distances[j] > 1.2*origin_distances[possible_routes[0]->stops[j] - 1])

{possible_routes[0]->circuityAllowed =

0;fprintf(stderr, "error\n");break;

}}

current->destinationY[current->currentDestinations] = trip->destY;

current->destinationX[current->currentDestinations] = trip->destX;

current->occupancy[current->currentDestinations] = 1;

current->miles = possible_routes[0]->distances.back(); // last element of vector

current->arrivalTime[possible_routes[0]->stops[0] - 1] = current->departureTime + 60*possible_routes[0]->distances[0];

for (int j = 1; j < current->currentDestinations + 1; j++)

{current->arrivalTime[possible_routes[0]-

>stops[j] - 1] = current->arrivalTime[possible_routes[0]->stops[j-1] - 1] + 60*(abs(current->destinationX[possible_routes[0]->stops[j] - 1] - current->destinationX[possible_routes[0]->stops[j-1] - 1]) + abs(current->destinationY[possible_routes[0]->stops[j] - 1] - current->destinationY[possible_routes[0]->stops[j-1] - 1])) + 60;

}current->currentDestinations++;possible_routes.clear();return 1;

}*/possible_routes.clear();

}current = current->next;

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}}

return 0;}

int RideShare::CheckExistingTaxis_PickUp(Trip *trip){

/***********************************************************************************************************************/

ATaxi *current = lists[trip->originY][trip->originX];if (current!= NULL) int help = lists[trip->originY][trip->originX]->miles;while (current != NULL){

// delete some taxis from the linked systemif ((current->stops[current->currentDestinations - 1]->arrivalTime +

DepartureDelay <= trip->originTime) || (current->currentDestinations - 2 >= 0 && current->stops[current->currentDestinations - 2]->arrivalTime + DepartureDelay <= trip->originTime))

{ATaxi *a = current;DeleteTaxi(a);for (unsigned int i = 0; i < current->map.size(); i++){

if (current->map[i][0] == trip->originY && current->map[i][1] == trip->originX)

{current = current->neighbors[i][1];

break;}

}

delete a;}else{

// same originif (trip->originY == current->originY && trip->originX == current-

>originX){

if (current->departureTime >= trip->originTime){

for (int i = 0; i < current->currentDestinations; i++){

if (current->stops[i]->destinationY == trip->destY && current->stops[i]->destinationX == trip->destX)

{current->stops[i]->occupancy++;return 1;

}}

if (current->currentDestinations < CommonDestination){

vector<int> permutations;if (current->currentDestinations ==

alreadyGenerated){

// generate numbers to be permuted (Cd = 2 is [1 2])

for (int i = 0; i < current->currentDestinations + 1; i++)

{permutations.push_back(i+1);

}

// find all combinatorial routes (Cd = 2 is [1 2; 2 1])

vector<Route *> routes_i;//int totalRoutes = 0;do {

Route *route = new Route(current->currentDestinations + 1);

for (int j = 0; j < current->currentDestinations + 1; j++)

{route-

>stops.push_back(permutations[j]);}routes_i.push_back(route);//totalRoutes++;

} while (next_permutation(permutations.begin(), permutations.end()));

routes.push_back(routes_i);alreadyGenerated++;

}

int p = current->currentDestinations - 1; //+1 - 2

vector<int> origin_distances;for (int i = 0; i < current->currentDestinations;

i++){

origin_distances.push_back(abs(current->originX - current->stops[i]->destinationX)+ abs(current->originY - current->stops[i]->destinationY));

}origin_distances.push_back(abs(current->originX -

trip->destX) + abs(current->originY - trip->destY));

// find route distancesvector<Route *> possible_routes;int totalPossibleRoutes = 0;for (unsigned int i = 0; i < routes[p].size(); i++){

possible_routes.push_back(routes[p][i]);totalPossibleRoutes++;

// first column element, origin to first destination

int distance = 0;if (routes[p][i]->stops[0] != current-

>currentDestinations + 1){

distance = abs(current->originX - current->stops[routes[p][i]->stops[0] - 1]->destinationX) + abs(current->originY - current->stops[routes[p][i]->stops[0] - 1]->destinationY);

}else{

distance = abs(current->originX - trip->destX) + abs(current->originY - trip->destY);

}for (int j = 0; j < routes[p][i]-

>numberOfStops; j++){

routes[p][i]->distances[j] = distance;}

for (int j = 0; j < current->currentDestinations; j++)

{if ((routes[p][i]->stops[j+1] !=

current->currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(current-

>stops[routes[p][i]->stops[j+1] - 1]->destinationX - current->stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}else if ((routes[p][i]->stops[j+1] ==

current->currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(trip->destX -

current->stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(trip->destY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}//else if ((routes[i][j+1] != current-

>currentDestinations + 1) && (routes[i][j] == current->currentDestinations + 1))

else{

distance = abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationX - trip->destX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - trip->destY);

}for (int k = routes[p][i]-

>distances.size() - 1; k > j; k--){

routes[p][i]->distances[k] = routes[p][i]->distances[k] + distance;

}

if (routes[p][i]->distances[j + 1] > 1.2*origin_distances[routes[p][i]->stops[j + 1] - 1])

{routes[p][i]->circuityAllowed =

0;totalPossibleRoutes--;possible_routes.pop_back();break;

}}

if (totalPossibleRoutes == 1){

for (int j = current->currentDestinations; j > 0; j--)

{if (possible_routes[0]-

>distances[j] > 1.2*origin_distances[possible_routes[0]->stops[j] - 1]){

possible_routes[0]->circuityAllowed = 0;

fprintf(stderr, "error_a\n");

break;}

}

current->stops[current->currentDestinations]->destinationY = trip->destY;

current->stops[current->currentDestinations]->destinationX = trip->destX;

current->stops[current->currentDestinations]->occupancy = 1;

current->miles = possible_routes[0]->distances.back(); // last element of vector

current->stops[possible_routes[0]->stops[0] - 1]->arrivalTime = current->departureTime + 60*possible_routes[0]->distances[0];

for (int j = 1; j < current->currentDestinations + 1; j++)

{current-

>stops[possible_routes[0]->stops[j] - 1]->arrivalTime = current->stops[possible_routes[0]->stops[j-1] - 1]->arrivalTime + 60*(abs(current->stops[possible_routes[0]->stops[j] - 1]->destinationX - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationX) + abs(current->stops[possible_routes[0]->stops[j] - 1]->destinationY - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationY)) + DepartureDelay;

}

// sort by arrivalTimecurrent->mySort_Stops();

// enter next to last destination into list

//int Y = trip->destY;//int X = trip->destX;AddTaxi(current, trip->destY, trip-

>destX);/*if (lists[Y][X] == NULL){

lists[Y][X] = current;vector<int> maps;

maps.push_back(Y); maps.push_back(X);vector<ATaxi *> taxis;

taxis.push_back(NULL); taxis.push_back(NULL);current->map.push_back(maps);current-

>neighbors.push_back(taxis);}else{

for (unsigned int k = 0; k < lists[Y][X]->map.size(); k++)

{if (lists[Y][X]->map[k][0]

== Y && lists[Y][X]->map[k][1] == X){

vector<int> maps; maps.push_back(Y); maps.push_back(X);

vector<ATaxi *> taxis; taxis.push_back(NULL); taxis.push_back(lists[Y][X]);

current->map.push_back(maps);

current->neighbors.push_back(taxis);

lists[Y][X]->neighbors[k][0] = current;

lists[Y][X] = current;

break;}

}}*/

current->currentDestinations++;possible_routes.clear();return 1;

}if (totalPossibleRoutes > 1){

fprintf(stderr,"error_b\n");}

}possible_routes.clear();

}}

}// different originelse{

for (int i = 0; i < current->currentDestinations; i++){

if (current->stops[i]->destinationY == trip->originY && current->stops[i]->destinationX == trip->originX)

{for (int j = i + 1; j < current-

>currentDestinations; j++){

if (current->stops[j]->destinationY == trip->destY && current->stops[j]->destinationX == trip->destX)

{if (current->stops[i]->arrivalTime +

DepartureDelay >= trip->originTime && trip->originTime >= current->stops[i]->arrivalTime - DepartureDelay)

{current->stops[j]->occupancy++;return 1;

}}

}}

}}

// current = current->nextfor (unsigned int i = 0; i < current->map.size(); i++){

if (current->map[i][0] == trip->originY && current->map[i][1] == trip->originX)

{current = current->neighbors[i][1];break;

}}

}}return 0;

}

int RideShare::CheckExistingTaxis_PickUp_Block(Trip *trip){

/***********************************************************************************************************************/

ATaxi *current = lists[trip->originY][trip->originX];if (current!= NULL) int help = lists[trip->originY][trip->originX]->miles;while (current != NULL){

// delete some taxis from the linked systemif ((current->stops[current->currentDestinations - 1]->arrivalTime +

DepartureDelay <= trip->originTime) || (current->currentDestinations - 2 >= 0 && current->stops[current->currentDestinations - 2]->arrivalTime + DepartureDelay <= trip->originTime))

{ATaxi *a = current;DeleteTaxi(a);for (unsigned int i = 0; i < current->map.size(); i++){

if (current->map[i][0] == trip->originY && current->map[i][1] == trip->originX)

{current = current->neighbors[i][1];break;

}}

delete a;}else{

// same originif (trip->originY == current->originY && trip->originX == current-

>originX){

if (current->departureTime >= trip->originTime){

for (int i = 0; i < current->currentDestinations; i++){

if (current->stops[i]->destinationY == trip->destY && current->stops[i]->destinationX == trip->destX)

{current->stops[i]->occupancy++;return 1;

}}

if (current->currentDestinations < CommonDestination){

vector<int> permutations;if (current->currentDestinations ==

alreadyGenerated){

// generate numbers to be permuted (Cd = 2 is [1 2])

for (int i = 0; i < current->currentDestinations + 1; i++)

{permutations.push_back(i+1);

}

// find all combinatorial routes (Cd = 2 is [1 2; 2 1])

vector<Route *> routes_i;//int totalRoutes = 0;do {

Route *route = new Route(current->currentDestinations + 1);

for (int j = 0; j < current->currentDestinations + 1; j++)

{route-

>stops.push_back(permutations[j]);}routes_i.push_back(route);//totalRoutes++;

} while (next_permutation(permutations.begin(), permutations.end()));

routes.push_back(routes_i);alreadyGenerated++;

}

int p = current->currentDestinations - 1; //+1 - 2

vector<int> origin_distances;for (int i = 0; i < current->currentDestinations;

i++){

origin_distances.push_back(abs(current->originX - current->stops[i]->destinationX)+ abs(current->originY - current->stops[i]->destinationY));

}origin_distances.push_back(abs(current->originX -

trip->destX) + abs(current->originY - trip->destY));

// find route distancesvector<Route *> possible_routes;int totalPossibleRoutes = 0;for (unsigned int i = 0; i < routes[p].size(); i++){

possible_routes.push_back(routes[p][i]);totalPossibleRoutes++;

// first column element, origin to first destination

int distance = 0;if (routes[p][i]->stops[0] != current-

>currentDestinations + 1){

distance = abs(current->originX - current->stops[routes[p][i]->stops[0] - 1]->destinationX) + abs(current->originY - current->stops[routes[p][i]->stops[0] - 1]->destinationY);

}else{

distance = abs(current->originX - trip->destX) + abs(current->originY - trip->destY);

}for (int j = 0; j < routes[p][i]-

>numberOfStops; j++){

routes[p][i]->distances[j] = distance;}

for (int j = 0; j < current->currentDestinations; j++)

{if ((routes[p][i]->stops[j+1] !=

current->currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(current-

>stops[routes[p][i]->stops[j+1] - 1]->destinationX - current->stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}else if ((routes[p][i]->stops[j+1] ==

current->currentDestinations + 1) && (routes[p][i]->stops[j] != current->currentDestinations + 1))

{distance = abs(trip->destX -

current->stops[routes[p][i]->stops[j] - 1]->destinationX) + abs(trip->destY - current->stops[routes[p][i]->stops[j] - 1]->destinationY);

}

//else if ((routes[i][j+1] != current->currentDestinations + 1) && (routes[i][j] == current->currentDestinations + 1))

else{

distance = abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationX - trip->destX) + abs(current->stops[routes[p][i]->stops[j+1] - 1]->destinationY - trip->destY);

}for (int k = routes[p][i]-

>distances.size() - 1; k > j; k--){

routes[p][i]->distances[k] = routes[p][i]->distances[k] + distance;

}

if (routes[p][i]->distances[j + 1] > 1.2*origin_distances[routes[p][i]->stops[j + 1] - 1])

{routes[p][i]->circuityAllowed =

0;totalPossibleRoutes--;possible_routes.pop_back();break;

}}

if (totalPossibleRoutes == 1){

for (int j = current->currentDestinations; j > 0; j--)

{if (possible_routes[0]-

>distances[j] > 1.2*origin_distances[possible_routes[0]->stops[j] - 1]){

possible_routes[0]->circuityAllowed = 0;

fprintf(stderr, "error_a\n");

break;}

}

current->stops[current->currentDestinations]->destinationY = trip->destY;

current->stops[current->currentDestinations]->destinationX = trip->destX;

current->stops[current->currentDestinations]->occupancy = 1;

current->miles = possible_routes[0]->distances.back(); // last element of vector

current->stops[possible_routes[0]->stops[0] - 1]->arrivalTime = current->departureTime + 60*possible_routes[0]->distances[0];

for (int j = 1; j < current->currentDestinations + 1; j++)

{current-

>stops[possible_routes[0]->stops[j] - 1]->arrivalTime = current->stops[possible_routes[0]->stops[j-1] - 1]->arrivalTime + 60*(abs(current->stops[possible_routes[0]->stops[j] - 1]->destinationX - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationX) + abs(current-

>stops[possible_routes[0]->stops[j] - 1]->destinationY - current->stops[possible_routes[0]->stops[j-1] - 1]->destinationY)) + DepartureDelay;

}

// sort by arrivalTimecurrent->mySort_Stops();

// enter next to last destination into list

//int Y = trip->destY;//int X = trip->destX;AddTaxi(current, trip->destY, trip-

>destX);/*if (lists[Y][X] == NULL){

lists[Y][X] = current;vector<int> maps;

maps.push_back(Y); maps.push_back(X);vector<ATaxi *> taxis;

taxis.push_back(NULL); taxis.push_back(NULL);current->map.push_back(maps);current-

>neighbors.push_back(taxis);}else{

for (unsigned int k = 0; k < lists[Y][X]->map.size(); k++)

{if (lists[Y][X]->map[k][0]

== Y && lists[Y][X]->map[k][1] == X){

vector<int> maps; maps.push_back(Y); maps.push_back(X);

vector<ATaxi *> taxis; taxis.push_back(NULL); taxis.push_back(lists[Y][X]);

current->map.push_back(maps);

current->neighbors.push_back(taxis);

lists[Y][X]->neighbors[k][0] = current;

lists[Y][X] = current;

break;}

}}*/

current->currentDestinations++;possible_routes.clear();return 1;

}if (totalPossibleRoutes > 1){

fprintf(stderr,"error_b\n");}

}possible_routes.clear();

}}

}

// different originelse{

for (int i = 0; i < current->currentDestinations; i++){

if (current->stops[i]->destinationY == trip->originY && current->stops[i]->destinationX == trip->originX)

{for (int j = i + 1; j < current-

>currentDestinations; j++){

if (current->stops[j]->destinationY == trip->destY && current->stops[j]->destinationX == trip->destX)

{if (current->stops[i]->arrivalTime +

DepartureDelay >= trip->originTime && trip->originTime >= current->stops[i]->arrivalTime - DepartureDelay)

{current->stops[j]->occupancy++;return 1;

}}

}}

}}

// current = current->nextfor (unsigned int i = 0; i < current->map.size(); i++){

if (current->map[i][0] == trip->originY && current->map[i][1] == trip->originX)

{current = current->neighbors[i][1];break;

}}

}}return 0;

}

void RideShare::AddTaxi(ATaxi *taxi, int Y, int X){

if (lists[Y][X] == NULL){

//if empty 2d listlists[Y][X] = taxi;last_in_list[Y][X] = taxi;

vector<int> maps; maps.push_back(Y); maps.push_back(X);vector<ATaxi *> taxis; taxis.push_back(NULL); taxis.push_back(NULL);taxi->map.push_back(maps);taxi->neighbors.push_back(taxis);

}else{

// add to front of 2d list/*for (unsigned int i = 0; i < lists[trip->destY][trip->destX]->map.size();

i++)

{if ((lists[trip->destY][trip->destX]->map[i][0] == trip->destY) &&

(lists[trip->destY][trip->destX]->map[i][1] == trip->destX)){

lists[trip->destY][trip->destX]->neighbors[i][0] = taxi;vector<int> maps; maps.push_back(trip->destY);

maps.push_back(trip->destX);taxi->map.push_back(maps);vector<ATaxi *> taxis; taxis.push_back(NULL);

taxis.push_back(lists[trip->destY][trip->destX]);taxi->neighbors.push_back(taxis);break;

}}lists[trip->destY][trip->destX] = taxi;*/

// add to end of 2d listfor (unsigned int i = 0; i < last_in_list[Y][X]->map.size(); i++){

if ((last_in_list[Y][X]->map[i][0] == Y) && (last_in_list[Y][X]->map[i][1] == X))

{last_in_list[Y][X]->neighbors[i][1] = taxi;vector<int> maps; maps.push_back(Y); maps.push_back(X);taxi->map.push_back(maps);vector<ATaxi *> taxis; taxis.push_back(last_in_list[Y][X]);

taxis.push_back(NULL);taxi->neighbors.push_back(taxis);break;

}}last_in_list[Y][X] = taxi;

}}

void RideShare::CreateTaxi(Trip *trip, int pickup){

ATaxi *taxi = new ATaxi();

taxi->originY = trip->originY;taxi->originX = trip->originX;taxi->departureTime = trip->originTime + DepartureDelay;

// no pick upif (pickup == 0){

if (waitingTaxis == 0) //empty queue{

first = taxi;last = taxi;

}else{

last->next = taxi;taxi->prev = last;last = taxi;

}}else{

AddTaxi(taxi, trip->originY, trip->originX);AddTaxi(taxi, trip->destY, trip->destX);

}

waitingTaxis = waitingTaxis + 1;taxi->miles = trip->manhattanMiles;taxi->stops.resize(CommonDestination);for (int i = 0; i < CommonDestination; i++){

taxi->stops[i] = new Stop();}/*taxi->destinationY.resize(CommonDestination);taxi->destinationX.resize(CommonDestination);taxi->occupancy.resize(CommonDestination);taxi->arrivalTime.resize(CommonDestination);*/taxi->stops[0]->destinationY = trip->destY;taxi->stops[0]->destinationX = trip->destX;taxi->stops[0]->occupancy = 1;taxi->stops[0]->arrivalTime = taxi->departureTime + 60*trip-

>manhattanMiles;//0.5/30*3600taxi->currentDestinations = 1;totalTaxisCreated++;taxi->number = totalTaxisCreated;//taxi->origin_distances.push_back(abs(trip->originY - trip->destY) + abs(trip-

>originX - trip->destX));}

ATaxi::ATaxi(void){

miles = 0;prev = NULL;next = NULL;currentDestinations = 0;

}

ATaxi::~ATaxi(void){

for (unsigned int i = 0; i < stops.size(); i++){

Stop *s = stops[i]; delete s;}stops.clear();

}

Trip::Trip(int originY, int originX, int originTime, int destY, int destX, int manhattanMiles){

Trip::originY = originY;Trip::originX = originX;Trip::originTime = originTime;Trip::destY = destY;

Trip::destX = destX;Trip::manhattanMiles = manhattanMiles;

}

Route::Route(int numberOfStops){

Route::numberOfStops = numberOfStops;Route::distances.resize(numberOfStops);Route::circuityAllowed = 1;

}

Stop::Stop(void){

destinationY = 0;destinationX = 0;occupancy = 0;arrivalTime = 0;

}

Fleet.h:

#include <vector>using namespace std;

const int Y_STATION_RANGE = 350;const int X_STATION_RANGE = 250;

struct TaxiTrip{

TaxiTrip();

int originY;int originX;int DepartureTime;vector<int> finalDestY;vector<int> finalDestX;vector<int> finalArrivalTime;double realStartTime;int completed;int pathcompleted;double distanceLeft;

};

struct Taxi{

Taxi(void);~Taxi(void);

int tripsCompleted;TaxiTrip *trip;Taxi *prev;Taxi *next;int timeEmpty;int particleIndex;int waiting;

};

struct Fleet{

Fleet(int CD, int DD, int call);

~Fleet(void);

void FleetAnalysis_Read(void);void FleetAnalysis_Analyze(void);//void CreateTaxiTrip(int originY, int originX, int DepartureTime, vector<int>

*destY, vector<int> *destX, vector<int> *ArrivalTime);Taxi *CheckExistingFleet(TaxiTrip *trip);Taxi *CreateNewTaxi(TaxiTrip *trip);void mySort(void);int FleetSize(void);int TotalTaxiTrips(void);int x_range(void);int y_range(void);

/*************************************************/vector<vector<Taxi *>> station_first;vector<vector<Taxi *>> station_last;vector<vector<int>> stations;/*************************************************/

int totalFleet;vector<TaxiTrip *> trips;int CD;int DD;int call;int totalTripsCompleted;int emptyVehicleDistance;//int waitingThreshold;

};

Fleet.cpp:

#include <stdio.h>#include "Fleet.h"#include <algorithm>#include <stdlib.h>#include <time.h>

Fleet::Fleet(int CD, int DD, int call){

this->CD = CD;this->DD = DD*60;this->call = call*60;//this->waitingThreshold = waitingThreshold*60;totalTripsCompleted = 0;totalFleet = 0;//fleet_first = NULL;//fleet_last = NULL;

station_first.resize(Y_STATION_RANGE);station_last.resize(Y_STATION_RANGE);stations.resize(Y_STATION_RANGE);for (int i = 0; i < Y_STATION_RANGE; i++){

station_first[i].resize(X_STATION_RANGE);station_last[i].resize(X_STATION_RANGE);stations[i].resize(X_STATION_RANGE);

}

for (int i = 0; i < Y_STATION_RANGE; i++)

{for (int j = 0; j < X_STATION_RANGE; j++){

station_first[i][j] = NULL;station_last[i][j] = NULL;stations[i][j] = 0;

}}

emptyVehicleDistance = 0;}

Fleet::~Fleet(void){

for (int i = 0; i < trips.size(); i++){

TaxiTrip *t = trips[i];delete t;

}

for(int i = 0; i < Y_STATION_RANGE; i++){

for (int j = 0; j < X_STATION_RANGE; j++){

while (station_first[i][j] != NULL){

Taxi *t = station_first[i][j];station_first[i][j] = station_first[i][j]->next;delete t;

}}

}}

bool SortByDepartureTime(const TaxiTrip *first, const TaxiTrip *second){ if (first->DepartureTime < second->DepartureTime) {

return true; } return false;}

/*bool SortByFinalArrivalTime(const TaxiTrip *first, const TaxiTrip *second){

if (first->DepartureTime == second->DepartureTime){

if (first->finalArrivalTime < second->finalArrivalTime){

return true;}return false;

}return first->DepartureTime < second->DepartureTime;

}*/

void Fleet::mySort(void){

// sort taxi trips by departure time sort(trips.begin(), trips.end(), SortByDepartureTime);

// sort taxi trips by final arrival time //sort(trips.begin(), trips.end(), SortByFinalArrivalTime);}

void Fleet:: FleetAnalysis_Read(void){

// Open file FILE *fp; if (!(fp = fopen("DepartedTaxis.csv", "r"))) { fprintf(stderr, "Unable to open file %s\n", "DepartedTaxis.csv"); }

char buffer[124];while (fgets(buffer, 123, fp)) //!= NULL{

char *bufferp = buffer;

// O_YOX DepartureTIme waitingTaxis miles destY1destX1occ1arrivaltime1 desty2destx2occ2 arrivaltime2

int originY;int originX;int DepartureTime;int waitingTaxis;int miles; // actually need to divide by 2 to get miles, keep integer for

nowvector<int> destY;vector<int> destX;vector<int> occupancy;vector<int> arrivalTime;destY.resize(CD);destX.resize(CD);occupancy.resize(CD);arrivalTime.resize(CD);//sscanf(bufferp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &pointer, &homeCounty,

&originCounty, &originY, &originX, &originTime, &destCounty, &destY, &destX, &destTime, &manhattanMiles);

if (CD == 1){

sscanf(bufferp, "%d,%d,%d,%d,%d,%d,%d,%d,%d", &originY, &originX, &DepartureTime, &waitingTaxis, &miles, &destY[0], &destX[0], &occupancy[0], &arrivalTime[0]);

}else{

char rest[124];sscanf(bufferp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%s", &originY, &originX,

&DepartureTime, &waitingTaxis, &miles, &destY[0], &destX[0], &occupancy[0], &arrivalTime[0], rest);

for (int i = 1; i < CD; i++){

if (i != CD - 1){

sscanf(rest, "%d,%d,%d,%d,%s", &destY[i], &destX[i], &occupancy[i], &arrivalTime[i], rest);

}else{

sscanf(rest, "%d,%d,%d,%d", &destY[i], &destX[i], &occupancy[i], &arrivalTime[i]);

}}

}

/*fprintf(stderr,"%d,%d,%d,%d,%d,%d,%d,%d,%d", originY, originX, DepartureTime, waitingTaxis, miles, destY[0], destX[0], occupancy[0], arrivalTime[0]);

for (int i = 1; i < CD; i++){

fprintf(stderr,",%d,%d,%d,%d", destY[i], destX[i], occupancy[i], arrivalTime[i]);

}fprintf(stderr,"\n");*//**************************only origin and final destination stations are

created*/stations[originY][originX] = 1;

TaxiTrip *t = new TaxiTrip();t->completed = 0;t->pathcompleted = 0;t->originY = originY;t->originX = originX;t->DepartureTime = DepartureTime;

//vector<int> finalDestinationY;//vector<int> finalDestinationX;//vector<int> arrival;for (int i = 0; i < CD; i++){

if (destY[i] != 0){

t->finalDestY.push_back(destY[i]);t->finalDestX.push_back(destX[i]);t->finalArrivalTime.push_back(arrivalTime[i]);stations[destY[i]][destX[i]] = 1;

}}trips.push_back(t);//stations[finalDestinationY][finalDestinationX] = 1;

//CreateTaxiTrip(originY, originX, DepartureTime, finalDestinationY, finalDestinationX, arrival);

/*if (finalDestinationY == 0 || finalDestinationX == 0 || arrival == 0){

fprintf(stderr, "%s\n", "destination error");}*/

}

// Close file fclose(fp);

mySort();

}

void Fleet:: FleetAnalysis_Analyze(void){

for(int i = 0; i < trips.size(); i++){

if (CheckExistingFleet(trips[i]) == NULL){

CreateNewTaxi(trips[i]);}

}}

Taxi* Fleet::CheckExistingFleet(TaxiTrip *trip){

int y = trip->originY;int x = trip->originX;

Taxi *current = station_first[y][x];while (current != NULL){

// But finalArrivalTime could be well before trip->DepartureTime??????????????????????????????????????????????????????????????

if (current->trip->finalArrivalTime[current->trip->finalArrivalTime.size() - 1] <= trip->DepartureTime)

{current->tripsCompleted++;current->trip = trip;current->timeEmpty = current->timeEmpty - (trip-

>finalArrivalTime[trip->finalArrivalTime.size() - 1] - trip->DepartureTime);

// delete from current stationif (current->prev == NULL && current->next == NULL){

station_first[y][x] = NULL;station_last[y][x] = NULL;

}else if (current->prev != NULL && current->next == NULL){

current->prev->next = NULL;station_last[y][x] = current->prev;

}else if (current->prev == NULL && current->next != NULL){

current->next->prev = NULL;station_first[y][x] = current->next;

}else{

current->prev->next = current->next;current->next->prev = current->prev;

}

// add to relevant stationint yf = trip->finalDestY[trip->finalDestY.size() - 1];int xf = trip->finalDestX[trip->finalDestX.size() - 1];if (station_first[yf][xf] == NULL){

station_first[yf][xf] = current;station_last[yf][xf] = current;current->prev = NULL;current->next = NULL;

}else{

station_last[yf][xf]->next = current;current->prev = station_last[yf][xf];station_last[yf][xf] = current;

current->next = NULL;}

totalTripsCompleted++;

return current;}current = current->next;

}

// check for other stationsif (DD > 0){

int maxTime = DD + call;int maxDistance = ceil(maxTime/60.0);int minX = 1; int minY = 1; int maxX = X_STATION_RANGE; int maxY =

Y_STATION_RANGE;int minX_poss = trip->originX - maxDistance;int maxX_poss = trip->originX + maxDistance;int minY_poss = trip->originY - maxDistance;int maxY_poss = trip->originY + maxDistance;if (minY_poss > 1){

minY = minY_poss;}if (minX_poss > 1){

minX = minX_poss;}if (maxY_poss < Y_STATION_RANGE){

maxY = maxY_poss;}if (maxX_poss < X_STATION_RANGE){

maxX = maxX_poss;}

for (int i = minY; i < maxY; i++){

for (int j = minX; j < maxX; j++){

y = i;x = j;

int distance = abs(y - trip->originY) + abs(x - trip->originX);int timeNeeded = distance*60 + 60;

if (timeNeeded <= maxTime){

Taxi *current = station_first[y][x];while (current != NULL){

// But finalArrivalTime could be well before trip->DepartureTime??????????????????????????????????????????????????????????????

if (current->trip->finalArrivalTime[current->trip->finalArrivalTime.size() - 1] <= trip->DepartureTime)

{//int distance = abs(current->trip-

>finalDestY - trip->originY) + abs(current->trip->finalDestX - trip->originX);//int timeNeeded = distance*60 +

60;//0.5/30*3600

//if (timeNeeded <= maxTime && current->trip->finalArrivalTime + timeNeeded <= trip->DepartureTime && current->trip->finalArrivalTime + timeNeeded >= trip->DepartureTime - (call + DD))

if (current->trip->finalArrivalTime[current->trip->finalArrivalTime.size() - 1] + timeNeeded <= trip->DepartureTime)

{emptyVehicleDistance =

emptyVehicleDistance + distance;current->tripsCompleted++;current->trip = trip;current->timeEmpty = current->timeEmpty

- (trip->finalArrivalTime[trip->finalArrivalTime.size() - 1] - trip->DepartureTime);

// delete from current stationif (current->prev == NULL && current-

>next == NULL){

station_first[y][x] = NULL;station_last[y][x] = NULL;

}else if (current->prev != NULL &&

current->next == NULL){

current->prev->next = NULL;station_last[y][x] = current-

>prev;}else if (current->prev == NULL &&

current->next != NULL){

current->next->prev = NULL;station_first[y][x] = current-

>next;}else{

current->prev->next = current->next;

current->next->prev = current->prev;

}

// add to relevant stationint yf = trip->finalDestY[trip-

>finalDestY.size() - 1];int xf = trip->finalDestX[trip-

>finalDestX.size() - 1];if (station_first[yf][xf] == NULL){

station_first[yf][xf] = current;station_last[yf][xf] = current;current->prev = NULL;current->next = NULL;

}else{

station_last[yf][xf]->next = current;

current->prev = station_last[yf][xf];

station_last[yf][xf] = current;current->next = NULL;

}

totalTripsCompleted++;

return current;}

}current = current->next;

}}

}}

}

return NULL;}

Taxi *Fleet::CreateNewTaxi(TaxiTrip *trip){

Taxi *taxi = new Taxi();taxi->waiting = 0;taxi->tripsCompleted = 1;taxi->trip = trip;taxi->timeEmpty = taxi->timeEmpty - (trip->finalArrivalTime[trip-

>finalArrivalTime.size() - 1] - trip->DepartureTime);

// add to taxi stationint y = trip->finalDestY[trip->finalDestY.size() - 1];int x = trip->finalDestX[trip->finalDestX.size() - 1];if (station_first[y][x] == NULL){

station_first[y][x] = taxi;station_last[y][x] = taxi;taxi->prev = NULL;taxi->next = NULL;

}else{

station_last[y][x]->next = taxi;taxi->prev = station_last[y][x];station_last[y][x] = taxi;taxi->next = NULL;

}

totalFleet++;totalTripsCompleted++;

return taxi;}

/*void Fleet::CreateTaxiTrip(int originY, int originX, int DepartureTime, vector<int> *destY, vector<int> *destX, vector<int> *ArrivalTime){

TaxiTrip *trip = new TaxiTrip(originY, originX, DepartureTime, destY, destX, ArrivalTime);

trip->completed = 0;

trips.push_back(trip);}*/

int Fleet::FleetSize(){

return totalFleet;}

int Fleet::TotalTaxiTrips(void){

return totalTripsCompleted;}

Taxi::Taxi(void){

timeEmpty = 86400; //24*60*60}

Taxi::~Taxi(void){}

TaxiTrip::TaxiTrip(){}

int Fleet::x_range(void){

return X_STATION_RANGE;}

int Fleet::y_range(void){

return Y_STATION_RANGE;}

Relevant Parts from Graphics Code:Particle.cpp:

////////////////////////////////////////////////////////////// Generating Particles////////////////////////////////////////////////////////////

void GenerateParticles(R3Scene *scene, double current_time, double delta_time, Taxi *taxi){

// Generate new particles for every sourceR3Particle *particle = new R3Particle();particle->position = R3Point(taxi->trip->originX, taxi->trip->originY, 0);R3Material *m = new R3Material(*scene->ParticleSource(0)->material);particle->material = m;//particle->material->ka = R3Rgb(R2Pixel(1.0,0.0,1.0,0));particle->material->kd = R3Rgb(R2Pixel(1.0,1.0,1.0,0));//particle->material->ks = R3Rgb(R2Pixel(1.0,1.0,1.0,0));particle->taxi = taxi;particle->taxi->particleIndex = scene->NParticles();

particle->velocity = R3Point(taxi->trip->finalDestX[0], taxi->trip->finalDestY[0], 0) - particle->position;

//particle->velocity.Normalize();//particle->taxi->trip->realStartTime = current_time;//particle->taxi->trip->distanceLeft = abs(taxi->trip->finalDestY - taxi->trip-

>originY) + abs(taxi->trip->finalDestX - taxi->trip->originX);scene->particles.push_back(particle);//fprintf(stdout, "%d\n", scene->NParticles());

}

////////////////////////////////////////////////////////////// Updating Particles////////////////////////////////////////////////////////////

void UpdateParticles(R3Scene *scene, double current_time, double delta_time, int integration_type){ // Update position for every particle

for (int i = 0; i < scene->NParticles(); i++){

if (scene->Particle(i)->taxi->trip->completed == 0){

scene->Particle(i)->taxi->waiting = 0;int index = scene->Particle(i)->taxi->trip->pathcompleted;//double distance;double tripTime;if (index == 0){

//distance = abs(scene->Particle(i)->taxi->trip->finalDestY[0] - scene->Particle(i)->taxi->trip->originY) + abs(scene->Particle(i)->taxi->trip->finalDestX[0] - scene->Particle(i)->taxi->trip->originX);

tripTime = (scene->Particle(i)->taxi->trip->finalArrivalTime[index] - scene->Particle(i)->taxi->trip->DepartureTime)/60.0;

}else{

tripTime = (scene->Particle(i)->taxi->trip->finalArrivalTime[index] - scene->Particle(i)->taxi->trip->finalArrivalTime[index - 1])/60.0;

//distance = abs(scene->Particle(i)->taxi->trip->finalDestY[index] - scene->Particle(i)->taxi->trip->finalDestY[index - 1]) + abs(scene->Particle(i)->taxi->trip->finalDestX[index] - scene->Particle(i)->taxi->trip->finalDestX[index - 1]);

}//double distance = abs(scene->Particle(i)->taxi->trip-

>finalDestY[scene->Particle(i)->taxi->trip->pathcompleted + 1] - scene->Particle(i)->taxi->trip->originY) + abs(scene->Particle(i)->taxi->trip->finalDestX[scene->Particle(i)->taxi->trip->pathcompleted + 1] - scene->Particle(i)->taxi->trip->originX);

//double tripTime = (scene->Particle(i)->taxi->trip->finalArrivalTime[scene->Particle(i)->taxi->trip->finalArrivalTime.size() - 1] - scene->Particle(i)->taxi->trip->DepartureTime)/60.0;

if (current_time >= (double (scene->Particle(i)->taxi->trip->finalArrivalTime[index]))/60.0)

{//fprintf(stdout,"%f\n",current_time);scene->Particle(i)->position = R3Point(scene->Particle(i)->taxi-

>trip->finalDestX[index], scene->Particle(i)->taxi->trip->finalDestY[index], 0);scene->Particle(i)->taxi->trip->pathcompleted++;if (scene->Particle(i)->taxi->trip->finalDestY.size() == scene-

>Particle(i)->taxi->trip->pathcompleted)

{scene->Particle(i)->taxi->trip->completed = 1;if (scene->Particle(i)->material->kd.Green() > 1e-12){

//scene->Particle(i)->material->kd = R3Rgb(R2Pixel(1,0,0,0));

scene->Particle(i)->material->kd.SetBlue(scene->Particle(i)->material->kd.Blue() - 0.1);

scene->Particle(i)->material->kd.SetGreen(scene->Particle(i)->material->kd.Green() - 0.1);

}scene->Particle(i)->taxi->waiting = 1;

}else{

scene->Particle(i)->velocity = R3Point(scene->Particle(i)->taxi->trip->finalDestX[index + 1], scene->Particle(i)->taxi->trip->finalDestY[index + 1], 0) - scene->Particle(i)->position;

}}else{

//fprintf(stdout,"%f\n",delta_time);scene->Particle(i)->position += scene->Particle(i)-

>velocity*delta_time/tripTime;}

}

/*if (scene->Particle(i)->taxi->waiting == 1){

scene->Particle(i)->material->ka = R3Rgb(R2Pixel(1,0,0,0));scene->Particle(i)->material->kd = R3Rgb(R2Pixel(1,0,0,0));scene->Particle(i)->material->ks = R3Rgb(R2Pixel(1,0,0,0));

}else{

scene->Particle(i)->material = scene->ParticleSource(0)->material;}*/

}}

Particleview.cpp:

int main(int argc, char **argv){ // Parse program arguments if (!ParseArgs(argc, argv)) exit(1);

RideShare *rs = new RideShare(delay_departure,common_destinations,pick_up); rs->RideShareAnalysis(trip_file_name);

fprintf(stdout,"Total Trips: %d\n", rs->totalTrips);fprintf(stdout, "Total Departed Taxis: %d\n", rs->totalDepartedTaxis);fprintf(stdout,"Total Trip Miles: %d\n",rs->totalTripMiles);fprintf(stdout,"Total Taxi Miles: %d\n",rs->totalTaxiMiles);delete rs;

//fprintf(stdout,"%d\n",common_destinations); //fprintf(stdout,"%d\n",max_empty_travel_time);

/******************************************************************************************************************/ //ft = new Fleet(2,0); ft = new Fleet(common_destinations, delay_departure, max_empty_travel_time); ft->FleetAnalysis_Read(); ft->FleetAnalysis_Analyze(); fprintf(stdout, "Total Taxi Trips: %d\n", ft->TotalTaxiTrips()); fprintf(stdout, "Fleet Size: %d\n", ft->FleetSize()); // Open file FILE *scenefile = fopen("stations.scn", "w"); if (!scenefile) { fprintf(stderr, "Unable to open file %s\n", "stations.scn"); }

fprintf(scenefile, "%s\n", "material 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 10 1 0");fprintf(scenefile,"\n");

/* particle_source mass fixed drag elasticity lifetime mat_id rate velocity angle_cutoff source_shape

particle_source 1 0 0 0 0 4 10 0 0 sphere 0 3 0 1*/ for (int i = 1; i < ft->y_range(); i++) {

for (int j = 1; j < ft->x_range(); j++) {

if (ft->stations[i][j] == 1) {

fprintf(scenefile,"%s\n","particle_source"); fprintf(scenefile, "%s\n", "1 0 0 0 0 0"); fprintf(scenefile, "%s\n", "100 0 0"); fprintf(scenefile,"%s ","sphere"); fprintf(scenefile,"%d %d %d ", j, i, 0); fprintf(scenefile,"%s\n", "0.5"); fprintf(scenefile,"\n");

} }

}

fclose(scenefile); // fprintf(stdout, "Total Taxi Trips: %d\n", ft->TotalTaxiTrips()); //fprintf(stdout, "Fleet Size: %d\n", ft->FleetSize()); //fprintf(stdout, "Empty Vehicle Miles: %d\n", ft->emptyVehicleDistance); /******************************************************************************************************************/ delete ft;

ft = new Fleet(common_destinations, delay_departure, max_empty_travel_time); ft->FleetAnalysis_Read();

input_scene_name = "stations.scn";

// Initialize GLUT GLUTInit(&argc, argv);

// Read scene scene = ReadScene(input_scene_name); if (!scene) exit(-1);

// Run GLUT interface GLUTMainLoop();

//fprintf(stdout, "Total Taxi Trips: %d\n", ft->TotalTaxiTrips()); //fprintf(stdout, "Fleet Size: %d\n", scene->NParticles());

// delete memory delete ft;

//fprintf(stdout,"%d\n",scene->NParticles());

// Return success return 0;}void DrawParticles(R3Scene *scene){ // Get current time (in seconds) since start of execution double current_time = GetTime(); static double previous_time = 0;

static double time_lost_taking_videos = 0; // for switching back and forth // between recording and not // recording smoothly

// program just started up? if (previous_time == 0) previous_time = current_time;

// time passed since starting double delta_time = current_time - previous_time;

if (save_video) { // in video mode, the time that passes only depends on the frame rate ... delta_time = VIDEO_FRAME_DELAY; // ... but we need to keep track how much time we gained and lost so that we can arbitrarily switch back and forth ... time_lost_taking_videos += (current_time - previous_time) - VIDEO_FRAME_DELAY; } else { // real time simulation delta_time = current_time - previous_time; }

if (current_time >= hour*30) {

fprintf(stdout, "Seconds from Midnight: %d\n", hour*60*30); hour++;

}

// Update particles UpdateParticles(scene, current_time - time_lost_taking_videos, delta_time, integration_type);

// Generate new particles if (taxiTripsAnalyzed <= ft->trips.size() - 1 && (double (ft->trips[taxiTripsAnalyzed]->DepartureTime)/60.0) <= current_time) {

Taxi *t = ft->CheckExistingFleet(ft->trips[taxiTripsAnalyzed]); if (t == NULL)

{t = ft->CreateNewTaxi(ft->trips[taxiTripsAnalyzed]);GenerateParticles(scene, current_time - time_lost_taking_videos,

delta_time, t);}else{

scene->Particle(t->particleIndex)->position = R3Point(t->trip->originX, t->trip->originY, 0);

scene->Particle(t->particleIndex)->velocity = R3Point(t->trip->finalDestX[t->trip->finalDestX.size() - 1], t->trip->finalDestY[t->trip->finalDestY.size() - 1], 0) - scene->Particle(t->particleIndex)->position;

}taxiTripsAnalyzed++;

} else {

}//GenerateParticles(scene, current_time - time_lost_taking_videos, delta_time);

// Render particles if (show_particles) RenderParticles(scene, current_time - time_lost_taking_videos, delta_time);

// Remember previous time previous_time = current_time;

time++;}

*Code for the graphics simulation took parts from code made for Princeton’s Spring 2013 COS 426 course.


Recommended