My System is as follows:
Optimize the value of O_t based on each value of L_t from 1 to 240 according to the below equations.
O_t = O1+O2+O3+O4
O1= LS1+3×D
O2=3×LS2+4×S
O3=S+3×D
O4= LS4×4+7×D
L_t = LS1+LS2+LS3+LS4+LS5+LS6
L_t = (S+D)/5
Desired outputs: Values of S, D, LS1, LS2, LS3, LS4, LS5, LS6 that result in the highest possible value of O_t for each value of L_t
Constraints:
- Variable to be maximized is O_t
- LS1, LS2, LS3, LS4, LS5, LS6, S, and D must all be whole numbers.
LS1+LS2+LS3+LS4+LS5+LS6=L_tO_t=O1+O2+O3+O4- output prints optimal values of LS1, LS2, LS3, LS4, LS5, LS6, S, and D for each value of L_t
- output in the form of a table
- L_t<15 then LS1,2,3,4,5,6 cannot exceed 5 L_t<30 then LS1,2,3,4,5,6 cannot exceed 10 L_t<50 then LS1,2,3,4,5,6 cannot exceed 15 L_t<60 then LS1,2,3,4,5,6 cannot exceed 17 L_t<90 then LS1,2,3,4,5,6 cannot exceed 20 L_t<120 then LS1,2,3,4,5,6 cannot exceed 25 L_t<150 then LS1,2,3,4,5,6 cannot exceed 30 L_t<180 then LS1,2,3,4,5,6 cannot exceed 35 L_t<210 then LS1,2,3,4,5,6 cannot exceed 40 L_t<240 then LS1,2,3,4,5,6 cannot exceed 45
How I am currently attempting to solve the system of equations: Optimized brute force. Generate a list of all possible S, D, and LS1-6 values, calculate O_t, and check against the previous maximum.
My code currently works (I am assuming since has been tested on smaller numbers and works well) but takes multiple days of running to solve for any large numbers. Here is my current code optimized as much as I can.
import numpy as np
import numba as nb
from tqdm import tqdm
@nb.njit
def calculate_O(LS1, LS2, LS3, LS4, LS5, LS6, S, D):
O1 = LS1 + 3 * D
O2 = 3 * LS2 + 4 * S
O3 = S + 3 * D
O4 = LS4 * 4 + 7 * D
return O1 + O2 + O3 + O4
@nb.njit
def find_optimal_value(L_t, possible_S_values, possible_D_values):
max_O = -np.inf
max_LS1 = 0
max_LS2 = 0
max_LS3 = 0
max_LS4 = 0
max_LS5 = 0
max_LS6 = 0
max_S = 0
max_D = 0
LS1_init = 11
LS2_init = 11
LS3_init = 11
LS4_init = 11
LS5_init = 11
LS6_init = 11
S_init = 2
D_init = 0
if L_t < 15:
LS_max = 5
elif L_t < 30:
LS_max = 10
elif L_t < 50:
LS_max = 15
elif L_t < 60:
LS_max = 17
elif L_t < 90:
LS_max = 20
elif L_t < 120:
LS_max = 25
elif L_t < 150:
LS_max = 30
elif L_t < 180:
LS_max = 35
elif L_t < 210:
LS_max = 40
elif L_t < 240:
LS_max = 45
for LS1 in range(L_t + 1):
if LS1 > LS_max:
continue
if LS1 + LS1_init > 50:
continue
for LS2 in range(L_t + 1 - LS1):
if LS2 > LS_max:
continue
if LS2 + LS2_init > 50:
continue
for LS3 in range(L_t + 1 - LS1 - LS2):
if LS3 > LS_max:
continue
if LS3 + LS3_init > 50:
continue
for LS5 in range(L_t + 1 - LS1 - LS2 - LS3):
if LS5 > LS_max:
continue
if LS5 + LS5_init > 50:
continue
for LS6 in range(L_t + 1 - LS1 - LS2 - LS3 - LS5):
if LS6 > LS_max:
continue
if LS6 + LS6_init > 50:
continue
LS4 = L_t - LS1 - LS2 - LS3 - LS5 - LS6
if LS4 > LS_max:
continue
if LS4 + LS4_init > 50:
continue
for S in possible_S_values:
D = 5 * L_t - S
if D < 0:
break
if S > 5 * L_t:
continue
if LS4 >= 0 and S >= 0 and LS1 + LS2 + LS3 + LS4 + LS5 + LS6 == L_t:
O = calculate_O(LS1+LS1_init, LS2+LS2_init, LS3+LS3_init, LS4+LS4_init, LS5+LS5_init, LS6+LS6_init, S+S_init, D+D_init)
if O > max_O:
max_O = O
max_LS1 = LS1
max_LS2 = LS2
max_LS3 = LS3
max_LS4 = LS4
max_LS5 = LS5
max_LS6 = LS6
max_S = S
max_D = D
return (max_LS1+LS1_init, max_LS2+LS2_init, max_LS3+LS3_init, max_LS4+LS4_init, max_LS5+LS5_init, max_LS6+LS6_init, max_S+S_init, max_D+D_init, max_O)
L_t_values = range(1, 100)
optimal_values = {}
for L_t in tqdm(L_t_values):
possible_S_values = np.arange(0, 5 * L_t + 1)
possible_D_values = np.arange(0, 5 * L_t + 1)
max_LS1, max_LS2, max_LS3, max_LS4, max_LS5, max_LS6, max_S, max_D, max_O = find_optimal_value(L_t, possible_S_values, possible_D_values)
optimal_values[L_t] = {'LS1': max_LS1, 'LS2': max_LS2, 'LS3': max_LS3, 'LS4': max_LS4, 'LS5': max_LS5,'LS6': max_LS6, 'S': max_S, 'D': max_D, 'O_t': max_O}
print('{:<5s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}'.format('L_t', 'LS1', 'LS2', 'LS3', 'LS4', 'LS5', 'LS6', 'S', 'D', 'O_t'))
for L_t in L_t_values:
values = optimal_values[L_t]
print('{:<5d}{:<10d}{:<10d}{:<10d}{:<10d}{:<10d}{:<10d}{:<10d}{:<10d}{:<10.2f}'.format(L_t, values['LS1'], values['LS2'], values['LS3'], values['LS4'], values['LS5'], values['LS6'], values['S'], values['D'], values['O_t']))
Note: this isn't for a class so any module for optimization is on the table as well as any other language - as long as it accurately completes the task in a reasonable timeframe.
Do not brute-force this problem. This is a classic (and somewhat easy) linear programming problem.
Your written constraints fail to mention that L, S and D have a lower bound of 0, and S and D have an upper bound of 5Lt. If these constraints are not enforced then the problem is unbounded.
You have not specified the upper bound of LS when L_t == 240. I assume that it continues the trend and is 50.
The following executes in 0.08 s. It should not take "multiple days" nor should it take multiple minutes.
Initial Conditions
To model your initial conditions is somewhat easy - just modify the variable bounds and add offsets to some of the affine expressions. However. For any Lt >= 235 the problem is infeasible. Do you see why?