-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVehicle.cpp
202 lines (185 loc) · 7.93 KB
/
Vehicle.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "Classes.h"
#include <iostream>
using namespace std;
Vehicle::Vehicle() {
// Add depot at both ends of the route
type = 1;
currentNodeId = 0;
Node start;
start.id = 0;
start.arrival_time = -1;
start.departure_time = startTime;
Node end;
end.id = 0;
end.arrival_time = 0;
end.departure_time = -1;
this->route.push_back(start);
this->route.push_back(end);
}
bool Vehicle::feasible(int customerid) {
bool timingbool=timingCondition(customers.at(customerid));
bool chargingbool=chargingCondition(customers.at(customerid));
bool capacitybool=capacityCondition(customers.at(customerid));
bool feasiblebool= timingbool && chargingbool && capacitybool ;
return feasiblebool;
}
bool Vehicle::timingCondition(Customer customer) {
time_type currDeptTime = this->route.at(this->route.size()-2).departure_time;
time_type expectedTime = travelTimes.at(this->currentNodeId).at(customer.id) + currDeptTime;
time_type timeToEnd = travelTimes.at(0).at(customer.id);
this->route.back().arrival_time = expectedTime + serviceTime + timeToEnd;
return (expectedTime < customer.timeWindowEnds && this->route.back().arrival_time < endTime);
}
bool Vehicle::capacityCondition(Customer customer) {
double volumeCap = this->type==1 ? capVolType1 : capVolType2;
double weightCap = this->type==2 ? capVolType1 : capVolType2;
bool volume = (this->currentCapVol + customer.demandVol) <= volumeCap;
bool weight = (this->currentCapWeight + customer.demandWeight) <= weightCap;
return (volume && weight);
}
bool Vehicle::chargingCondition(Customer customer) {
// Distance till Depot check must be thought of
// Find the nearest charging station to the customer
double distance = travelCosts.at(this->currentNodeId).at(customer.id) + travelCosts.at(0).at(customer.id) - travelCosts.at(this->currentNodeId).at(0);
return (this->distanceRemaining > distance);
}
void Vehicle::updateTotalCost() {
double fixedCost = this->type==1 ? fixedCost1 : fixedCost2;
this->totalCost = this->travellingCost + this->waitingCost + this->chargingCost + fixedCost;
}
double Vehicle::costAddCustomerCS(Customer customer, int chargingStation) {
double costNodeCS = travelCosts.at(this->currentNodeId).at(chargingStation);
double costCustomerCS = travelCosts.at(customer.id).at(chargingStation);
double endCost = travelCosts.at(customer.id).at(0);
double additionCost = costNodeCS + costCustomerCS + endCost - travelCosts.at(this->currentNodeId).at(0);
return additionCost;
}
double Vehicle::costAddCustomerDepot(Customer customer) {
double costCustDepot = travelCosts.at(customer.id).at(0);
return 2*costCustDepot;
}
void Vehicle::addCustomer(int customerId) {
Customer customer = customers.at(customerId);
Node node;
node.id = customer.id;
time_type timeTaken = travelTimes.at(this->currentNodeId).at(customer.id);
double travelCost = travelCosts.at(this->currentNodeId).at(customer.id);
node.arrival_time = this->route.at(this->route.size()-2).departure_time + timeTaken;
node.departure_time = node.arrival_time + serviceTime;
this->currentNodeId = customer.id;
auto it = this->route.end();
this->route.insert(--it, node);
// Update costs
double factor = this->type == 1 ? unitTransCost1 : unitTransCost2;
this->travellingCost += (travelCost * factor);
double waitCost = (customer.timeWindowStarts > node.arrival_time) ? (customer.timeWindowStarts - node.arrival_time)*waiting_factor : 0;
this->waitingCost += waitCost;
updateTotalCost();
}
void Vehicle::addCustomerCS(int customerId, int chargingStation) {
Node cs;
cs.id = chargingStation;
time_type timeToCS = travelTimes.at(this->currentNodeId).at(chargingStation);
double travelCostCS = travelCosts.at(this->currentNodeId).at(chargingStation);
cs.arrival_time = this->route.at(this->route.size()-2).departure_time + timeToCS;
cs.departure_time = cs.arrival_time + chargingTimeCS;
this->currentNodeId = chargingStation;
auto it = this->route.end();
this->route.insert(--it, cs);
Node node;
node.id = customerId;
Customer customer = customers.at(customerId);
time_type timeTaken = travelTimes.at(this->currentNodeId).at(customer.id);
double travelCost = travelCosts.at(this->currentNodeId).at(customer.id);
node.arrival_time = this->route.at(this->route.size()-2).departure_time + timeTaken;
node.departure_time = node.arrival_time + serviceTime;
this->currentNodeId = customer.id;
it = this->route.end();
this->route.insert(--it, node);
// Update costs
this->travellingCost += (travelCost + travelCostCS);
double waitCost = (customer.timeWindowStarts > node.arrival_time) ? (customer.timeWindowStarts - node.arrival_time)*waiting_factor : 0;
this->waitingCost += waitCost;
this->chargingCost += chargingCostStation;
updateTotalCost();
}
void Vehicle::addCustomerDepot(int customerId) {
Customer customer = customers.at(customerId);
Node depot;
depot.id = 0;
this->currentNodeId = 0;
time_type timeToDepot = travelTimes.at(this->currentNodeId).at(0);
time_type timeDepotToCustomer = travelTimes.at(0).at(customer.id);
double travelCostDepot = travelCosts.at(this->currentNodeId).at(0);
depot.arrival_time = this->route.at(this->route.size()-2).departure_time + timeToDepot;
depot.departure_time = depot.arrival_time + chargingTimeDepot;
auto it = this->route.end();
this->route.insert(--it, depot);
Node node;
node.id = customerId;
node.arrival_time = depot.departure_time + timeDepotToCustomer;
node.departure_time = node.arrival_time + serviceTime;
this->currentNodeId = customer.id;
it = this->route.end();
this->route.insert(--it, node);
// Update costs
double travelCost = travelCosts.at(this->currentNodeId).at(customer.id);
this->travellingCost += travelCost;
double waitCost = (customer.timeWindowStarts > node.arrival_time) ? (customer.timeWindowStarts - node.arrival_time)*waiting_factor : 0;
this->waitingCost += (waitCost + waitingCostDepot);
updateTotalCost();
}
bool Vehicle::addChargingStationOrDepot()
{
double minCost = infinity;
int minCustomerIndex = -1, minChargingStation = -1;
int typeOfInsertion = -1; // 0 for charging station and 1 for depot
for(unsigned i=0; i < customerPool.size(); i++)
{
Customer customer = customers.at(customerPool.at(i));
if(timingCondition(customer))
{
if (capacityCondition(customer))
{
if(!chargingCondition(customer))//if charging condition is not satisfied
{
int chargingStation = customer.findNearestCS();
// Calculate Cost of insertion of customer and charging station
double currCost = costAddCustomerCS(customer, chargingStation);
if (currCost != -1 && currCost < minCost)
{
minCost = currCost;
minCustomerIndex = i;
minChargingStation = chargingStation;
typeOfInsertion = 0;
}
}
else{
cout<<"There is some Error";
std::exit(0);
}
}
else
{
// Add depot and calculate cost
double currCost = costAddCustomerDepot(customer);
if (currCost != -1 && currCost < minCost)
{
minCost = currCost;
minCustomerIndex = i;
typeOfInsertion = 1;
}
}
}
}
if (minCost == -1) {
return false;
}
// Add the suitable customer
if (typeOfInsertion == 0) {
addCustomerCS(minCustomerIndex, minChargingStation);
} else {
addCustomerDepot(minCustomerIndex);
}
return true;
}