Objective: Due to external force majeure factors, a company needs to reduce the bonus of some employees who have excessively high bonuses
Condition:
1. A compression interval is stipulated, and the compressed bonus must be within this interval
2. If a> B before compression, a> B after compression
3. Try to compress the same person’s bonus as much as possible this year
The original data
bonus_2020_dict = { # 2020 bonus
'a': 117800.'b': 115800.'c': 47360.'d': 51500.'e': 0.'f': 99348.'g': 0.'h': 104348.'i': 117466.'j': 58999.'k': 0.'l': 11754
}
bonus_2021_dict = { # 2021 prize money
'a': 127980.'b': 187955.'c': 112450.'d': 104048.'e': 96059.'f': 104473.'g': 113087.'h': 149459.'i': 138412.'j': 164352.'k': 100891.'l': 104219,
}
top_limit = 134540 # Compressed maximum value
down_limit = 67270 The minimum value after compression
Copy the code
Solution:
Thinking a
I started out thinking about fitting a line, which is the easiest way to do it,
Assuming the slope K and constant B such that Max (bonus_2021) * K + B = top_limit,
Figure out everyone’s compressed bonus = bonus_2021
But I traversed the slopes of (0 to 1) with 1% accuracy, and found that no combination of K and B satisfies all three conditions
It’s not that simple…
Redefining the interval
The error of the previous scheme is that the compressed value is lower than the value of 2020, which is too much compression. After the compression of condition 3, the bonus of the same person this year should be as much as possible higher than that of last year. It is found that:
The actual range is not from down_limit to top_limit
Max (down_limit, bonus_2020) ~ min(top_limit, bonus_2021)
To make it more intuitive, here’s a picture:
The value range of point A after compression is actually very small, only between 117800 and 127980, that is to say, the compression space of point A is actually only part of 127980-117800 =10180
What is this part? Here’s a simple formula:
Compression value = compressible space * compression ratio
Compression ratio = 1 – Bonus_2021 / Max (Bonus_2021)
So write the code:
max_2021 = bonus_2021_dict[max(bonus_2021_dict,key=lambda x:bonus_2021_dict[x])]
zip_bonus_dict = {}
for k,bonus_21 in bonus_2021_dict.items():
# Redefine the interval
now_down_limit = max((down_limit, bonus_2020_dict[k]))
now_top_limit = min((top_limit, bonus_21))
limit = now_top_limit - now_down_limit
Get a reduced bonus
zip_bonus = round(now_top_limit - limit * (1 - bonus_21 / max_2021))
zip_bonus_dict[k] = zip_bonus
Copy the code
I sorted the data in ascending order by bonus_2021
It can be clearly observed from the picture that the middle blue line zip_bonus2 is not monotonically increasing, which indicates that condition two is violated: a> B before compression, then A > B after compression
Cause analysis:
The lower limit of point F this year is very high because of the high bonus for point F in 2020
However, the bonus of c and G next to point F is low in 2020, and the lower limit of compressible space is low. When the compression ratio is similar to point F, the bonus will be lower than point F after compression.
So what’s the solution?
That is, c,g inherits the lower bound of F!
Then extend to all the points, after they are arranged in ascending order, the latter point can inherit the lower limit of the previous point
The code is as follows:
bonus_2021_list = list(bonus_2021_dict.items())
bonus_2021_list.sort(key=lambda x: x[1]) # Rank 2021 bonuses in ascending order
max_2021 = bonus_2021_list[-1] [1]
now_down_limit = down_limit # This value is the lower limit of each point
zip_bonus_dict = {}
for bonus_21_tuple in bonus_2021_list:
k = bonus_21_tuple[0]
bonus_21 = bonus_21_tuple[1]
Add the lower limit of the previous point to the selection
now_down_limit = max((down_limit, now_down_limit, bonus_2020_dict[k]))
The selection of the upper limit remains the same
now_top_limit = min((top_limit, bonus_21))
limit = now_top_limit - now_down_limit
zip_bonus = round(now_top_limit - limit * (1 - bonus_21 / max_2021))
zip_bonus_dict[k] = zip_bonus
Copy the code
The results are shown below:
The new yellow line meets all the criteria.
The last
This algorithm will not be adopted in the end by real needs, because the key point is that the current person’s bonus amount is related to the previous person’s bonus last year, which is a very unreasonable thing in practice
In general, this algorithm solves mathematical problems and may one day be applied to other practical problems, so it’s worth noting here
2022/3
This article uses the article synchronization assistant to synchronize