* speed up hop-to-hop calculations
* better and faster trip clustering: trip tries * add --write-colors to extract line colors from OSM data * refactor config parameter names, update default pfaedle.cfg * add --stats for writing a stats.json file * add --no-fast-hops, --no-a-star, --no-trie for debugging * general refactoring
This commit is contained in:
parent
f1822868c5
commit
4c29892658
126 changed files with 14576 additions and 12196 deletions
261
src/pfaedle/router/Weights.cpp
Normal file
261
src/pfaedle/router/Weights.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright 2018, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include <limits>
|
||||
#include "pfaedle/router/Weights.h"
|
||||
|
||||
using pfaedle::router::DistDiffTransWeight;
|
||||
using pfaedle::router::ExpoTransWeight;
|
||||
using pfaedle::router::LineSimilarity;
|
||||
using pfaedle::router::NormDistrTransWeight;
|
||||
using util::geo::haversine;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
ExpoTransWeight::DistHeur::DistHeur(double maxV, const RoutingOpts& rOpts,
|
||||
const std::set<trgraph::Edge*>& tos)
|
||||
: _rOpts(rOpts), _maxV(maxV), _maxCentD(0), _lastE(0) {
|
||||
size_t c = 0;
|
||||
double x = 0, y = 0;
|
||||
|
||||
for (const auto to : tos) {
|
||||
x += to->getFrom()->pl().getGeom()->getX();
|
||||
y += to->getFrom()->pl().getGeom()->getY();
|
||||
c++;
|
||||
}
|
||||
|
||||
x /= c;
|
||||
y /= c;
|
||||
|
||||
_center = POINT{x, y};
|
||||
|
||||
for (const auto to : tos) {
|
||||
const double cur = haversine(*to->getFrom()->pl().getGeom(), _center);
|
||||
if (cur > _maxCentD) _maxCentD = cur;
|
||||
}
|
||||
|
||||
_maxCentD /= _maxV;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t ExpoTransWeight::DistHeur::operator()(
|
||||
const trgraph::Edge* a, const std::set<trgraph::Edge*>& b) const {
|
||||
UNUSED(b);
|
||||
|
||||
// avoid repeated calculation for the same edge over and over again
|
||||
if (a == _lastE) return _lastC;
|
||||
|
||||
_lastE = a;
|
||||
|
||||
const double d = haversine(*a->getFrom()->pl().getGeom(), _center);
|
||||
const double heur = fmax(0, (d / _maxV - _maxCentD) * 10);
|
||||
|
||||
// avoid overflow
|
||||
if (heur > std::numeric_limits<uint32_t>::max()) {
|
||||
_lastC = std::numeric_limits<uint32_t>::max();
|
||||
;
|
||||
return _lastC;
|
||||
}
|
||||
|
||||
_lastC = heur;
|
||||
return heur;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t ExpoTransWeight::CostFunc::operator()(const trgraph::Edge* from,
|
||||
const trgraph::Node* n,
|
||||
const trgraph::Edge* to) const {
|
||||
if (!from) return 0;
|
||||
|
||||
uint32_t c = from->pl().getCost();
|
||||
|
||||
if (c == std::numeric_limits<uint32_t>::max()) return c;
|
||||
|
||||
if (from == _lastFrom) {
|
||||
// the transit line simi calculation is independent of the "to" edge, so if
|
||||
// the last "from" edge was the same, skip it!
|
||||
c = _lastC;
|
||||
} else if (!_noLineSimiPen) {
|
||||
const auto& simi = transitLineSimi(from);
|
||||
|
||||
if (!simi.nameSimilar) {
|
||||
if (_rOpts.lineUnmatchedPunishFact < 1) {
|
||||
c = std::ceil(static_cast<double>(c) * _rOpts.lineUnmatchedPunishFact);
|
||||
} else if (_rOpts.lineUnmatchedPunishFact > 1) {
|
||||
double a =
|
||||
std::round(static_cast<double>(c) * _rOpts.lineUnmatchedPunishFact);
|
||||
if (a > std::numeric_limits<uint32_t>::max())
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
c = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (!simi.fromSimilar) {
|
||||
if (_rOpts.lineNameFromUnmatchedPunishFact < 1) {
|
||||
c = std::ceil(static_cast<double>(c) *
|
||||
_rOpts.lineNameFromUnmatchedPunishFact);
|
||||
} else if (_rOpts.lineNameFromUnmatchedPunishFact > 1) {
|
||||
double a = std::round(static_cast<double>(c) *
|
||||
_rOpts.lineNameFromUnmatchedPunishFact);
|
||||
if (a > std::numeric_limits<uint32_t>::max())
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
c = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (!simi.toSimilar) {
|
||||
if (_rOpts.lineNameToUnmatchedPunishFact < 1) {
|
||||
c = std::ceil(static_cast<double>(c) *
|
||||
_rOpts.lineNameToUnmatchedPunishFact);
|
||||
} else if (_rOpts.lineNameToUnmatchedPunishFact > 1) {
|
||||
double a = std::round(static_cast<double>(c) *
|
||||
_rOpts.lineNameToUnmatchedPunishFact);
|
||||
if (a > std::numeric_limits<uint32_t>::max())
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
c = a;
|
||||
}
|
||||
}
|
||||
|
||||
_lastC = c;
|
||||
_lastFrom = from;
|
||||
}
|
||||
|
||||
uint32_t overflowCheck = c;
|
||||
|
||||
if (n && !n->pl().isTurnCycle()) {
|
||||
if (_rOpts.fullTurnPunishFac != 0 && from->getFrom() == to->getTo() &&
|
||||
from->getTo() == to->getFrom()) {
|
||||
// trivial full turn
|
||||
c += _rOpts.fullTurnPunishFac;
|
||||
|
||||
if (c <= overflowCheck) return std::numeric_limits<uint32_t>::max();
|
||||
overflowCheck = c;
|
||||
} else if (_rOpts.fullTurnPunishFac != 0 && n->getDeg() > 2) {
|
||||
// otherwise, only intersection angles will be punished
|
||||
|
||||
double ang = util::geo::innerProd(
|
||||
*n->pl().getGeom(), from->pl().backHop(), to->pl().frontHop());
|
||||
|
||||
if (ang < _rOpts.fullTurnAngle) {
|
||||
c += _rOpts.fullTurnPunishFac;
|
||||
if (c <= overflowCheck) return std::numeric_limits<uint32_t>::max();
|
||||
overflowCheck = c;
|
||||
}
|
||||
}
|
||||
|
||||
// turn restriction cost
|
||||
if (_rOpts.turnRestrCost > 0 && from->pl().isRestricted() &&
|
||||
!_res.may(from, to, n)) {
|
||||
c += _rOpts.turnRestrCost;
|
||||
if (c <= overflowCheck) return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
LineSimilarity ExpoTransWeight::CostFunc::transitLineSimi(
|
||||
const trgraph::Edge* e) const {
|
||||
if (_rAttrs.shortName.empty() && _rAttrs.lineFrom.empty() &&
|
||||
_rAttrs.lineTo.empty())
|
||||
return {true, true, true};
|
||||
|
||||
LineSimilarity best = {false, false, false};
|
||||
for (const auto* l : e->pl().getLines()) {
|
||||
auto simi = _rAttrs.simi(l);
|
||||
if (simi.nameSimilar && simi.toSimilar && simi.fromSimilar) return simi;
|
||||
if (best < simi) best = simi;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
double ExpoTransWeight::weight(uint32_t c, double d, double t0, double d0,
|
||||
const RoutingOpts& rOpts) {
|
||||
UNUSED(t0);
|
||||
UNUSED(d);
|
||||
UNUSED(d0);
|
||||
return rOpts.transitionPen * static_cast<double>(c) / 10.0;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t ExpoTransWeight::invWeight(double c, const RoutingOpts& rOpts) {
|
||||
return std::round((c / rOpts.transitionPen) * 10);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t ExpoTransWeight::maxCost(double tTime, const RoutingOpts& rOpts) {
|
||||
// abort after 3 times the scheduled time, but assume a min time of
|
||||
// 1 minute!
|
||||
return std::ceil(fmax(tTime, 60) * 3 * rOpts.lineUnmatchedPunishFact *
|
||||
rOpts.lineNameToUnmatchedPunishFact *
|
||||
rOpts.lineNameFromUnmatchedPunishFact * 10);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
||||
// _____________________________________________________________________________
|
||||
double NormDistrTransWeight::weight(uint32_t cs, double d, double t0, double d0,
|
||||
const RoutingOpts& rOpts) {
|
||||
UNUSED(d);
|
||||
UNUSED(d0);
|
||||
UNUSED(rOpts);
|
||||
|
||||
double t = static_cast<double>(cs) / 10.0;
|
||||
|
||||
// standard deviation of normal distribution
|
||||
double standarddev = 1;
|
||||
|
||||
// no backwards time travel!
|
||||
if (t0 < 0) return std::numeric_limits<double>::infinity();
|
||||
|
||||
// always assume it takes at least 10 seconds to travel
|
||||
t0 = fmax(10, t0);
|
||||
|
||||
double cNorm = (t / t0 - 1) / standarddev;
|
||||
double normWeight = cNorm * cNorm;
|
||||
|
||||
double expWeight = ExpoTransWeight::weight(cs, d, t0, d0, rOpts);
|
||||
|
||||
return normWeight + expWeight;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t NormDistrTransWeight::invWeight(double c, const RoutingOpts& rOpts) {
|
||||
UNUSED(rOpts);
|
||||
UNUSED(c);
|
||||
|
||||
throw(std::runtime_error("Cannot apply inv weight to DistDiffTransWeight"));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
||||
// _____________________________________________________________________________
|
||||
double DistDiffTransWeight::weight(uint32_t c, double d, double t0, double d0,
|
||||
const RoutingOpts& rOpts) {
|
||||
UNUSED(t0);
|
||||
UNUSED(c);
|
||||
// double mean = 250; // expectation value of 250 meters for buses
|
||||
// double lambda = 1.0 / mean;
|
||||
|
||||
double w = fabs(d - d0);
|
||||
|
||||
return rOpts.transitionPen * w;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t DistDiffTransWeight::invWeight(double c, const RoutingOpts& rOpts) {
|
||||
UNUSED(rOpts);
|
||||
UNUSED(c);
|
||||
|
||||
throw(std::runtime_error("Cannot apply inv weight to DistDiffTransWeight"));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
uint32_t DistDiffTransWeight::maxCost(double tTime, const RoutingOpts& rOpts) {
|
||||
UNUSED(tTime);
|
||||
UNUSED(rOpts);
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue