import numpy as np
from scipy.optimize import minimize
from functools import lru_cache
import scipy
k = 3
m = 420
p = 6
def Evaluate(cs, reps=200):
assert m%p == 0
C = [[cs[outer + inner] for inner in range(p-1, -1, -1) for _ in range(m//p)] for outer in range(0, len(cs)-1,p)]
C = np.array(C)
@lru_cache(maxsize=None)
def dp(b, j, i, l):
if j>=k or i>=m:
return b
if l<=C[j, i]:
ans = np.exp(-C[j,i]/m)*dp(b, j, i+1, l) + (1-np.exp(-C[j,i]/m))*(
l/C[j, i] * dp(1, j+1, i+1, l) + (C[j, i]-l)/C[j, i] * dp(0, j+1, i+1, l))
else:
ans = np.exp(-C[j,i]/m)*dp(b, j, i+1, l) + (1-np.exp(-C[j,i]/m))*dp(1, j+1, i+1, l)
return ans
def cost(l):
l = l[0]
return dp(0, 0, 0, l)/(1-np.exp(-l))
"""Run global optimization on cost in the range (0, max(C)]"""
res = scipy.optimize.shgo(cost, bounds=[(0.000000000000001,C.max())], iters=10, options={'disp':False, 'f_tol':1e-9})
competitive_ratio = min(res.fun, 1-np.exp(-sum(C[0])/m)) #do not forget l'>max(C) case
"As a sanity check, make sure that global minimizer succeeded"
ls = np.linspace(0.000000000000001, C.max(), reps)
ans = 1
for l in ls:
ans = min(ans, cost([l]))
assert res.fun <= ans
"""End of sanity check"""
return competitive_ratio
cs0 = [3.64589394e+00, 3.58116098e+00, 2.03323633e+00, 1.93319241e+00,
1.15603731e+00, 9.92652855e-01, 6.10147568e-01, 3.94833386e-01,
2.41093283e-01, 1.36659577e-01, 4.80563875e-02, 2.83455285e-02,
8.39298670e-02, 1.91858842e-02, 0.00133218127, 1.33218127e-03,
1.05769060e-03, 1.05769044e-03]
competitive_ratio = Evaluate(cs0, reps=5000) #Takes around a minute
print(competitive_ratio)
aW1wb3J0IG51bXB5IGFzIG5wCmZyb20gc2NpcHkub3B0aW1pemUgaW1wb3J0IG1pbmltaXplCmZyb20gZnVuY3Rvb2xzIGltcG9ydCBscnVfY2FjaGUgCmltcG9ydCBzY2lweQoKCmsgPSAzCm0gPSA0MjAKcCA9IDYKCmRlZiBFdmFsdWF0ZShjcywgcmVwcz0yMDApOgogICAgYXNzZXJ0IG0lcCA9PSAwCiAgICAKICAgIEMgPSBbW2NzW291dGVyICsgaW5uZXJdIGZvciBpbm5lciBpbiByYW5nZShwLTEsIC0xLCAtMSkgZm9yIF8gaW4gcmFuZ2UobS8vcCldIGZvciBvdXRlciBpbiByYW5nZSgwLCBsZW4oY3MpLTEscCldCiAgICBDID0gbnAuYXJyYXkoQykKICAgIAogICAgQGxydV9jYWNoZShtYXhzaXplPU5vbmUpCiAgICBkZWYgZHAoYiwgaiwgaSwgbCk6CiAgICAgICAgaWYgaj49ayBvciBpPj1tOgogICAgICAgICAgICByZXR1cm4gYgoKICAgICAgICBpZiBsPD1DW2osIGldOgogICAgICAgICAgICBhbnMgPSBucC5leHAoLUNbaixpXS9tKSpkcChiLCBqLCBpKzEsIGwpICsgKDEtbnAuZXhwKC1DW2osaV0vbSkpKigKICAgICAgICAgICAgICAgIGwvQ1tqLCBpXSAqIGRwKDEsIGorMSwgaSsxLCBsKSArIChDW2osIGldLWwpL0NbaiwgaV0gKiBkcCgwLCBqKzEsIGkrMSwgbCkpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgYW5zID0gbnAuZXhwKC1DW2osaV0vbSkqZHAoYiwgaiwgaSsxLCBsKSArICgxLW5wLmV4cCgtQ1tqLGldL20pKSpkcCgxLCBqKzEsIGkrMSwgbCkKICAgICAgICByZXR1cm4gYW5zCgogICAgZGVmIGNvc3QobCk6CiAgICAgICAgbCA9IGxbMF0KICAgICAgICByZXR1cm4gIGRwKDAsIDAsIDAsIGwpLygxLW5wLmV4cCgtbCkpCiAgICAKICAgICIiIlJ1biBnbG9iYWwgb3B0aW1pemF0aW9uIG9uIGNvc3QgaW4gdGhlIHJhbmdlICgwLCBtYXgoQyldIiIiCiAgICByZXMgPSBzY2lweS5vcHRpbWl6ZS5zaGdvKGNvc3QsIGJvdW5kcz1bKDAuMDAwMDAwMDAwMDAwMDAxLEMubWF4KCkpXSwgaXRlcnM9MTAsICBvcHRpb25zPXsnZGlzcCc6RmFsc2UsICdmX3RvbCc6MWUtOX0pCiAgICAKICAgIGNvbXBldGl0aXZlX3JhdGlvID0gbWluKHJlcy5mdW4sIDEtbnAuZXhwKC1zdW0oQ1swXSkvbSkpICNkbyBub3QgZm9yZ2V0IGwnPm1heChDKSBjYXNlCgogICAgIkFzIGEgc2FuaXR5IGNoZWNrLCBtYWtlIHN1cmUgdGhhdCBnbG9iYWwgbWluaW1pemVyIHN1Y2NlZWRlZCIKICAgIGxzID0gbnAubGluc3BhY2UoMC4wMDAwMDAwMDAwMDAwMDEsIEMubWF4KCksIHJlcHMpCiAgICBhbnMgPSAxCiAgICBmb3IgbCBpbiBsczoKICAgICAgICBhbnMgPSBtaW4oYW5zLCBjb3N0KFtsXSkpCiAgICAKICAgIGFzc2VydCByZXMuZnVuIDw9IGFucwogICAgIiIiRW5kIG9mIHNhbml0eSBjaGVjayIiIgogICAgCiAgICByZXR1cm4gY29tcGV0aXRpdmVfcmF0aW8KCmNzMCA9IFszLjY0NTg5Mzk0ZSswMCwgMy41ODExNjA5OGUrMDAsIDIuMDMzMjM2MzNlKzAwLCAxLjkzMzE5MjQxZSswMCwKICAgICAgIDEuMTU2MDM3MzFlKzAwLCA5LjkyNjUyODU1ZS0wMSwgNi4xMDE0NzU2OGUtMDEsIDMuOTQ4MzMzODZlLTAxLAogICAgICAgMi40MTA5MzI4M2UtMDEsIDEuMzY2NTk1NzdlLTAxLCA0LjgwNTYzODc1ZS0wMiwgMi44MzQ1NTI4NWUtMDIsCiAgICAgICA4LjM5Mjk4NjcwZS0wMiwgMS45MTg1ODg0MmUtMDIsIDAuMDAxMzMyMTgxMjcsIDEuMzMyMTgxMjdlLTAzLAogICAgICAgMS4wNTc2OTA2MGUtMDMsIDEuMDU3NjkwNDRlLTAzXQoKCmNvbXBldGl0aXZlX3JhdGlvID0gRXZhbHVhdGUoY3MwLCByZXBzPTUwMDApICNUYWtlcyBhcm91bmQgYSBtaW51dGUgCgpwcmludChjb21wZXRpdGl2ZV9yYXRpbykK