Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include "domain.h"
- #include "graph.h"
- #include "router.h"
- #include "transport_catalogue.h"
- #include <cmath>
- #include <memory>
- #include <set>
- #include <list>
- #include <map>
- #include <variant>
- constexpr size_t begin_pseudo_vertex = -1;
- template<typename KEY,typename VALUE>
- const std::map<VALUE,KEY> InvertMap(std::map<KEY,VALUE>& dictionary){
- std::map<VALUE,KEY> result;
- for (auto& [key,value]:dictionary)
- result[value]=key;
- return std::move(result);
- }
- using namespace std::string_view_literals;
- namespace Catalogue{
- namespace Routering{
- using Minutes = double;
- struct Settings{
- double bus_wait_time=0;
- double bus_velocity=0;
- };
- using StopName = std::string_view;
- using BusName = std::string_view;
- class RouterManager{
- using Graph = graph::DirectedWeightedGraph<Minutes>;
- struct WaitCommand{
- StopName stop_name_;
- Minutes time_;
- WaitCommand& SetTimeWaiting(Minutes time){
- time_=time;
- return *this;
- }
- WaitCommand& SetStopName(StopName name){
- stop_name_=name;
- return *this;
- }
- };
- struct BusProceedCommand{
- BusName bus_name_;
- int span_count_;
- Minutes time_;
- BusProceedCommand& SetTime(Minutes time){
- time_=time;
- return *this;
- }
- BusProceedCommand& SetSpanCount(size_t span_count){
- span_count_=span_count;
- return *this;
- }
- BusProceedCommand& SetBusName(BusName name){
- bus_name_=name;
- return *this;
- }
- };
- public:
- struct Command: private std::variant<nullptr_t,WaitCommand, BusProceedCommand>{
- using variant::variant;
- bool IsWaitCommand() const{
- if(std::holds_alternative<WaitCommand>(*this))
- return true;
- else return false;
- }
- bool IsBusCommand() const{
- if(std::holds_alternative<BusProceedCommand>(*this))
- return true;
- else return false;
- }
- BusProceedCommand& AsBusCommand(){
- return std::get<BusProceedCommand>(*this);
- }
- WaitCommand& AsWaitCommand(){
- return std::get<WaitCommand>(*this);
- }
- std::string_view GetBusName(){
- if(IsBusCommand())
- return AsBusCommand().bus_name_;
- else
- throw std::logic_error("Not bus command");
- }
- std::string_view GetStopName(){
- if(IsWaitCommand())
- return AsWaitCommand().stop_name_;
- else
- throw std::logic_error("Not wait command");
- }
- int GetSpanCount(){
- if (IsBusCommand())
- return AsBusCommand().span_count_;
- else
- throw std::logic_error("Not bus command");
- }
- WaitCommand& SetTimeWaiting(Minutes time){
- return AsWaitCommand().SetTimeWaiting(time);
- }
- WaitCommand& SetStopName(StopName name){
- return AsWaitCommand().SetStopName(name);
- }
- BusProceedCommand& SetBusName(BusName name){
- return AsBusCommand().SetBusName(name);
- }
- };
- struct ResultRouteOptimization{
- Minutes summary_time;
- std::optional<std::vector<Command>> commands;
- };
- RouterManager(std::shared_ptr<Transport> catalogue):catalogue_(catalogue){
- }
- ResultRouteOptimization SearchOptimalRoute(StopName from, StopName to) const{
- if(vertex_ids_by_wait_stops.count(from)&&vertex_ids_by_wait_stops.count(to)){
- if(from!=to){
- std::optional<graph::Router<Catalogue::Routering::Minutes>::RouteInfo> result = router_->BuildRoute(vertex_ids_by_wait_stops.at(from),vertex_ids_by_wait_stops.at(to));
- return {result->weight,Reinterpreter(result)};
- }
- else return {0.,std::vector<Command>()};
- }
- else
- return {};
- }
- ResultRouteOptimization SearchOptimalRoute(const Stop& from, const Stop& to) const{
- return std::move(SearchOptimalRoute(from.name_,to.name_));
- }
- RouterManager& SetRouterSettings(Settings settings){
- this->sets_ = settings;
- return *this;
- }
- void InitRouter(){
- int number_vertexes=0;
- for(auto& [bus_name, bus_item]:catalogue_->GetBusData())
- number_vertexes+=bus_item.unique_stops_+(bus_item.stops_.size()-bus_item.unique_stops_)*2;
- graph_=std::make_unique<Graph>(catalogue_->GetStopData().size()*3);
- InitEdgesWaitStops();
- InitVertexIdAndTimesBuses();
- router_=std::make_unique<graph::Router<Minutes>>(*graph_);
- }
- private:
- std::optional<std::vector<Command>> Reinterpreter(std::optional<graph::Router<Catalogue::Routering::Minutes>::RouteInfo> data) const{
- std::vector<Command> commands;
- if(data.has_value()){
- commands.reserve(data->edges.size()+1);
- std::vector<graph::Edge<Minutes>> edges;
- edges.reserve(data->edges.size());
- for(auto& edge:data->edges)
- edges.push_back(graph_->GetEdge(edge));
- for(auto& edge:edges){
- if(IsWaiting(edge)){
- commands.push_back({WaitCommand().SetStopName(stops_by_vertex_ids.at(edge.to)).
- SetTimeWaiting(sets_.bus_wait_time)});
- }
- else if(IsBusProceed(edge)){
- commands.push_back({BusProceedCommand().SetBusName(buses_by_vertex_ids.at(edge.from).at(edge.to)).
- SetTime(edge.weight).SetSpanCount(span_count.at(edge.from).at(edge.to))});
- }
- else
- throw std::logic_error("Error action defining by router");
- }
- if(!commands.empty()){
- assert(commands.front().IsWaitCommand());
- assert(commands.back().IsBusCommand());
- }
- return commands;
- }
- return std::nullopt;
- }
- bool IsWaiting(graph::Edge<Minutes> edge) const{
- if(stops_by_vertex_ids.count(edge.from) && stops_by_vertex_ids.count(edge.to)){
- StopName from_name = stops_by_vertex_ids.at(edge.from);
- StopName to_name = stops_by_vertex_ids.at(edge.to);
- if(vertex_ids_by_wait_stops.at(from_name)==edge.from && vertex_ids_by_bus_stops.at(to_name)==edge.to)
- return true;
- else return false;
- }
- else return false;
- }
- bool IsBusProceed(graph::Edge<Minutes> edge) const{
- if(stops_by_vertex_ids.count(edge.from) && stops_by_vertex_ids.count(edge.to)){
- StopName from_name = stops_by_vertex_ids.at(edge.from);
- StopName to_name = stops_by_vertex_ids.at(edge.to);
- if(vertex_ids_by_bus_stops.at(from_name)==edge.from && vertex_ids_by_wait_stops.at(to_name)==edge.to)
- return true;
- else return false;
- }
- else return false;
- }
- void InitVertexIdAndTimesBuses(){ //инициализация псевдовершин (вспомогательные вершины, разделяющие ожидание и время в пути)
- const auto& buses = catalogue_->GetBusData();
- for (auto& [bus_name,bus_object]:buses){
- for (auto stop_ptr1=bus_object.stops_.begin();stop_ptr1!=bus_object.stops_.end()-1;++stop_ptr1){
- for (auto stop_ptr2=stop_ptr1+1;stop_ptr2!=bus_object.stops_.end();++stop_ptr2){
- Minutes time_direct = 0;
- Minutes time_reverse = 0;
- if((*stop_ptr1)->name_=="Biryusinka" && (*stop_ptr2)->name_=="TETs 26"){
- int i=0;
- i=i;
- }
- for (auto route_iter = stop_ptr1;route_iter<stop_ptr2;++route_iter){
- time_direct += ComputeTime((*route_iter)->name_,(*(route_iter+1))->name_);
- time_reverse+=ComputeTime((*(route_iter+1))->name_,(*route_iter)->name_);
- }
- span_count[vertex_ids_by_bus_stops.at((*stop_ptr1)->name_)]
- [vertex_ids_by_wait_stops.at((*stop_ptr2)->name_)]=std::abs(stop_ptr2-stop_ptr1);
- graph_->AddEdge({vertex_ids_by_bus_stops.at((*stop_ptr1)->name_),
- vertex_ids_by_wait_stops.at((*stop_ptr2)->name_),
- time_direct});
- AddBusByVertexesDefinition((*stop_ptr1)->name_,
- (*stop_ptr2)->name_,
- bus_name);
- if(!bus_object.IsRoundTrip()){
- graph_->AddEdge({vertex_ids_by_bus_stops.at((*stop_ptr2)->name_),
- vertex_ids_by_wait_stops.at((*stop_ptr1)->name_),
- time_reverse});
- AddBusByVertexesDefinition((*stop_ptr2)->name_,
- (*stop_ptr1)->name_,
- bus_name);
- span_count[vertex_ids_by_bus_stops.at((*stop_ptr2)->name_)]
- [vertex_ids_by_wait_stops.at((*stop_ptr1)->name_)]=std::abs(stop_ptr2-stop_ptr1);
- if(time_direct==0){
- int i=0;
- i=i;
- }
- }
- }
- }
- }
- }
- void InitEdgesWaitStops(){ //инициализация "супер-вершин" (управляющие вершины - фактические вершины, относительно которых будут делаться расчёты)
- graph::VertexId vertex_id=0;
- auto& stops = catalogue_->GetStopData();
- for(const auto& [stop_name,stop_info]:stops){
- AddWaitVertexId(stop_name,vertex_id);
- AddBusVertexId(stop_name,vertex_id+1);
- graph_->AddEdge({
- vertex_id,
- ++vertex_id,
- static_cast<double>(sets_.bus_wait_time)
- });
- ++vertex_id;
- }
- }
- Minutes ComputeTime(StopName from, StopName to) const{
- Minutes dist = static_cast<double>(catalogue_->GetDistance(from,to))/sets_.bus_velocity/100.*6.;
- return dist;
- }
- graph::VertexId AddWaitVertexId(StopName stop_name,graph::VertexId id){
- stops_by_vertex_ids[id]=stop_name;
- return vertex_ids_by_wait_stops[stop_name]=id;
- }
- graph::VertexId AddBusVertexId(StopName stop_name, graph::VertexId id){
- stops_by_vertex_ids[id]=stop_name;
- return vertex_ids_by_bus_stops[stop_name]=id;
- }
- void AddBusByVertexesDefinition(StopName from, StopName to, BusName bus_name){
- buses_by_vertex_ids[vertex_ids_by_bus_stops.at(from)][vertex_ids_by_wait_stops.at(to)]=bus_name;
- }
- Settings sets_;
- std::shared_ptr<Transport> catalogue_;
- std::unique_ptr<Graph> graph_;
- std::unique_ptr<graph::Router<Minutes>> router_;
- std::map<StopName,graph::VertexId> vertex_ids_by_wait_stops;
- std::map<StopName,graph::VertexId> vertex_ids_by_bus_stops;
- std::map<graph::VertexId,StopName> stops_by_vertex_ids;
- std::map<graph::VertexId,std::map<graph::VertexId,size_t>> span_count;
- std::map<graph::VertexId,std::map<graph::VertexId,BusName>> buses_by_vertex_ids;
- };
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement