You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
5.2 KiB

1 month ago
  1. # Import necessary libraries
  2. %pip install gurobipy
  3. import pandas as pd
  4. from gurobipy import *
  5. # Define model
  6. model = Model("CloudServiceTransportation")
  7. # Number of providers (AWS, Azure, Google)
  8. m = 3 # AWS, Azure, Google
  9. # Number of services (C1, C2, AI/ML)
  10. n = 3 # C1, C2, AI/ML
  11. # Cost coefficients for AWS, Azure, and Google for each service (no storage cost)
  12. costs_AWS = {'C1': 0.1664, 'C2': 0.08, 'AI/ML': 3.06}
  13. costs_Azure = {'C1': 0.2021, 'C2': 0.10, 'AI/ML': 0.90}
  14. costs_Google = {'C1': 0.1900, 'C2': 0.10, 'AI/ML': 1.80}
  15. # Supply limits for each provider (AWS, Azure, Google) - fixed units
  16. supply_AWS = {'C1': 100, 'C2': 300, 'AI/ML': 50}
  17. supply_Azure = {'C1': 120, 'C2': 180, 'AI/ML': 80}
  18. supply_Google = {'C1': 130, 'C2': 200, 'AI/ML': 70}
  19. # Demand for each service (C1, C2, AI/ML)
  20. demand = {'C1': 100, 'C2': 100, 'AI/ML': 50}
  21. # Inter-provider egress costs
  22. inter_provider_egress = {
  23. ('AWS', 'Azure'): 20,
  24. ('AWS', 'Google'): 30,
  25. ('Azure', 'Google'): 15,
  26. ('Azure', 'AWS'): 25,
  27. ('Google', 'AWS'): 35,
  28. ('Google', 'Azure'): 10
  29. }
  30. # Budget constraint
  31. budget = 20000 # Total budget
  32. # Decision variables for quantities to transport
  33. x = {} # Amount of service allocated
  34. y = {} # Binary variable indicating provider selection
  35. w = {} # Egress costs between providers
  36. # Create decision variables
  37. for i, provider_from in enumerate(['AWS', 'Azure', 'Google']):
  38. for j, service in enumerate(['C1', 'C2', 'AI/ML']):
  39. x[i, j] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"{provider_from}_{service}")
  40. y[i, j] = model.addVar(vtype=GRB.BINARY, name=f"provider_{provider_from}_service_{service}")
  41. for k, provider_to in enumerate(['AWS', 'Azure', 'Google']):
  42. if provider_from != provider_to:
  43. w[i, j, k] = model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"egress_{provider_from}_{service}_{provider_to}")
  44. # Update model
  45. model.update()
  46. # Objective function: Minimize total cost (including egress costs)
  47. total_cost = (
  48. sum(costs_AWS[service] * x[0, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) +
  49. sum(costs_Azure[service] * x[1, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) +
  50. sum(costs_Google[service] * x[2, j] for j, service in enumerate(['C1', 'C2', 'AI/ML'])) +
  51. sum(inter_provider_egress[('AWS', 'Azure')] * w[0, j, 1] for j in range(n)) +
  52. sum(inter_provider_egress[('AWS', 'Google')] * w[0, j, 2] for j in range(n)) +
  53. sum(inter_provider_egress[('Azure', 'Google')] * w[1, j, 2] for j in range(n)) +
  54. sum(inter_provider_egress[('Azure', 'AWS')] * w[1, j, 0] for j in range(n)) +
  55. sum(inter_provider_egress[('Google', 'AWS')] * w[2, j, 0] for j in range(n)) +
  56. sum(inter_provider_egress[('Google', 'Azure')] * w[2, j, 1] for j in range(n))
  57. )
  58. model.setObjective(total_cost, GRB.MINIMIZE)
  59. # Supply constraints
  60. for i, provider in enumerate(['AWS', 'Azure', 'Google']):
  61. for j, service in enumerate(['C1', 'C2', 'AI/ML']):
  62. supply_limit = {'AWS': supply_AWS, 'Azure': supply_Azure, 'Google': supply_Google}[provider][service]
  63. model.addConstr(x[i, j] <= supply_limit * y[i, j], name=f"supply_{provider}_{service}")
  64. # Demand constraints
  65. for j, service in enumerate(['C1', 'C2', 'AI/ML']):
  66. model.addConstr(sum(x[i, j] for i in range(m)) == demand[service], name=f"demand_{service}")
  67. # Budget constraint
  68. model.addConstr(total_cost <= budget, name="BudgetConstraint")
  69. # Only one provider per service
  70. for j, service in enumerate(['C1', 'C2', 'AI/ML']):
  71. model.addConstr(sum(y[i, j] for i in range(m)) == 1, name=f"one_provider_per_service_{service}")
  72. # Egress constraints: Egress cost applies only when transferring between providers
  73. for i in range(m):
  74. for j in range(n):
  75. for k in range(m):
  76. if i != k:
  77. model.addConstr(w[i, j, k] <= x[i, j], name=f"egress_constraint_{i}_{j}_{k}")
  78. # Optimize model
  79. model.optimize()
  80. # Display results in a table format if optimal solution is found
  81. if model.status == GRB.OPTIMAL:
  82. # Create a list to hold the results
  83. results = []
  84. # Calculate egress costs dynamically for each provider
  85. egress_costs = {'AWS': 0, 'Azure': 0, 'Google': 0}
  86. for i, provider_from in enumerate(['AWS', 'Azure', 'Google']):
  87. for j in range(n):
  88. for k, provider_to in enumerate(['AWS', 'Azure', 'Google']):
  89. if provider_from != provider_to:
  90. egress_costs[provider_from] += w[i, j, k].x * inter_provider_egress[(provider_from, provider_to)]
  91. # Gather results for each provider
  92. for i, provider in enumerate(['AWS', 'Azure', 'Google']):
  93. row = [provider]
  94. # Add allocated quantities of each service
  95. for j, service in enumerate(['C1', 'C2', 'AI/ML']):
  96. allocated_quantity = x[i, j].x
  97. row.append(allocated_quantity)
  98. # Append the calculated egress cost
  99. row.append(egress_costs[provider])
  100. results.append(row)
  101. # Convert to DataFrame for display
  102. columns = ['Provider', 'C1 (units)', 'C2 (units)', 'AI/ML (units)', 'Egress Cost ($)']
  103. df = pd.DataFrame(results, columns=columns)
  104. # Display the DataFrame and the total optimal cost
  105. print(f"Optimal Cost: {model.objVal}")
  106. print(df)
  107. else:
  108. print("No optimal solution found")