osu-performance
osu-performance copied to clipboard
lengthBonus as a Summation of Difficulty Instead of Object Count
Hello,
In collaboration with MBmasher, I present a new solution to the length problem.
The Problem Currently the algorithm addresses length as the total object count of a map. While this idea certainly has merit, it has several problems. For example, a 2 minute stream map that has lots of 1/4th rhythm can be treated as longer than a 5 minute jump map simply due to the object count being more dense. In addition, the difficulty of these objects are not assessed. A map that has a relatively consistent difficulty would get the same length bonus as a map that has difficulty spikes assuming the object count and other factors were equal.
Thus, something new is needed.
The Approach / The Math In order to properly balance length, a system that assesses the aggregate difficulty of a map respective to the star rating is needed. To make this a bit more visual for those who aren't seeing where I'm going with this, here are some graphs that display the difficulty curves of both speed.cs and aim.cs
http://puu.sh/BNTOR/cf7fa8a2b2.png http://puu.sh/BNTPh/cd6a05b751.png
With these images, it should be clear what I intend to do. By summing up the area under the curve, we can give reward for length not only in terms of real time, but also balance for the difficulty of the section. Without any more delay, the math for this suggestion is shown below.
Formal: http://puu.sh/BNTWD/e5090554ca.png Code:
for strain in strains:
total += strain ^ d
length_bonus = -c + b * ((2 + log10(aim_total + speed_total)) / (2 + log10(stars)) - 1)
Where strain in strains refers to the sum / calculation for both aim_total and speed_total and stars
In essence, this function takes the log of the aggregate difficulty with the log base being the star rating of the map (as I'm using the formula log_x(y) = log (y) / log(x)). This makes it so length is rewarded regardless of the star rating. Some people may have some questions as to why I have 2+log etc. but for the most part these constants are to prevent huge adverse scaling for low SR maps. With my testing that I have done, the following values have been tested and I believe produce satisfactory results.
b= 1.6
c=-1.28
d=1.12
I will say that the only major issue I have with this method currently is the slightly too large buff for normal and hard maps (because these type of maps don't spike at all, so they are buffed in comparison). That being said, the issues are minor compared to the benefits.
Some Results Ah yes the juicy part that everyone cares about. I'm a bit concerned with the calculator that we developed to do the testing as there are a few anomalies, so some values might be slightly inaccurate. (I apologize for the small sample size). Please note that these values are still subject to change.
Within Temptation - The Unforgiven[Marathon] https://puu.sh/BNUBj/255ac14540.png Fairy FORE - Vivid[Insane] https://puu.sh/BNUBM/583c3a33b5.png Will Stetson - Harumachi Clover [Oh no!] +DT http://puu.sh/BNVvK/64b1959c7e.png Will Stetson - Harumachi Clover [Oh no!] https://puu.sh/BNUFw/d1aac4c924.png VINXIS - Sidetracked Day[THREE DIMENSIONS] +HR http://puu.sh/BNVB6/c2378d6cb4.png MuryokuP - Sweet Sweet Cendrillon Drug[Normal] https://puu.sh/BNVbx/39f1d87226.png MuryokuP - Sweet Sweet Cendrillon Drug[Cendrillon] https://puu.sh/BNVbe/62217919a5.png Imperial Circus Dead Decadence - Uta[Himei] +HR https://puu.sh/BNUWU/ecdeab1163.png Yamajet feat. Hiura Masako - Sunglow[Melody] http://puu.sh/BNVFx/3894582b87.png Yamajet feat. Hiura Masako - Sunglow[Melody] +DT http://puu.sh/BNVGz/238f09cb50.png GYZE - HONESTY[DISHONEST] +HR https://puu.sh/BNUVB/2ccf2a7da0.png GYZE - HONESTY[DISHONEST] http://puu.sh/BNVIu/93fc534305.png Fujijo Seitokai Shikkou-bu - Best FriendS (GoldenWolf)[Extreme] http://puu.sh/BNVRr/df180fdef9.png Fujijo Seitokai Shikkou-bu - Best FriendS (GoldenWolf)[Extreme] +DT http://puu.sh/BNVSk/042ead7be8.png
The astute among you all might have realize that DT universally causes the lengthBonus to be reduced. This is indeed intended and one of the best features of this algorithm: lengthBonus varies across mods. In fact, DT causes the bonus to lower and HT causes the bonus to raise universally.
Conclusion While these values aren't all perfect, I believe them to be leaps and bounds better than the current system. In the coming days MBmasher will likely release an updated calculator for those who are interested in testing some values on their own.
With that all said, I hope you all are interested in pursuing this change. Hopefully an official PR can be produced and testing can begin on the official code soon. Thank you for reading and remember to drop a :+1: if you like the change!
It's true that short maps with DT (+HD) are somewhat overweighted, but I think the current math nerfs them a bit too hard.
I like the idea of this rebalance. Researched very well. I pray that peppy will actually see this, and not ignore it like he does with actually good suggestions.
How are you using lengthBonus to determine the difficulty of the map? I.e. how are you factoring it into the star rating? Furthermore, if it's also supposed to be a completely separate difficulty attribute alongside aim/speed, is there a similar formula for pp that you can provide?
Right now I basically have:

Where total strain is the summation of exponentiated strains, and difficulty value is the summation of weighted strains. As you can see I've just added it into the final SR, but idk if that's what you intend.
Also, you mention stars in the code but the sum of weighted strains as per your formula. Which one is correct? Because SR is effectively the sum of scaled weighted strains.
Also one thing I noticed as part of your formula is that you weigh the first strain by (.9)^1, where it's actually (.9)^0. Probably doesn't have much of an effect, just a discrepancy to note.
lengthBonus will not affect the SR of the map, it'll only affect the pp of it
aim_total and speed_total refer to the weighted strains BEFORE scaling, while stars refers to TOTAL star rating AFTER scaling
What about this map? https://osu.ppy.sh/beatmapsets/429411/#osu/939197
Ah I see, so this is a pp processor implementation that essentially requites two new attributes.
Is there any way to adjust the bonus relative to the length of the whole map? Maybe changing the 2 from 2+log into a constant or something similar. Edit: just to be clear, I mean changing it from 2+log( to a+log(, where a is a constant like b, c, and d. The reason I bring this up is because of this:
In fact, DT causes the bonus to lower and HT causes the bonus to raise universally.
I personally have no issues with this result, but I think the ability to fine-tune the extent to which this happens would make the algorithm much better for the long term. You mentioned that the algorithm buffs normal/hard maps too much, so if I understand the purpose of that 2 correctly, changing this value could help fix the problem.
The length bonus function is not a monotone function (as a set function), which is a desired property
We can regard length bonus function as a multi-set function or collection function which intakes a collection of difficulty value and output one real value.
Basically, we want the length bonus function to have the property that:
If
, then
In other words, if we add any chunk to a beatmap, the length bonus should not decrease.
But the function you propose violates this property
I quickly implemented it as
function func(arr, c, b, d) {
const seq = arr.sort().reverse();
const total = Math.log10(seq.reduce((s, a) => s + Math.pow(a, d), 0));
const sr= Math.log10(seq.reduce(([s, mul], a) => [s + mul * a, mul * 0.9], [0, 0.9])[0]);
return c + b*((2+ total)/(2 + sr) - 1);
}
And we have
> func([1,1,1,1], 1.28, 1.6, 1.12)
1.3515534994438259
> func([1,1,1,1,3], 1.28, 1.6, 1.12)
1.3418421687793718
So I don't think it is a good idea.
In fact, I was checking another property I think the function should have while found your function doesn't satisfy the basic monotonicity. I think the function should also satisfy submodular property which says:
If , and let
be any chunk, then
In other words, suppose we have a short map
, and a long map
induced by adding more chunks to the short map. If we add the same new chunk
to the two maps, the length bonus gain to the short map should be no less than the gain to the long map. i.e., adding a chunk adds more length bonus to the short map.
I believe designer of length bonus function should have these two properties in mind.
The effect of your first point you're observing was entirely intended. As the bottom function you display includes a 3 (aka the new hardest point of the map), the star rating increases and would cause the length bonus to decrease. This is designed so that maps with difficulty curves that spike don't get overly high length bonuses because the sections compared to the diff spikes would be so easy that they would not affect the difficulty to FC for the player capable of FCing the spike.
As for the second property, a short map obviously would receive more bonus for the section being added. If it didn't, then length would scale infinitely and maps like The Unforgiven would give 1000pp.
I don't see why these properties would be desired.
While I agree that the length bonus itself does not absolutely need to be monotonic when adding hit objects to the end or beginning of a map, being so would ensure that also the final pp value itself is monotonic, which must be the case. Otherwise the algorithm is broken.
If additional stuff is added to the end or beginning of a map, then the pp for SSing it should never, ever decrease.
If the length bonus is not monotonic, (as your suggested algorithm is not), then you need to be extra careful to make the final pp value still is. Ideally with a formal proof, because this absolutely must not go wrong.
Second to Tom94. The motivation that I hope length bonus function to be monotone and submodular is because in that case, the final pp function is naturally monotone and submodular.
Now let me elaborate submodular. This property is desired because it ensures that, when you slap a new section in your map, it should have larger impact on short map than on long map. Otherwise, the pp gained from a map will be super-linear to its length. In that case, I guess we will see new meta like length filler or something like that.
The only case in which the additional stuff being added to the end of the map would cause the lengthBonus to lower would be if the additional stuff added to the end of the map increases the star rating, thereby increasing the log base. This would therefore theoretically raise the overall pp even though the lengthBonus itself has decreased. I'll see if I can either formally prove such a property exists or modify the algorithm until such a result is achieved.
Would it be possible to scale strain for each subsection off of the maximum aim/speed up to the subsection compared to the aim/speed of the current subsection?
It'd allow for maps with a difficulty spike in the middle to still maintain the amount of pp from the beginning of the map to that point, but it'd lessen the pp gained afterwards (but still be greater than the amount from the beginning to the diff spike)
Is it not the case where length is already implicitly accounted for in the algorithm (since you're summing the strains + a decay factor)? Looks like to me, you could reduce the decay if you wanted to explictly benefit longer maps and remove the length bonus altogether.
This would require re-tuning of all parameters though, but might be the best way to go?
I personally suggest looking at the class of Archimedean t-norm or Archimedean t-conorm functions. I think it is easy to turn a t-conorm function to a set function, and we will naturally have monotonicity. Apart from that, we will also naturally have null-additive. But it is a large class though and many of such functions are too trivial. So it is just a personal suggestion.
Is there a chance that this will be implemented in Catch too? I feel like it might partially fix maps like Image Material
Any updates?
When?
When it's ready.
Hello,
Good news! Updates! While there is still balancing and testing to be done, I believe I have an amended algorithm that should help solve the following issues.
Separation of lengthBonus
Instead of the previous suggestion where both speed and aim scale by the same lengthBonus that encompasses both skills, the new algorithm will split lengthBonus into two separate bonuses that can be balanced separately (as these two curves have different properties). In addition, this will prevent cases where maps with highly consistent aim difficulty inaccurately scale a speed spike.
Universal Star Rating Balance In the previous version of this algorithm, I noticed an issue regarding lengthBonus and a maps star rating. Imagine two difficulties with perfectly consistent difficulty curves, where one is 2 stars and the other is 5 stars. Under the previous algorithm, these two maps would have different bonuses (in fact, the easier map would get more of a bonus). Now, the bonus is perfectly balanced to be independent of the star rating of the map.
Spikes Do Not Lower PP
There were some previous fears that since lengthBonus can lower in value when a new section is added (a property that is still maintained in this version because it is desired), the PP of a map may also lower when such a new section is added. From my testing so far, it is not possible for the PP to drop as a result of adding a new section to a map. The only case in which lengthBonus drops is when a new spike is added to the difficulty. This spike causes the star rating of the map to increase thereby lowering the weight of the other sections of the map as compared to the star rating. Thus, while the lengthBonus decreases, the maps star rating must rise as a result. However, since the star rating has increased, the net PP change would be positive from such a section being added. Spikes should and will always outweigh the effects of the lengthBonus's change from the new section.
Expect an update to the original post sometime in the future (soon) with the amended algorithm and a new data supporting it's implementation.
Thank you for reading,
Xexxar
(For those who care about the math, log(aggregateSR / scaledAggregateSR) did the trick. Using a separate log base caused more problems than it was worth (aggregateSR is the sum of all difficulty sections, scaledAggregateSR is the same sum with the .9^n scaling factor))
I actually support this change, though I'm doubting some of the vague parts of your latest comment, such as
Under the previous algorithm, these two maps would have different bonuses (in fact, the easier map would get more of a bonus). Now, the bonus is perfectly balanced to be independent of the star rating of the map.
I'm not sure how the bonus balances out. If the easier map gets the bonus in the previous algorithm, that would make it an issue. However, being independent of the star rating doesn't sound like it will fix it?
I'm not sure how the bonus balances out. If the easier map gets the bonus in the previous algorithm, that would make it an issue. However, being independent of the star rating doesn't sound like it will fix it?
The sr already scales the pp itself, and therefore the absolute increase in pp will be higher for harder maps, the percentage stays the same. The percentage shouldn't be different as it is just meant to reflect consistent difficulty, no matter whether the map is high or low sr
Great to see we're getting updates on this! :)
Here's some sample data with this change:
Original (reference, no changes): http://original.smgi.me
This change + speed bonus http://xexxar-lb-sb.smgi.me
Note that I've been told the length bonus and speed bonus changes are supposed to be included together.
I would like to introduce an amended version of the algorithm that no longer has a minimum value.
In my testing, d=1.2, beta = .45, c = .38 seem to work very well by keeping the changes in a ~85%-110% range. Overall I would say that stream maps are going to see a pretty sizable nerf but this is to be expected due to object count no longer being used for length. I tried to balance TV size maps so there would be no change for them.
At this point I think this is ready to be merged. Other than minor balancing I believe this is as good as it can get. As always, if there are questions let me know.
Note that the formula can be rewritten as follows:
This shows the relationship to the initial proposal. The difference is that the ratio is brought into the log instead of outside. Therefore, the log term will be negative when the thing inside of it is less than 10. I assume that c and beta have been checked such that the length bonus as a whole will never be negative, but I'm sure we don't want a negative length bonus.
Also, am I correct in assuming that the speed and length bonus will be implemented simultaneously, or will they be done sequentially?
EDIT: My reasoning is incorrect. log is negative when the input is less than 1, so if the ratio of summations is positive (which is always true). But this still means there is a theoretical minimum length bonus equal to c.
Note that the formula can be rewritten as follows:
This shows the relationship to the initial proposal. The difference is that the ratio is brought into the log instead of outside. Therefore, the log term will be negative when the thing inside of it is less than 10. I assume that c and beta have been checked such that the length bonus as a whole will never be negative, but I'm sure we don't want a negative length bonus. Also, am I correct in assuming that the speed and length bonus will be implemented simultaneously, or will they be done sequentially?
I am pretty sure \log(1+x) is non-negative when x \geq 0
@johnmave126 Thanks. Fixed my comment accordingly.
As a note, I've split out the changes so you can find the test website for these changes at:
https://xexxar-lb.smgi.me
Which does not include the speed bonus changes.