Link graph: Change distance scaling algorithm in demand scaler

Fix erratic scaling and increase effect at large setting values
pull/684/head
Jonathan G Rennison 1 month 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]); int32_t supply = scaler.EffectiveSupply(job[from_id], job[to_id]);
assert(supply > 0); assert(supply > 0);
/* Scale the distance by mod_dist around max_distance */ constexpr int32_t divisor_scale = 16;
int32_t distance = this->max_distance - (this->max_distance -
(int32_t)DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY())) * int32_t scaled_distance = this->base_distance;
this->mod_dist / 100; 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 */ /* Scale the accuracy by distance around accuracy / 2 */
int32_t divisor = this->accuracy * (this->mod_dist - 50) / 100 + const int32_t divisor = divisor_scale + ((this->accuracy * scaled_distance * divisor_scale) / (this->base_distance * 2));
this->accuracy * distance / this->max_distance + 1; assert(divisor >= divisor_scale);
assert(divisor > 0);
uint demand_forw = 0; uint demand_forw = 0;
if (divisor <= supply) { if (divisor <= (supply * divisor_scale)) {
/* At first only distribute demand if /* At first only distribute demand if
* effective supply / accuracy divisor >= 1 * effective supply / accuracy divisor >= 1
* Others are too small or too far away to be considered. */ * 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) { } else if (++chance > this->accuracy * num_demands * num_supplies) {
/* After some trying, if there is still supply left, distribute /* After some trying, if there is still supply left, distribute
* demand also to other nodes. */ * demand also to other nodes. */
@ -410,7 +413,7 @@ void DemandCalculator::CalcMinimisedDistanceDemand(LinkGraphJob &job, const std:
* @param job Job to calculate the demands for. * @param job Job to calculate the demands for.
*/ */
DemandCalculator::DemandCalculator(LinkGraphJob &job) : 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(); const LinkGraphSettings &settings = job.Settings();
CargoID cargo = job.Cargo(); CargoID cargo = job.Cargo();
@ -419,8 +422,7 @@ DemandCalculator::DemandCalculator(LinkGraphJob &job) :
this->mod_dist = settings.demand_distance; this->mod_dist = settings.demand_distance;
if (this->mod_dist > 100) { if (this->mod_dist > 100) {
/* Increase effect of mod_dist > 100 */ /* Increase effect of mod_dist > 100 */
int over100 = this->mod_dist - 100; this->mod_dist = 100 + ((this->mod_dist - 100) * 4);
this->mod_dist = 100 + over100 * over100;
} }
if (settings.GetDistributionType(cargo) == DT_MANUAL) return; if (settings.GetDistributionType(cargo) == DT_MANUAL) return;

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

Loading…
Cancel
Save