Link graph: Change distance scaling algorithm in demand scaler

Fix erratic scaling and increase effect at large setting values
tmp-jgrpp
Jonathan G Rennison 3 weeks ago
parent 3712b84d2e
commit 3d04989507

@ -308,23 +308,26 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, const std::vector<bool> &re
int32_t supply = scaler.EffectiveSupply(job[from_id], job[to_id]);
assert(supply > 0);
/* Scale the distance by mod_dist around max_distance */
int32_t distance = this->max_distance - (this->max_distance -
(int32_t)DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY())) *
this->mod_dist / 100;
constexpr int32_t divisor_scale = 16;
int32_t scaled_distance = this->base_distance;
if (this->mod_dist > 0) {
const int32_t distance = DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY());
/* Scale distance around base_distance by (mod_dist * (100 / 1024)).
* Note that this means that the distance range is always compressed because mod_dist <= 1024. */
scaled_distance = this->base_distance + (((distance - this->base_distance) * this->mod_dist) / 1024);
}
/* Scale the accuracy by distance around accuracy / 2 */
int32_t divisor = this->accuracy * (this->mod_dist - 50) / 100 +
this->accuracy * distance / this->max_distance + 1;
assert(divisor > 0);
const int32_t divisor = divisor_scale + ((this->accuracy * scaled_distance * divisor_scale) / (this->base_distance * 2));
assert(divisor >= divisor_scale);
uint demand_forw = 0;
if (divisor <= supply) {
if (divisor <= (supply * divisor_scale)) {
/* At first only distribute demand if
* effective supply / accuracy divisor >= 1
* Others are too small or too far away to be considered. */
demand_forw = supply / divisor;
demand_forw = (supply * divisor_scale) / divisor;
} else if (++chance > this->accuracy * num_demands * num_supplies) {
/* After some trying, if there is still supply left, distribute
* demand also to other nodes. */
@ -410,7 +413,7 @@ void DemandCalculator::CalcMinimisedDistanceDemand(LinkGraphJob &job, const std:
* @param job Job to calculate the demands for.
*/
DemandCalculator::DemandCalculator(LinkGraphJob &job) :
max_distance(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(MapMaxX(), MapMaxY())))
base_distance(IntSqrt(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(MapMaxX(), MapMaxY()))))
{
const LinkGraphSettings &settings = job.Settings();
CargoID cargo = job.Cargo();
@ -419,8 +422,7 @@ DemandCalculator::DemandCalculator(LinkGraphJob &job) :
this->mod_dist = settings.demand_distance;
if (this->mod_dist > 100) {
/* Increase effect of mod_dist > 100 */
int over100 = this->mod_dist - 100;
this->mod_dist = 100 + over100 * over100;
this->mod_dist = 100 + ((this->mod_dist - 100) * 4);
}
if (settings.GetDistributionType(cargo) == DT_MANUAL) return;

@ -15,9 +15,9 @@ public:
DemandCalculator(LinkGraphJob &job);
private:
int32_t max_distance; ///< Maximum distance possible on the map.
int32_t mod_dist; ///< Distance modifier, determines how much demands decrease with distance.
int32_t accuracy; ///< Accuracy of the calculation.
int32_t base_distance; ///< Base distance for scaling purposes.
int32_t mod_dist; ///< Distance modifier, determines how much demands decrease with distance.
int32_t accuracy; ///< Accuracy of the calculation.
template<class Tscaler>
void CalcDemand(LinkGraphJob &job, const std::vector<bool> &reachable_nodes, Tscaler scaler);

Loading…
Cancel
Save