Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

MMA 662 - Assignment 2

Instructions:

1. Answer the questions in this Jupyter Notebook file and upload it in the Assignment 2 entry under the Assignments tab in MyCourses. Answer each question in its own place. Late submissions are NOT accepted. Also, files not in the correct format (other than a Jupyter Notebook) are NOT accepted.

2. You can submit your answer file multiple times, but only the last submission is kept and graded.

3. For each question, make sure to print all the results that the question asks. Also, prevent printing unnecessary information.

4. We only grade the final answer, not the code, for coding questions. However, as the coding part of Question 7 can be a bit challenging, we will give partial credit for concise and correct explanations provided instead of the code only for this question. (Simple criterion: Your explanations should shed light on things that are not obvious from the question itself!)

5. Simple explanations are not enough for formulation questions, and you have to write the exact mathematical formulation of the problem. If you are using an additional variable, introduce it clearly.

In [ ]: import pandas as pd

import numpy as np

import gurobipy as gb

from gurobipy import *

Problem 1: The Apportionment Problem

The Story:

The problem of allocating parliamentary seats in a fairway is a political matter in democratic societies. Suppose a country with a total population of N = Σipi tries to allocate its s available seats to its provinces, each with a population of pi. The common sense says that the fairway to distribute these seats is to allocate each province a seat quota proportional to its population:

Although this solution seems appealing, it ignores that the number of allocated seats must be integers. For instance, in a country with 30 million population and 130 parliament seats, the seat quota for a province with a population of 5 million is qi  =  = 21., which is impossible. In this problem, we will use two methods that you are familiar with to address this issue - plus some additional considerations.

The Data:

The country we are working on has 20 provinces, and its parliament has 601 seats. In the attached file assignment2_data.csv, you can find the dataset for this problem. The first column is the province's name, the second column is the province's population, and the third column is the quota (qi) for the province. The quota for each province is the continuous value we calculated using the formula above as qi  = s ×  . Read the dataset using Python's Pandas

package - or any package you choose - and extract the relevant information. (To ensure everyone is working with the same data, do not calculate the quotas again yourself; just use the given qi s.) For example, in this dataset, the population of province P4 is 3200000, and the quota for this province is 13.16359.

Question 1: The Min Sum Approach: (7.5 points)

You have seen this approach in your first quiz. In this approach, the goal is to minimize the sum of absolute gaps between the number of allocated seats to each province (ai) and its quota (qi) while leaving no seats unfilled. That is, we seek to find allocations a0 to a19 to


(The last line means the number of allocated seats to each province has to be a non-negative integer.)

Linearize the above problem using the method you learned in the quiz, write its code using

Gurobi, and solve it. Report the sum of absolute gaps for the optimal solution and the number of seats allocated to each province.

(Hint: notice that when you are linearizing the absolute value, the auxiliary variables you must   introduce should be continuous, not discrete. This is because while the allocations are discrete, the gap between allocations and the quotas is continuous.)

In [ ]: # Read data from the csv file:

Province =

Population =

=

Num = len(Province)


# Total seats:

s = 601

###############################################

# Create a new model

model = gb.Model("Question1")

model.setParam('MIPGap', 0.00001)

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:



Question 2: The Min Max Approach: (7.5 points)

You are familiar with this approach too! Here, instead of the sum of absolute gaps, we want to minimize the absolute value of the largest gap while leaving no seats unfilled. In other words,  we want to find the allocations a0 to a19 to:

Linearize the above problem using the method you learned in the quiz, write its code using

Gurobi, and solve it. Report the maximum absolute gap in the optimal solution, the number of seats allocated to each province, and the sum of absolute gaps in the optimal solution.

In [ ]: # Read data from the csv file:

Province =

Population =

=

Num = len(Province)

# Total seats:

= 601

###############################################

# Create a new model

model = gb.Model("Question2")

model.setParam('MIPGap', 0.00001)

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:

Question 3: Political Considerations: (20 points)


Due to political reasons, some considerations should be addressed when allocating seats to each province. Here, we want to implement three of them:

1. The number of seats allocated to the two least populated provinces (P4 and P8) must be equal.

2. The number of seats allocated to each province with more than 10,000,000 population ( P7, P10, and P15) should not exceed its quota.

3. If the number of seats allocated to P0 is more than its quota, then the number of seats

allocated to P2 must be more than its quota as well.

Now answer the following questions:

Question 3.1: Mathematical Formulation of the Considerations:

Write the mathematical formulation for each of the above considerations using the techniques you've learned in the course in the course in the following Markdown cell. (Your writing should be clear about which formula is for which consideration.) (10 points)

Your formulations:

First Constraint:

Second Constraint:

Third Constraint:

Question 3.2: Implementing the Considerations:

Based on the first approach (minimizing the sum of absolute gaps while filling all the seats) and by adding these considerations as new constraints. Find the sum of absolute gaps for the

optimal solution using Gurobi and report it. (10 points)

In [ ]: # Read data from the csv file:

Province =

Population =

=

Num = len(Province)

# Total seats:

= 601

###############################################

# Create a new model

model = gb.Model("Question3")

model.setParam('MIPGap', 0.00001)


# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:



Problem 2: Designing the Floor Plan

The Story and Data:

You are responsible for designing the floor plan of a shopping mall. The management team    wants to include stores and facilities that maximize its expected annual profit while satisfying  some constraints. In the following table, called the original table, you can see the yearly profit expected from one unit of each type of store/facility, the area it occupies, and the maximum   number of units you can build from each type. (Notice that the mall can have more than one  unit of each kind of store/facility as long as you do not pass the maximum number limit.)

There are two fundamental constraints that you need to consider when designing the floor plan in all questions:

1. The total area of all stores and facilities should be at most 20,000 m2. (Just so you know, Montreal's Eaton Center's total retail floor area is 45,000 m2.)

2. The mall should have at least one complete toilet and one complete security division. (By "at least one complete," we mean ≥ 1.)

For example, we decided to have 2 restaurants, 2 clothing stores, 1 tech store, 3 pharmacies, 3 toy stores, 1 toilet, and 2 security divisions in the mall. The expected annual profit of this floor plan is:

2 × $300, 000 + 2 × $800, 000 + 1 × $1, 000, 000 + 3 × $500, 000 + 3 × $500, 000 − 1 × $25,

Question 4: Using Continuous Variables: (15 points)

Suppose you can have continuous numbers of each type of store/facility. For instance, you are allowed to have 3.45 units of pharmacies in your mall. Remember to consider the two fundamental constraints.

What is the maximum expected annual profit, and what combination of stores/facilities brings   about this profit? What is the total occupied area? Model it as a linear programming problem,   solve it, and report the results using Gurobi or by hand. Remember, if you solve it by hand, you must provide solid, convincing explanations.


In [ ]:

Type = [ 'Restaurant', 'Clothing Store', 'Tech Store', 'Pharmacy', 'Dept Store', 'Toy

Profit = [300000, 800000, 1000000, 500000, 2200000, 500000, -25000, -100000]

Area = [500, 1700, 1000, 900, 4300, 1400, 200, 300]

Max_No = [5, 15, 5, 5, 3, 5, 3, 3]

Num = len(Type)

###############################################

# Create a new model

model = gb.Model("Question4")

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:

Question 5: Using Integer Variables: (10 points)

In realistic settings, the number of stores/facilities should be discrete. Again, we are interested in the maximum expected annual profit and the optimal combination. Remember to consider  the two fundamental constraints.

What is the maximum expected annual profit, and what combination of stores/facilities brings about this profit? What is the total occupied area? Model it as an integer programming problem, solve it, and report the results using Gurobi.

In [ ]: Type = ['Restaurant', 'Clothing Store', 'Tech Store', 'Pharmacy', 'Dept Store', 'Toy S

Profit = [300000, 800000, 1000000, 500000, 2200000, 500000, -25000, -100000]

Area = [500, 1700, 1000, 900, 4300, 1400, 200, 300]

Max_No = [5, 15, 5, 5, 3, 5, 3, 3]

Num = len(Type)

###############################################

# Create a new model

model = gb.Model("Question5")

model.setParam('MIPGap', 0.00001)# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:



Question 6: Some Additional Constraints: (20 points)

We are still working based on the setup of Question 5, where we decided to use discrete decision variables. In addition to the two fundamental constraints, we want to maximize the expected profit while adding these four constraints to our model:

1. The number of toilets in the mall should be at least half the number of restaurants.

2. The mall should have at least one complete department store or one complete tech store, or both.

3. The total area the clothing stores occupy should not exceed 5,000 m2 .

4. If the mall has more than two complete toy stores, the number of security divisions should be at least two.

Answer the following questions:

Question 6.1: Mathematical Formulation of the Additional Constraints:

Write the mathematical formulation for each of the above constraints using the techniques

you've learned in the course in the following Markdown cell. (Your writing should be clear about which formula is for which one of the additional constraints.) (10 points)

Your Formulations:

First Constraint:

Second Constraint:

Third Constraint:

Fourth Constraint:

Question 6.2: Implementing the Additional Constraints:

What is the maximum expected annual profit, and what combination of stores/facilities brings about this profit? What is the total occupied area? Model it as a mixed integer programming problem (assume the number of each store/facility is an integer), solve it, and report the results using Gurobi. (10 points)


In [ ]: Type = ['Restaurant', 'Clothing Store', 'Tech Store', 'Pharmacy', 'Dept Store', 'Toy S

Profit = [300000, 800000, 1000000, 500000, 2200000, 500000, -25000, -100000]

Area = [500, 1700, 1000, 900, 4300, 1400, 200, 300]

Max_No = [5, 15, 5, 5, 3, 5, 3, 3]

Num = len(Type)

###############################################

# Create a new model

model = gb.Model("Question6")

model.setParam('MIPGap', 0.00001)

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:



Question 7: The Case for Diminishing Returns: (15 points)

Diminishing return to scale: We expect the marginal profit of each additional unit from each store to decrease. That is, while a single pharmacy in the mall brings about $500,000 annual profit, having two pharmacies in the mall creates $800,000, and three pharmacies make $900,000 together. Therefore, the marginal profit of adding a new pharmacy is $500,000 when there is no pharmacy, $300,000 when there is one pharmacy, and $100,000 when there are already two pharmacies in the mall.

Considering this phenomenon, our expectation for the annual profit created by the different number of restaurants, technology stores, and pharmacies is updated as in the following table: (Do not forget that the numbers in the following table represent the profit we expect all the stores to create together, not the profit produced by each of them. So, for example, we expect three restaurants to make $750,000 altogether.)

The maximum number limit for each type of store/facility remains the same as the limits

depicted in the original table, and the expected profit for stores/facilities other than restaurants, technology stores, and pharmacies is estimated linearly similar to the previous questions.

For example, suppose we decided to have 2 restaurants, 2 clothing stores, 1 tech store, 3

pharmacies, 3 toy stores, 1 toilet, and 2 security divisions in the mall. Then, the expected profit of this decision is:

$550, 000 + 2 × $800, 000 + $1, 000, 000 + $900, 000 + 3 × $500, 000 − 1 × $25, 000 − 2 × $


In addition to diminishing return to scale and the two fundamental constraints, we still want to entertain the constraints we introduced in Question 6.

What is the maximum expected annual profit, and what combination of stores/facilities brings about this profit? What is the total occupied area? Model it as a mixed integer programming

problem (assume the number of each store/facility is an integer), solve it, and report the results using Gurobi.


In [ ]: Type = ['Restaurant', 'Clothing Store', 'Tech Store', 'Pharmacy', 'Dept Store', 'Toy S

Profit = [300000, 800000, 1000000, 500000, 2200000, 500000, -25000, -100000]

Area = [500, 1700, 1000, 900, 4300, 1400, 200, 300]

Max_No = [5, 15, 5, 5, 3, 5, 3, 3]

Num = len(Type)

Rest_profit = [0, 300000, 550000, 750000, 850000, 900000]

Tech_profit = [0, 1000000, 1750000, 2250000, 2500000, 2600000]

Pharma_profit = [0, 500000, 800000, 900000, 950000, 950000]

###############################################

# Create a new model

model = gb.Model("Question7")

model.setParam('MIPGap', 0.00001)

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

# Your code here:


Problem 3: BlancedMilk Needs Your Help (Again!)

We have been through the problems BalancedMilk faces after it lost its largest supplier multiple  times. (You may review Assignment and Quiz 1 if you forgot them.) The issue is not resolved yet, and S8 is still shut down. BalancedMilk managers are so excited that now you know how to implement logical constraints using MIP, because they want you to help them with their new problem! They gave you the following information:

1. BalancedMilk is not committed to distributing the milk supplied by the remaining supply

centers, S1 to S7. (It has the option not to distribute the milk it receives from the remaining supply centers.) Additionally, it must not oversupply any demand market.

2. The cost of not supplying (not delivering) milk to each demand market is 15$/tonne.

3. S3, S4, and S5  belong to the same company. The company has imposed the following

constraint: BalancedMilk should utilize ≥ 50% (equal or more than 50%) of the capacity of at least two of the three supply centers owned by this company.



4. Because D5 and D6  are close, the firm has some flexibility in answering their demands. So either D5  receives ≥ 80% of its demand, or D6  receives ≥ 60% of its demand, or both.

5. A competitor is trying to damage BalancedMilk's reputation by focusing on the

discrimination it imposes between different demand centers. This competitor is trying to

exploit the difference between D2  and D8  and D9. Therefore, to respond to this criticism, if D2 receives > 50% of its demand, then D8  and D9  should both receive ≥ 50% of their demand as well.

(Trust me. I am not a recruiter for any dairy transportation company, and neither am I preparing the MMA cohort for an internship at one. It is just that BalancedMilk has so many unresolved issues!)

Question 8: The formulation (15 points)

Write the mathematical formulation of this problem using the techniques you've learned in the course in the following Markdown cell. Use the variables we have already defined.

xij shows the amount of milk (in tonnes) transported from supply center i to demand center j. \ cij is the transportation cost from supply center i to demand center j. \ Si  is the capacity of   supply center i. \ Dj  is the demand of demand center j.

We introduce the following auxiliary variables: \ yi  shows the amount of milk (in tonnes)

supplied by supply center i: yi  = Σj(1)1 xij  for i = 1,  , 7. \ zj shows the amount of milk (in tonnes) delivered to demand center j. zj  = Σ1 xij  for j = 1,  , 10.

The objective function is:

The constraints are: \ Supply and demand constraints: \

Logical constraints: \ First logical constraint:

Second logical constraint:

Third logical constraint:

Question 9: The implementation (10 points)

Write the code for this problem using Gurobi and see if an optimal solution with these

constraints exists. If yes, what are the lowest cost, the utilized capacity of each supply center, and the satisfied demand of each demand center?

(Remember that while the indices of suppliers and demand markets start from 1, the indices of the variables in Python begin from 0.)

In [ ]: Cost = [[20, 49, 16, 30,  8, 35, 21, 40, 10, 12],

[15, 53, 7, 20, 47, 11, 16, 17, 15, 44],

[22, 25, 42, 22, 31, 9, 11, 29, 20, 5],

[45, 6, 33, 35, 49, 25, 30, 47, 32, 31],

[9, 12, 41, 15, 38, 14, 53, 22, 12, 13],

[21, 24, 32, 49, 5, 47, 30, 23, 37, 8],

[12, 19, 5, 28, 47, 39, 15, 35, 9, 51]]


SupplyCenter = ['S_1', 'S_2', 'S_3', 'S_4', 'S_5', 'S_6', 'S_7']

Supply = [110, 80, 100, 240, 100, 280, 130]

DemandMarket = ['D_1', 'D_2', 'D_3', 'D_4', 'D_5', 'D_6', 'D_7', 'D_8', 'D_9', 'D_10']

Demand = [90, 100, 150, 190, 180, 240, 210, 90, 160, 70]

n_supply = len(SupplyCenter)

n_demand = len(DemandMarket)

Range_supply = range(n_supply)

Range_demand = range(n_demand)

##############################

# Create a new model

model = gb.Model("Question9")

# We ask Gurobi not to print too much on screen

model.Params.OutputFlag = 0

model.setParam('MIPGap', 0.00001)

# Your code here: