#include "engine/archive.h" #include "engine/engine.h" #include #include namespace CityFlow { Archive::Archive(const Engine &engine) : step(engine.step), activeVehicleCount(engine.activeVehicleCount), rnd(engine.rnd), finishedVehicleCnt(engine.finishedVehicleCnt), cumulativeTravelTime(engine.cumulativeTravelTime) { // copy the vehicle Pool vehiclePool = copyVehiclePool(engine.vehiclePool); // record the information of each drivable object for (const auto &drivable : engine.roadnet.getDrivables()) { auto result = drivablesArchive.emplace(drivable, DrivableArchive()); assert(result.second); archiveDrivable(drivable, result.first->second); } // record the information of each flow for (const auto &flow : engine.flows) { auto result = flowsArchive.emplace(&flow, FlowArchive()); assert(result.second); archiveFlow(&flow, result.first->second); } //record the information of each traffic light for (const auto &intersection : engine.roadnet.getIntersections()) { const auto &light = &intersection.getTrafficLight(); auto result = trafficLightsArchive.emplace(&intersection, TrafficLightArchive()); assert(result.second); archiveTrafficLight(light, result.first->second); } } Vehicle *Archive::getNewPointer(const VehiclePool &vehiclePool, const Vehicle *old) { if (!old) return nullptr; int priority = old->getPriority(); auto result = vehiclePool.find(priority); assert(result != vehiclePool.end()); return result->second.first; } void Archive::archiveDrivable(const Drivable *drivable, Archive::DrivableArchive &drivableArchive) { for (const auto &vehicle : drivable->getVehicles()) drivableArchive.vehicles.emplace_back(getNewPointer(vehiclePool, vehicle)); if (drivable->isLane()) { const Lane *lane = static_cast(drivable); for (const auto &vehicle : lane->getWaitingBuffer()) { drivableArchive.waitingBuffer.emplace_back(getNewPointer(vehiclePool, vehicle)); } drivableArchive.history = lane->history; drivableArchive.historyVehicleNum = lane->historyVehicleNum; drivableArchive.historyAverageSpeed = lane->historyAverageSpeed; } } void Archive::archiveFlow(const Flow *flow, Archive::FlowArchive &flowArchive) { flowArchive.currentTime = flow->currentTime; flowArchive.nowTime = flow->nowTime; flowArchive.cnt = flow->cnt; } void Archive::archiveTrafficLight(const TrafficLight *light, Archive::TrafficLightArchive &trafficLightArchive) { trafficLightArchive.curPhaseIndex = light->curPhaseIndex; trafficLightArchive.remainDuration = light->remainDuration; } void Archive::resume(Engine &engine) const{ engine.step = step; engine.activeVehicleCount = activeVehicleCount; for (auto &veh : engine.vehiclePool) { auto vehicle = veh.second.first; delete vehicle; } engine.vehiclePool = copyVehiclePool(vehiclePool); engine.vehicleMap.clear(); for (const auto &iter : engine.vehiclePool) { Vehicle *vehicle = iter.second.first; engine.vehicleMap.emplace(vehicle->getId(), vehicle); } engine.rnd = rnd; for (auto &threadVeh : engine.threadVehiclePool) threadVeh.clear(); for (const auto &pair : engine.vehiclePool) { const auto &vehicle = pair.second.first; size_t threadIndex = pair.second.second; engine.threadVehiclePool[threadIndex].emplace(vehicle); } for (auto &drivable : engine.roadnet.getDrivables()) { const auto &archive = drivablesArchive.find(drivable)->second; drivable->vehicles.clear(); for (const auto &vehicle : archive.vehicles) { drivable->vehicles.emplace_back(getNewPointer(engine.vehiclePool, vehicle)); } if (drivable->isLane()) { Lane *lane = static_cast(drivable); lane->waitingBuffer.clear(); for (const auto &vehicle : archive.waitingBuffer) { lane->waitingBuffer.emplace_back(getNewPointer(engine.vehiclePool, vehicle)); } lane->history = archive.history; lane->historyVehicleNum = archive.historyVehicleNum; lane->historyAverageSpeed = archive.historyAverageSpeed; } } for (auto &flow : engine.flows) { const auto &archive = flowsArchive.find(&flow)->second; flow.currentTime = archive.currentTime; flow.nowTime = archive.nowTime; flow.cnt = archive.cnt; } for (auto &intersection : engine.roadnet.getIntersections()) { auto &light = intersection.getTrafficLight(); const auto &archive = trafficLightsArchive.find(&intersection)->second; light.remainDuration = archive.remainDuration; light.curPhaseIndex = archive.curPhaseIndex; } engine.finishedVehicleCnt = this->finishedVehicleCnt; engine.cumulativeTravelTime = this->cumulativeTravelTime; } Archive::VehiclePool Archive::copyVehiclePool(const VehiclePool &src) { VehiclePool newPool; for (const auto &veh : src) { const Vehicle *oldVehicle = veh.second.first; Vehicle *newVehicle = new Vehicle(*oldVehicle); newPool.emplace(oldVehicle->getPriority(), std::make_pair(newVehicle, veh.second.second)); } // update the vehicle pointers for (const auto &veh : newPool) { Vehicle *vehicle = veh.second.first; vehicle->laneChangeInfo.partner = getNewPointer(newPool, vehicle->laneChangeInfo.partner); vehicle->controllerInfo.leader = getNewPointer(newPool, vehicle->controllerInfo.leader); vehicle->controllerInfo.blocker = getNewPointer(newPool, vehicle->controllerInfo.blocker); std::shared_ptr laneChange = vehicle->laneChange; laneChange->targetLeader = getNewPointer(newPool, laneChange->targetLeader); laneChange->targetFollower = getNewPointer(newPool, laneChange->targetFollower); if (laneChange->signalRecv) { laneChange->signalRecv = getNewPointer(newPool, laneChange->signalRecv->source)->laneChange->signalSend; } } return newPool; } void Archive::dump(const std::string &fileName) const { rapidjson::Document jsonRoot; jsonRoot.SetObject(); auto &allocator = jsonRoot.GetAllocator(); jsonRoot.AddMember("step", static_cast(this->step), allocator); jsonRoot.AddMember("activeVehicleCount", static_cast(this->activeVehicleCount), allocator); std::stringstream rndStringStream; rndStringStream << this->rnd; rapidjson::Value rndValue; rndValue.SetString(rndStringStream.str().c_str(), jsonRoot.GetAllocator()); jsonRoot.AddMember("rnd", rndValue, allocator); // Serialize the mt19937 object dumpVehicles(jsonRoot); dumpDrivables(jsonRoot); dumpFlows(jsonRoot); dumpTrafficLights(jsonRoot); jsonRoot.AddMember("finishedVehicleCnt", finishedVehicleCnt, allocator); jsonRoot.AddMember("cumulativeTravelTime", cumulativeTravelTime, allocator); writeJsonToFile(fileName, jsonRoot); } rapidjson::Value Archive::dumpVehicle(const Vehicle &vehicle, rapidjson::Document &jsonRoot) const { rapidjson::Value vehicleValue(rapidjson::kObjectType); auto &allocator = jsonRoot.GetAllocator(); vehicleValue.AddMember("priority", vehicle.priority, allocator); vehicleValue.AddMember("id", rapidjson::Value(vehicle.getId(), allocator).Move(), allocator); vehicleValue.AddMember("enterTime", vehicle.enterTime, allocator); // save vehicleInfo vehicleValue.AddMember("speed", vehicle.vehicleInfo.speed, allocator); vehicleValue.AddMember("len", vehicle.vehicleInfo.len, allocator); vehicleValue.AddMember("width", vehicle.vehicleInfo.width, allocator); vehicleValue.AddMember("maxPosAcc", vehicle.vehicleInfo.maxPosAcc, allocator); vehicleValue.AddMember("maxNegAcc", vehicle.vehicleInfo.maxNegAcc, allocator); vehicleValue.AddMember("usualPosAcc", vehicle.vehicleInfo.usualPosAcc, allocator); vehicleValue.AddMember("usualNegAcc", vehicle.vehicleInfo.usualNegAcc, allocator); vehicleValue.AddMember("minGap", vehicle.vehicleInfo.minGap, allocator); vehicleValue.AddMember("maxSpeed", vehicle.vehicleInfo.maxSpeed, allocator); vehicleValue.AddMember("headwayTime", vehicle.vehicleInfo.headwayTime, allocator); vehicleValue.AddMember("yieldDistance", vehicle.vehicleInfo.yieldDistance, allocator); vehicleValue.AddMember("turnSpeed", vehicle.vehicleInfo.turnSpeed, allocator); // save route rapidjson::Value routeValue(rapidjson::kArrayType); for (const auto &road : vehicle.controllerInfo.router.route) { pushBackObjectAsMember(routeValue, road, allocator); } vehicleValue.AddMember("route", routeValue, allocator); // save controllerInfo vehicleValue.AddMember("dis", vehicle.controllerInfo.dis, allocator); addObjectAsMember(vehicleValue, "drivable", vehicle.controllerInfo.drivable, allocator); addObjectAsMember(vehicleValue, "prevDrivable", vehicle.controllerInfo.prevDrivable, allocator); vehicleValue.AddMember("approachingIntersectionDistance", vehicle.controllerInfo.approachingIntersectionDistance, allocator); vehicleValue.AddMember("gap", vehicle.controllerInfo.gap, allocator); vehicleValue.AddMember("enterLaneLinkTime", static_cast(vehicle.controllerInfo.enterLaneLinkTime), allocator); addObjectAsMember(vehicleValue, "leader", vehicle.controllerInfo.leader, allocator); addObjectAsMember(vehicleValue, "blocker", vehicle.controllerInfo.blocker, allocator); vehicleValue.AddMember("end", vehicle.controllerInfo.end, allocator); vehicleValue.AddMember("running", vehicle.controllerInfo.running, allocator); // save lane change info vehicleValue.AddMember("partnerType", vehicle.laneChangeInfo.partnerType, allocator); addObjectAsMember(vehicleValue, "partner", vehicle.laneChangeInfo.partner, allocator); vehicleValue.AddMember("offset", vehicle.laneChangeInfo.offset, allocator); if (vehicle.laneChange->signalSend) { auto &signal = vehicle.laneChange->signalSend; vehicleValue.AddMember("laneChangeUrgency", signal->urgency, allocator); vehicleValue.AddMember("laneChangeDirection", signal->direction, allocator); addObjectAsMember(vehicleValue, "laneChangeTarget", signal->target, allocator); } if (vehicle.laneChange->signalRecv) { auto &signal = vehicle.laneChange->signalRecv; addObjectAsMember(vehicleValue, "laneChangeRecv", signal->source, allocator); } addObjectAsMember(vehicleValue, "laneChangeLeader", vehicle.laneChange->targetLeader, allocator); addObjectAsMember(vehicleValue, "laneChangeFollower", vehicle.laneChange->targetFollower, allocator); vehicleValue.AddMember("laneChangeWaitingTime", vehicle.laneChange->waitingTime, allocator); vehicleValue.AddMember("laneChanging", vehicle.laneChange->changing, allocator); vehicleValue.AddMember("laneChangeLastTime", vehicle.laneChange->lastChangeTime, allocator); return vehicleValue; } void Archive::dumpVehicles(rapidjson::Document &jsonRoot) const { rapidjson::Value vehicleArray(rapidjson::kArrayType); auto &allocator = jsonRoot.GetAllocator(); for (const auto &iter : this->vehiclePool) { const auto &vehicle = iter.second.first; assert(vehicle); rapidjson::Value vehicleValue = dumpVehicle(*vehicle, jsonRoot); vehicleArray.PushBack(vehicleValue, allocator); } jsonRoot.AddMember("vehicles", vehicleArray, allocator); } void Archive::dumpDrivables(rapidjson::Document &jsonRoot) const { rapidjson::Value drivablesValue(rapidjson::kObjectType); auto &allocator = jsonRoot.GetAllocator(); for (const auto &iter : drivablesArchive) { rapidjson::Value drivableValue(rapidjson::kObjectType); const Drivable *drivable = iter.first; const DrivableArchive &drivableArchive = iter.second; // save vehicles rapidjson::Value vehicleList(rapidjson::kArrayType); for (const auto &vehicle : drivableArchive.vehicles) { pushBackObjectAsMember(vehicleList, vehicle, allocator); } drivableValue.AddMember("vehicles", vehicleList, allocator); if (drivable->isLane()) { // save waiting buffer rapidjson::Value waitingBuffer(rapidjson::kArrayType); for (const auto &vehicle : drivableArchive.waitingBuffer) { pushBackObjectAsMember(waitingBuffer, vehicle, allocator); } drivableValue.AddMember("waitingBuffer", waitingBuffer, allocator); //save history rapidjson::Value historyValue(rapidjson::kArrayType); for (const auto &record : drivableArchive.history) { historyValue.PushBack(record.vehicleNum, allocator); historyValue.PushBack(record.averageSpeed, allocator); } drivableValue.AddMember("history", historyValue, allocator); drivableValue.AddMember("historyVehicleNum", drivableArchive.historyVehicleNum, allocator); drivableValue.AddMember("historyAverageSpeed", drivableArchive.historyAverageSpeed, allocator); } drivablesValue.AddMember( rapidjson::Value(drivable->getId(), allocator).Move(), drivableValue, allocator ); } jsonRoot.AddMember("drivables", drivablesValue, allocator); } void Archive::dumpFlows(rapidjson::Document &jsonRoot) const { rapidjson::Value flowsValue(rapidjson::kObjectType); auto &allocator = jsonRoot.GetAllocator(); for (const auto &iter : flowsArchive) { const auto &flow = iter.first; const auto &flowArchive = iter.second; rapidjson::Value flowValue(rapidjson::kObjectType); flowValue.AddMember("nowTime", flowArchive.nowTime, allocator); flowValue.AddMember("currentTime", flowArchive.currentTime, allocator); flowValue.AddMember("cnt", static_cast(flowArchive.cnt), allocator); flowsValue.AddMember( rapidjson::Value(flow->getId(), allocator).Move(), flowValue, allocator); } jsonRoot.AddMember("flows", flowsValue, allocator); } void Archive::dumpTrafficLights(rapidjson::Document &jsonRoot) const { rapidjson::Value trafficLightsValue(rapidjson::kObjectType); auto &allocator = jsonRoot.GetAllocator(); for (const auto &iter : trafficLightsArchive) { const auto &intersection = iter.first; const auto &trafficLightArchive = iter.second; rapidjson::Value trafficLightValue(rapidjson::kObjectType); trafficLightValue.AddMember("remainDuration", trafficLightArchive.remainDuration, allocator); trafficLightValue.AddMember("curPhaseIndex", static_cast(trafficLightArchive.curPhaseIndex), allocator); trafficLightsValue.AddMember( rapidjson::Value(intersection->getId(), allocator).Move(), trafficLightValue, allocator); } jsonRoot.AddMember("trafficLights", trafficLightsValue, allocator); } Archive::Archive(Engine &engine, const std::string &filename) { // read from file rapidjson::Document jsonRoot; readJsonFromFile(filename, jsonRoot); std::mt19937 rndTemp; // restore random seed std::string rndString = getJsonMember("rnd", jsonRoot); std::istringstream istr(rndString); istr >> rnd; // restore engine info step = getJsonMember("step", jsonRoot); activeVehicleCount = getJsonMember("activeVehicleCount", jsonRoot); // restore vehiclePool auto &vehiclesValue = getJsonMemberArray("vehicles", jsonRoot); std::map vehicleDict; for (auto &vehicleValue : vehiclesValue.GetArray()) { VehicleInfo vehicleInfo; vehicleInfo.speed = getJsonMember("speed", vehicleValue); vehicleInfo.len = getJsonMember("len", vehicleValue); vehicleInfo.width = getJsonMember("width", vehicleValue); vehicleInfo.maxPosAcc = getJsonMember("maxPosAcc", vehicleValue); vehicleInfo.maxNegAcc = getJsonMember("maxNegAcc", vehicleValue); vehicleInfo.usualPosAcc = getJsonMember("usualPosAcc", vehicleValue); vehicleInfo.usualNegAcc = getJsonMember("usualNegAcc", vehicleValue); vehicleInfo.minGap = getJsonMember("minGap", vehicleValue); vehicleInfo.maxSpeed = getJsonMember("maxSpeed", vehicleValue); vehicleInfo.headwayTime = getJsonMember("headwayTime", vehicleValue); vehicleInfo.yieldDistance = getJsonMember("yieldDistance", vehicleValue); vehicleInfo.turnSpeed = getJsonMember("turnSpeed", vehicleValue); // Rebuild Route std::vector route; auto &routeValue = getJsonMemberArray("route", vehicleValue); for (const auto &roadValue : routeValue.GetArray()) { const auto &roadId = roadValue.GetString(); route.emplace_back(engine.roadnet.getRoadById(roadId)); } vehicleInfo.route = std::make_shared(route); Vehicle *vehicle = new Vehicle(vehicleInfo, getJsonMember("id", vehicleValue), &engine); auto enterTime = getJsonMember("enterTime", vehicleValue); vehicle->enterTime = enterTime; auto priority = getJsonMember("priority", vehicleValue); vehicle->priority = priority; vehiclePool.emplace(priority, std::make_pair(vehicle, rndTemp() % engine.threadNum)); vehicleDict.emplace(vehicle->getId(), vehicle); auto &controllerInfo = vehicle->controllerInfo; controllerInfo.dis = getJsonMember("dis", vehicleValue); controllerInfo.approachingIntersectionDistance = getJsonMember("approachingIntersectionDistance", vehicleValue); controllerInfo.gap = getJsonMember("gap", vehicleValue); controllerInfo.enterLaneLinkTime = getJsonMember("enterLaneLinkTime", vehicleValue); controllerInfo.end = getJsonMember("end", vehicleValue); controllerInfo.running = getJsonMember("running", vehicleValue); auto &laneChangeInfo = vehicle->laneChangeInfo; laneChangeInfo.partnerType = getJsonMember("partnerType", vehicleValue); laneChangeInfo.offset = getJsonMember("offset", vehicleValue); // Construct the laneChange Object vehicle->laneChange = std::make_shared(vehicle); auto &laneChange = vehicle->laneChange; rapidjson::Value::ConstMemberIterator sendItr = vehicleValue.FindMember("laneChangeUrgency"); if (sendItr != vehicleValue.MemberEnd()) { auto signal = std::make_shared(); signal->source = vehicle; signal->urgency = sendItr->value.GetInt(); signal->direction = getJsonMember("laneChangeDirection", vehicleValue); laneChange->signalSend = signal; } laneChange->waitingTime = getJsonMember("laneChangeWaitingTime", vehicleValue); laneChange->changing = getJsonMember("laneChanging", vehicleValue); laneChange->lastChangeTime = getJsonMember("laneChangeLastTime", vehicleValue); } // restore pointer relations for (auto &vehicleValue : vehiclesValue.GetArray()) { std::string vehicleId = getJsonMember("id", vehicleValue); Vehicle *vehicle = vehicleDict[vehicleId]; const char *drivableId = getJsonMember("drivable", vehicleValue, nullptr); assert(drivableId); vehicle->controllerInfo.drivable = engine.roadnet.getDrivableById(std::string(drivableId)); assert(vehicle->controllerInfo.drivable); const char *prevDrivableId = getJsonMember("prevDrivable", vehicleValue, nullptr); if (prevDrivableId) { vehicle->controllerInfo.prevDrivable = engine.roadnet.getDrivableById(std::string(prevDrivableId)); } const char *leaderId = getJsonMember("leader", vehicleValue, nullptr); if (leaderId) { vehicle->controllerInfo.leader = vehicleDict[leaderId]; } const char *blockerId = getJsonMember("blocker", vehicleValue, nullptr); if (blockerId) { vehicle->controllerInfo.blocker = vehicleDict[blockerId]; } const char *partnerId = getJsonMember("partner", vehicleValue, nullptr); if (partnerId) { vehicle->laneChangeInfo.partner = vehicleDict[partnerId]; } if (vehicle->laneChange->signalSend) { auto &signal = vehicle->laneChange->signalSend; const char *targetId = getJsonMember("laneChangeTarget", vehicleValue, nullptr); assert(targetId); Drivable *target = engine.roadnet.getDrivableById(targetId); assert(target->isLane()); signal->target = static_cast(target); } rapidjson::Value::ConstMemberIterator signalRecvIter = vehicleValue.FindMember("laneChangeRecv"); if (signalRecvIter != vehicleValue.MemberEnd()) { std::string sourceId = signalRecvIter->value.GetString(); vehicle->laneChange->signalRecv = vehicleDict[sourceId]->laneChange->signalSend; } const char *laneChangeLeaderId = getJsonMember("laneChangeLeader", vehicleValue, nullptr); if (laneChangeLeaderId) { vehicle->laneChange->targetLeader = vehicleDict[laneChangeLeaderId]; } const char *laneChangeFollowerId = getJsonMember("laneChangeFollower", vehicleValue, nullptr); if (laneChangeFollowerId) { vehicle->laneChange->targetFollower = vehicleDict[laneChangeFollowerId]; } } // Ensure partners in the same thread for (auto &iter : vehiclePool) { auto &vehicle = iter.second.first; if (!vehicle->isReal()) { assert(vehicle->hasPartner()); auto partnerPriority = vehicle->getPartner()->getPriority(); iter.second.second = vehiclePool[partnerPriority].second; } } // restore drivables auto &drivablesValue = getJsonMemberObject("drivables", jsonRoot); for (auto &drivable : engine.roadnet.getDrivables()) { auto &drivableValue = getJsonMemberObject(drivable->getId(), drivablesValue); auto result = drivablesArchive.emplace(drivable, DrivableArchive()); assert(result.second); auto &drivableArchive = result.first->second; auto &vehiclesValue = getJsonMemberArray("vehicles", drivableValue); for (auto &vehicleValue : vehiclesValue.GetArray()) { std::string vehicleId = vehicleValue.GetString(); drivableArchive.vehicles.emplace_back(vehicleDict[vehicleId]); } if (drivable->isLane()) { auto &waitingBufferValue = getJsonMemberArray("waitingBuffer", drivableValue); for (auto &vehicleValue : waitingBufferValue.GetArray()) { std::string vehicleId = vehicleValue.GetString(); drivableArchive.waitingBuffer.emplace_back(vehicleDict[vehicleId]); } auto &historyValue = getJsonMemberArray("history", drivableValue); int cnt = 0; int vehicleNum = 0; for (auto &recordValue : historyValue.GetArray()) { if (cnt % 2) { double averageSpeed = recordValue.GetDouble(); drivableArchive.history.emplace_back(vehicleNum, averageSpeed); } else { vehicleNum = recordValue.GetInt(); } ++cnt; } drivableArchive.historyAverageSpeed = getJsonMember("historyAverageSpeed", drivableValue); drivableArchive.historyVehicleNum = getJsonMember("historyVehicleNum", drivableValue); } } // restore flows auto &flowsValue = getJsonMemberObject("flows", jsonRoot); for (auto &flow : engine.flows) { auto &flowValue = getJsonMemberObject(flow.getId(), flowsValue); auto result = flowsArchive.emplace(&flow, FlowArchive()); assert(result.second); auto &flowArchive = result.first->second; flowArchive.nowTime = getJsonMember("nowTime", flowValue); flowArchive.currentTime = getJsonMember("currentTime", flowValue); flowArchive.cnt = getJsonMember("cnt", flowValue); } // restore trafficlights auto &trafficLightsValue = getJsonMemberObject("trafficLights", jsonRoot); for (auto &intersection : engine.roadnet.getIntersections()) { auto &trafficLightValue = getJsonMemberObject(intersection.getId(), trafficLightsValue); auto result = trafficLightsArchive.emplace(&intersection, TrafficLightArchive()); assert(result.second); auto &trafficLightArchive = result.first->second; trafficLightArchive.remainDuration = getJsonMember("remainDuration", trafficLightValue); trafficLightArchive.curPhaseIndex = getJsonMember("curPhaseIndex", trafficLightValue); } finishedVehicleCnt = getJsonMember("finishedVehicleCnt", jsonRoot); cumulativeTravelTime = getJsonMember("cumulativeTravelTime", jsonRoot); } }