#pragma once
#include <config.h>
#include <vector>
#include <map>
template<class R, class E, class V>
class LogitCalculator : public RouteCostCalculator<R, E, V> {
public:
LogitCalculator(const double beta, const double gamma,
const double theta) : myBeta(beta), myGamma(gamma), myTheta(theta) {}
virtual ~LogitCalculator() {}
void setCosts(R* route, const double costs, const bool ) const {
route->setCosts(costs);
}
void calculateProbabilities(std::vector<R*> alternatives, const V* const veh, const SUMOTime time) {
const double theta = myTheta >= 0 ? myTheta : getThetaForCLogit(alternatives);
const double beta = myBeta >= 0 ? myBeta : getBetaForCLogit(alternatives);
const double t = STEPS2TIME(time);
if (beta > 0) {
for (const R* const pR : alternatives) {
double lengthR = 0;
const std::vector<const E*>& edgesR = pR->getEdgeVector();
for (const E* const edge : edgesR) {
lengthR += edge->getTravelTime(veh, t);
}
double overlapSum = 0;
for (const R* const pS : alternatives) {
double overlapLength = 0.;
double lengthS = 0;
for (const E* const edge : pS->getEdgeVector()) {
lengthS += edge->getTravelTime(veh, t);
if (std::find(edgesR.begin(), edgesR.end(), edge) != edgesR.end()) {
overlapLength += edge->getTravelTime(veh, t);
}
}
overlapSum += pow(overlapLength / sqrt(lengthR * lengthS), myGamma);
}
myCommonalities[pR] = beta * log(overlapSum);
}
}
for (R* const pR : alternatives) {
double weightedSum = 0;
for (const R* const pS : alternatives) {
weightedSum += exp(theta * (pR->getCosts() - pS->getCosts() + myCommonalities[pR] - myCommonalities[pS]));
}
pR->setProbability(1. / weightedSum);
}
}
private:
double getBetaForCLogit(const std::vector<R*> alternatives) const {
double min = std::numeric_limits<double>::max();
for (const R* const pR : alternatives) {
const double cost = pR->getCosts() / 3600.;
if (cost < min) {
min = cost;
}
}
return min;
}
double getThetaForCLogit(const std::vector<R*> alternatives) const {
double sum = 0.;
double diff = 0.;
double min = std::numeric_limits<double>::max();
for (const R* const pR : alternatives) {
const double cost = pR->getCosts() / 3600.;
sum += cost;
if (cost < min) {
min = cost;
}
}
const double meanCost = sum / double(alternatives.size());
for (const R* const pR : alternatives) {
diff += pow(pR->getCosts() / 3600. - meanCost, 2);
}
const double cvCost = sqrt(diff / double(alternatives.size())) / meanCost;
if (cvCost > 0) {
return 3.1415926535897932384626433832795 / (sqrt(6.) * cvCost * (min + 1.1)) / 3600.;
}
return 1. / 3600.;
}
private:
const double myBeta;
const double myGamma;
const double myTheta;
std::map<const R*, double> myCommonalities;
private:
LogitCalculator& operator=(const LogitCalculator& s);
};