Last active
November 17, 2021 21:46
-
-
Save WillianFuks/1e372264d4bacc3de067d6956e83ecc6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def optimize(data_models, train_limit, ob_cost_factor=2, container_cost_factor=10): | |
results = {} | |
containers = data_models['containers'] | |
shippers = data_models['shippers'] | |
orig_ports = data_models['orig_port'] | |
transp = data_models['transp'] | |
transp_train_map = data_models['transp_train_map'] | |
shipper_trade_spaces = data_models['shipper_trade_spaces'] | |
overbooking_spaces = shipper_trade_spaces.matrix | |
dest_shipper_map = data_models['dest_shipper_map'] | |
orig_transp_map = data_models['orig_transp_map'] | |
dest_shipper_and_orig = data_models['dest_shipper_and_orig'] | |
trade_shipper_and_trade_map = data_models['trade_shipper_and_trade_map'] | |
shipper_shipper_and_trade_map = data_models['shipper_shipper_and_trade_map'] | |
dest_trade_map = data_models['dest_trade_map'] | |
orig_shipper_map = data_models['orig_shipper_map'] | |
orig_shipper_and_orig_map = data_models['orig_shipper_and_orig_map'] | |
shipper_shipper_and_orig_map = data_models['shipper_shipper_and_orig_map'] | |
factory_orig_and_transp_cost = data_models['factory_orig_and_transp_cost'] | |
factory_orig_and_transp_map = data_models['factory_orig_and_transp_map'] | |
orig_orig_and_transp_map = data_models['orig_orig_and_transp_map'] | |
transp_orig_and_transp_map = data_models['transp_orig_and_transp_map'] | |
dests_arr = np.asarray(containers.matrix[:, 1].todense()).flatten().astype(np.int32) | |
dest_trades_arr = dest_trade_map.matrix[dests_arr] | |
# This matrix is a mapping from trades to shippers and trades. This allows us to | |
# convert everything to spaces later on as spaces are defined at the shipper and | |
# trade level. | |
trade_shipper_trade_matrix = dest_trades_arr @ trade_shipper_and_trade_map.matrix | |
factories_arr = np.asarray(containers.matrix[:, 0].todense()).flatten().astype( | |
np.int32) | |
# Each factory have only a few available options for transportation and which origins | |
# it may attend. This variable is used to make sure the origin and transport chosen | |
# by the algorithm are available for the factory of each container | |
factories_origs_transp_arr = factory_orig_and_transp_map.matrix[factories_arr] | |
orig_and_transp_costs_matrix = factory_orig_and_transp_cost.matrix[factories_arr] | |
container_costs_arr = np.asarray(containers.matrix[:, 2].todense()).flatten() | |
n_containers = len(containers) | |
n_shippers = len(shippers) | |
n_origins = len(orig_ports) | |
n_transp = len(transp) | |
# cvxpy variables. | |
x_shippers = cx.Variable((n_containers, n_shippers), boolean=True, name='Shippers') | |
x_ob_shippers = cx.Variable((n_containers, n_shippers), boolean=True, | |
name='OverBooking Shippers') | |
x_origins = cx.Variable((n_containers, n_origins), boolean=True, name='Origins') | |
x_transp = cx.Variable((n_containers, n_transp), boolean=True, name='Transports') | |
# cvxpy "AND" variables. | |
y_shipper_and_origin = cx.Variable( | |
(n_containers, shipper_shipper_and_orig_map.matrix.shape[1]), | |
boolean=True, | |
name='Shippers AND Origins' | |
) | |
y_shipper_ob_and_origin = cx.Variable( | |
(n_containers, shipper_shipper_and_orig_map.matrix.shape[1]), | |
boolean=True, | |
name='Shippers Overbooking AND Origins' | |
) | |
y_origin_and_transp = cx.Variable( | |
(n_containers, orig_orig_and_transp_map.matrix.shape[1]), | |
boolean=True, | |
name='Orig Ports AND Transportation' | |
) | |
constraints = [] | |
# x_shippers constraints | |
shipper_shipper_trade_arr = x_shippers @ shipper_shipper_and_trade_map.matrix | |
shipper_trade_consumed = cx.sum( | |
cx.multiply(trade_shipper_trade_matrix, shipper_shipper_trade_arr), | |
axis=0, keepdims=True | |
) | |
constr00 = shipper_trade_consumed <= shipper_trade_spaces.matrix | |
constr01 = cx.sum(x_shippers + x_ob_shippers, axis=1) <= 1 | |
constr02 = (x_shippers + x_ob_shippers) <= dest_shipper_map.matrix[dests_arr] | |
constr03 = cx.sum(shipper_trade_consumed) <= n_containers | |
constraints.extend([constr00, constr01, constr02, constr03]) | |
# x_origins constraints | |
constr10 = cx.sum(x_origins, axis=1) <= 1 | |
constr11 = (x_shippers + x_ob_shippers) <= x_origins @ orig_shipper_map.matrix | |
constr12 = cx.sum(x_shippers + x_ob_shippers, axis=1) == cx.sum(x_origins, axis=1) | |
constraints.extend([constr10, constr11, constr12]) | |
# x_ob_shippers constraints | |
constr20 = cx.sum(x_ob_shippers, axis=1) <= 1 | |
constr21 = cx.sum(x_shippers + x_ob_shippers) <= n_containers | |
shipper_ob_shipper_ob_trade_arr = ( | |
x_ob_shippers @ shipper_shipper_and_trade_map.matrix | |
) | |
shipper_ob_trade_consumed = cx.sum( | |
cx.multiply(trade_shipper_trade_matrix, shipper_ob_shipper_ob_trade_arr), | |
axis=0, keepdims=True | |
) | |
shipper_ob_trade_indices = cx.max( | |
cx.multiply(trade_shipper_trade_matrix, shipper_ob_shipper_ob_trade_arr), | |
axis=0, keepdims=True | |
) | |
constr22 = shipper_ob_trade_consumed <= overbooking_spaces | |
constr23 = ( | |
shipper_trade_consumed >= | |
cx.multiply(shipper_trade_spaces.matrix, cx.max(shipper_ob_trade_indices, axis=0, | |
keepdims=True)) | |
) | |
constraints.extend([constr20, constr21, constr22, constr23]) | |
# y_shipper_and_orig constraints. | |
x1 = x_shippers @ shipper_shipper_and_orig_map.matrix | |
x2 = x_origins @ orig_shipper_and_orig_map.matrix | |
constr30 = y_shipper_and_origin >= x1 + x2 - 1 | |
constr31 = y_shipper_and_origin <= x1 | |
constr32 = y_shipper_and_origin <= x2 | |
constr33 = cx.sum(y_shipper_and_origin, axis=1) == cx.sum(x_shippers, axis=1) | |
constr34 = y_shipper_and_origin >= 0 | |
x1 = x_ob_shippers @ shipper_shipper_and_orig_map.matrix | |
constr35 = y_shipper_ob_and_origin >= x1 + x2 - 1 | |
constr36 = y_shipper_ob_and_origin <= x1 | |
constr37 = y_shipper_ob_and_origin <= x2 | |
constr38 = cx.sum(y_shipper_ob_and_origin, axis=1) == cx.sum(x_ob_shippers, axis=1) | |
constr39 = y_shipper_ob_and_origin >= 0 | |
constraints.extend([constr30, constr31, constr32, constr33, constr34, constr35, | |
constr36, constr37, constr38, constr39]) | |
# x_transp constraints. | |
constr40 = cx.sum(x_origins, axis=1) == cx.sum(x_transp, axis=1) | |
constr41 = x_transp <= x_origins @ orig_transp_map.matrix | |
constr42 = cx.sum(x_transp @ transp_train_map.matrix) <= train_limit | |
constraints.extend([constr40, constr41, constr42]) | |
# y_origin_and_transp | |
x1 = x_origins @ orig_orig_and_transp_map.matrix | |
x2 = x_transp @ transp_orig_and_transp_map.matrix | |
constr50 = y_origin_and_transp >= x1 + x2 - 1 | |
constr51 = y_origin_and_transp <= x1 | |
constr52 = y_origin_and_transp <= x2 | |
constr53 = cx.sum(y_origin_and_transp, axis=1) == cx.sum(x_origins, axis=1) | |
constr54 = y_origin_and_transp >= 0 | |
constr55 = cx.sum( | |
cx.multiply(factories_origs_transp_arr, y_origin_and_transp), | |
axis=1) == cx.sum(x_origins, axis=1) | |
constraints.extend([constr50, constr51, constr52, constr53, constr54, constr55]) | |
cost = ( | |
cx.sum(cx.multiply( | |
y_shipper_and_origin, | |
dest_shipper_and_orig.matrix[dests_arr] | |
)) + | |
cx.sum( | |
cx.multiply(y_shipper_ob_and_origin, | |
dest_shipper_and_orig.matrix[dests_arr] * ob_cost_factor) | |
) + | |
cx.sum( | |
cx.multiply((1 - cx.sum(x_shippers + x_ob_shippers, axis=1)), | |
container_costs_arr * container_cost_factor)) + | |
cx.sum( | |
cx.multiply(y_origin_and_transp, orig_and_transp_costs_matrix)) | |
) | |
objective = cx.Minimize(cost) | |
problem = cx.Problem(objective, constraints) | |
problem.solve() | |
print(problem.solution) | |
print(time() - t0) | |
print('y_origin_and_transp ', y_origin_and_transp.value) | |
print('y_shipper_and_origin ', y_shipper_and_origin.value) | |
results['x_shippers'] = x_shippers.value | |
results['x_ob_shippers'] = x_ob_shippers.value | |
results['x_origins'] = x_origins.value | |
results['x_transp'] = x_transp.value | |
return results |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment