'How divide pie with constraints
How divide a pie with constraints?
Hi I have rounded pie and would like to divide it, but am not able to figure out how to do it.
I have four friends: A,B,C,D I want to divide pie based on how I like them, so based on opinion.
Slice sizes:
A= 1/22 of pie B= 10/22 of pie C= 1/22 of pie D= 10/22 of pie.
How to divide the pie when there are some constrains? Like B will tell me he wants < 10% of whole pie and D must have at least 85% of pie. A,C don't care.
In this case I can say ok, so D wants at least 85% 22*0.85= 18.7 so he will get this. Now I have only rest of the pie 22-18.7= 3.3 = 15% to divide and I don't want to give bigger slice than 10% to B. And I want still apply the ratios I proposed but only on rest of the pie as D must have at least 85%.
I think the ratios should be now applied after constrains are resolved.
A has no constraint so he can get from 0-100%
B wants 0-10%
C has no constraints 0-100%
D wants at least 85-100%
I can apply the ratios on slices under constrains like when B wants 0-10% then I can say the ratio will have influence to the size between 0-10% and for D will the ratio influence size (85%-100%).
| friends: | A | B | C | D |
|constraints:| | <=0.1 | >=0.85 | |
|ranges: | 0 to 1 | 0 to 0.1 | 0.85 to 1 | 0 to 1 |
|ratios: | 1/22 | 10/22 | 1/22 | 10/22 |
Hopefully is the problem understandable. At the end I want to have whole pie divided among ABCD with not violated constrains, and with somehow applied ratios.
Solution 1:[1]
Let me propose a formalization of this problem as a quadratic program. Let x be the desired result. We want to minimize the L2 norm of x/ratio (element-wise) subject to lower ? x ? upper (element-wise) and xยท1 = 1.
The idea behind this objective is that, by examining the optimality conditions, we can show that there exists some scalar z such that x = median(lower, ratio z, upper).
Below is some very poorly tested Python 3 code to approximately solve this quadratic program.
from fractions import Fraction
ratio = [1, 10, 2, 10]
lower = [0, 0, 0, 85]
upper = [100, 10, 100, 100]
# Want to minimize the L2 norm of x / ratio subject to lower <= x <= upper and
# sum(x) == 100
# Validation
assert 0 < len(ratio) == len(lower) == len(upper)
assert all(0 < r for r in ratio)
assert all(0 <= l <= u <= 100 for (l, u) in zip(lower, upper))
assert sum(lower) <= 100 <= sum(upper)
# Binary search
n = len(ratio)
critical = sorted(
{Fraction(bound[i], ratio[i]) for bound in [lower, upper] for i in range(n)}
)
a = 0
b = len(critical)
while b - a > 1:
m = (a + b) // 2
z = critical[m]
if sum(sorted([lower[i], ratio[i] * z, upper[i]])[1] for i in range(n)) <= 100:
a = m
else:
b = m
x = [0] * n
z = critical[a]
divisor = 0
for i in range(n):
value = ratio[i] * z
if value < lower[i]:
x[i] = lower[i]
elif upper[i] <= value:
x[i] = upper[i]
else:
divisor += ratio[i]
dividend = 100 - sum(x)
for i in range(n):
if lower[i] <= ratio[i] * z < upper[i]:
x[i] = Fraction(ratio[i], divisor) * dividend
print(x)
Output:
[Fraction(5, 3), 10, Fraction(10, 3), 85]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
