From 0a18d03cf05d635cd87d7f25521ffae2fbc48f81 Mon Sep 17 00:00:00 2001 From: phamduchongan93 Date: Thu, 5 Dec 2024 18:04:36 -0800 Subject: [PATCH] first commit --- main.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..44cbf3c --- /dev/null +++ b/main.py @@ -0,0 +1,131 @@ +# Import necessary libraries +%pip install gurobipy +import pandas as pd +from gurobipy import * + +# Define model +model = Model("CloudServiceTransportation") + +# Number of providers (AWS, Azure, Google) +m = 3 # AWS, Azure, Google +# Number of services (C1, C2, AI/ML) +n = 3 # C1, C2, AI/ML + +# Cost coefficients for AWS, Azure, and Google for each service (no storage cost) +costs_AWS = {'C1': 0.1664, 'C2': 0.08, 'AI/ML': 3.06} +costs_Azure = {'C1': 0.2021, 'C2': 0.10, 'AI/ML': 0.90} +costs_Google = {'C1': 0.1900, 'C2': 0.10, 'AI/ML': 1.80} + +# Supply limits for each provider (AWS, Azure, Google) - fixed units +supply_AWS = {'C1': 100, 'C2': 300, 'AI/ML': 50} +supply_Azure = {'C1': 120, 'C2': 180, 'AI/ML': 80} +supply_Google = {'C1': 130, 'C2': 200, 'AI/ML': 70} + +# Demand for each service (C1, C2, AI/ML) +demand = {'C1': 100, 'C2': 100, 'AI/ML': 50} + +# Inter-provider egress costs +inter_provider_egress = { + ('AWS', 'Azure'): 20, + ('AWS', 'Google'): 30, + ('Azure', 'Google'): 15, + ('Azure', 'AWS'): 25, + ('Google', 'AWS'): 35, + ('Google', 'Azure'): 10 +} + +# Budget constraint +budget = 20000 # Total budget + +# Decision variables for quantities to transport +x = {} # Amount of service allocated +y = {} # Binary variable indicating provider selection +w = {} # Egress costs between providers + +# Create decision variables +for i, provider_from in enumerate(['AWS', 'Azure', 'Google']): + for j, service in enumerate(['C1', 'C2', 'AI/ML']): + x[i, j] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"{provider_from}_{service}") + y[i, j] = model.addVar(vtype=GRB.BINARY, name=f"provider_{provider_from}_service_{service}") + for k, provider_to in enumerate(['AWS', 'Azure', 'Google']): + if provider_from != provider_to: + w[i, j, k] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"egress_{provider_from}_{service}_{provider_to}") + +# Update model +model.update() + +# Objective function: Minimize total cost (including egress costs) +total_cost = ( + sum(costs_AWS[service] * x[0, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) + + sum(costs_Azure[service] * x[1, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) + + sum(costs_Google[service] * x[2, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) + + sum(inter_provider_egress[('AWS', 'Azure')] * w[0, j, 1] for j in range(n)) + + sum(inter_provider_egress[('AWS', 'Google')] * w[0, j, 2] for j in range(n)) + + sum(inter_provider_egress[('Azure', 'Google')] * w[1, j, 2] for j in range(n)) + + sum(inter_provider_egress[('Azure', 'AWS')] * w[1, j, 0] for j in range(n)) + + sum(inter_provider_egress[('Google', 'AWS')] * w[2, j, 0] for j in range(n)) + + sum(inter_provider_egress[('Google', 'Azure')] * w[2, j, 1] for j in range(n)) +) +model.setObjective(total_cost, GRB.MINIMIZE) + +# Supply constraints +for i, provider in enumerate(['AWS', 'Azure', 'Google']): + for j, service in enumerate(['C1', 'C2', 'AI/ML']): + supply_limit = {'AWS': supply_AWS, 'Azure': supply_Azure, 'Google': supply_Google}[provider][service] + model.addConstr(x[i, j] <= supply_limit * y[i, j], name=f"supply_{provider}_{service}") + +# Demand constraints +for j, service in enumerate(['C1', 'C2', 'AI/ML']): + model.addConstr(sum(x[i, j] for i in range(m)) == demand[service], name=f"demand_{service}") + +# Budget constraint +model.addConstr(total_cost <= budget, name="BudgetConstraint") + +# Only one provider per service +for j, service in enumerate(['C1', 'C2', 'AI/ML']): + model.addConstr(sum(y[i, j] for i in range(m)) == 1, name=f"one_provider_per_service_{service}") + +# Egress constraints: Egress cost applies only when transferring between providers +for i in range(m): + for j in range(n): + for k in range(m): + if i != k: + model.addConstr(w[i, j, k] <= x[i, j], name=f"egress_constraint_{i}_{j}_{k}") + +# Optimize model +model.optimize() + +# Display results in a table format if optimal solution is found +if model.status == GRB.OPTIMAL: + # Create a list to hold the results + results = [] + + # Calculate egress costs dynamically for each provider + egress_costs = {'AWS': 0, 'Azure': 0, 'Google': 0} + for i, provider_from in enumerate(['AWS', 'Azure', 'Google']): + for j in range(n): + for k, provider_to in enumerate(['AWS', 'Azure', 'Google']): + if provider_from != provider_to: + egress_costs[provider_from] += w[i, j, k].x * inter_provider_egress[(provider_from, provider_to)] + + # Gather results for each provider + for i, provider in enumerate(['AWS', 'Azure', 'Google']): + row = [provider] + # Add allocated quantities of each service + for j, service in enumerate(['C1', 'C2', 'AI/ML']): + allocated_quantity = x[i, j].x + row.append(allocated_quantity) + # Append the calculated egress cost + row.append(egress_costs[provider]) + results.append(row) + + # Convert to DataFrame for display + columns = ['Provider', 'C1 (units)', 'C2 (units)', 'AI/ML (units)', 'Egress Cost ($)'] + df = pd.DataFrame(results, columns=columns) + + # Display the DataFrame and the total optimal cost + print(f"Optimal Cost: {model.objVal}") + print(df) +else: + print("No optimal solution found") +