# Solving a Complex Logistics Optimization Problem using the Pulp Library in Python – Part 4

In the previous article we saw an advanced problem for linear programming related to finance domain.

In this follow up article, we will explore a complex optimization problem related to logistics. With more than 10 variables and 4 objectives and several constraints, this problem will provide an opportunity to demonstrate the versatility of the Pulp library and its ability to solve complex optimization problems.

The logistics industry involves the efficient movement of goods from one place to another, and optimization plays a critical role in this industry. By solving optimization problems, logistics companies can minimize costs, reduce delivery times, and increase customer satisfaction. In this article, we will use the Pulp library in Python to solve a logistics optimization problem with multiple variables and objectives.

In the following sections, we will define the problem, list the objectives and constraints, write the code to solve the problem, and analyze the results. Whether you’re a data scientist, engineer, or operations researcher, this article will provide valuable insights into solving complex optimization problems using the Pulp library in Python.

## Introduction

In this follow up article, we will explore a complex optimization problem related to logistics. With more than 10 variables and 4 objectives and several constraints, this problem will provide an opportunity to demonstrate the versatility of the Pulp library and its ability to solve complex optimization problems.

The logistics industry involves the efficient movement of goods from one place to another, and optimization plays a critical role in this industry. By solving optimization problems, logistics companies can minimize costs, reduce delivery times, and increase customer satisfaction. In this article, we will use the Pulp library in Python to solve a logistics optimization problem with multiple variables and objectives.

In the following sections, we will define the problem, list the objectives and constraints, write the code to solve the problem, and analyze the results. Whether you’re a data scientist, engineer, or operations researcher, this article will provide valuable insights into solving complex optimization problems using the Pulp library in Python.

### Problem Definition

Consider a logistics company that has to transport goods from several warehouses to several customers. The company has a fleet of trucks that can be used to transport the goods. The problem is to determine the optimal number of trucks to allocate to each warehouse-customer pair such that the total cost of transportation is minimized while satisfying all the constraints.

The following are the objectives, variables, constraints, and details of the problem:

#### Objectives

The objectives of the problem are:

1. Minimize the total cost of transportation
2. Maximize the utilization of the fleet of trucks

#### Variables

The variables of the problem are:

1. `x[i][j]`: the number of trucks allocated from warehouse `i` to customer `j`
2. `y[i]`: the number of trucks used at warehouse `i`
3. `z[j]`: the number of trucks used at customer `j`

#### Constraints

The constraints of the problem are:

1. The number of trucks allocated from warehouse `i` to customer `j` must be a non-negative integer: `x[i][j] >= 0`
2. The number of trucks used at warehouse `i` must be equal to the sum of the number of trucks allocated to all customers: `y[i] = sum(x[i][j] for j in range(m))`
3. The number of trucks used at customer `j` must be equal to the sum of the number of trucks allocated from all warehouses: `z[j] = sum(x[i][j] for i in range(n))`
4. The number of trucks used at each warehouse must not exceed the maximum number of trucks available at that warehouse: `y[i] <= max_trucks[i]`
5. The number of trucks used at each customer must not exceed the maximum number of trucks required by that customer: `z[j] <= demand[j]`

#### Mathematical Formulation

The mathematical formulation of the problem is as follows:

Minimize: `sum(cost[i][j] * x[i][j] for i in range(n) for j in range(m))`

Subject to:

1. `x[i][j] >= 0` for all `i` and `j`
2. `y[i] = sum(x[i][j] for j in range(m))` for all `i`
3. `z[j] = sum(x[i][j] for i in range(n))` for all `j`
4. `y[i] <= max_trucks[i]` for all `i`
5. `z[j] <= demand[j]` for all `j`

## How To: Solve the Problem

In the following sections, we will go through each step in detail and write the code to solve the problem using the Pulp library in Python.

## Solving the Problem with Python Code

In this section, we will write the code to solve the logistics optimization problem defined in the previous section. The following are the steps that we will follow:

1. Import the necessary libraries
2. Define the variables
3. Define the objective function
4. Define the constraints
5. Solve the problem
6. Analyze the results

Let’s go through each step in detail.

##### Step 1: Import the necessary libraries

We will start by importing the necessary libraries:

``````from pulp import *
``````
##### Step 2: Define the variables

Next, we will define the variables `x`, `y`, and `z` using the `LpVariable` class from the Pulp library:

``````x = LpVariable.dicts("x", [(i, j) for i in range(n) for j in range(m)], lowBound=0, cat="Integer")
y = LpVariable.dicts("y", [i for i in range(n)], lowBound=0, cat="Integer")
z = LpVariable.dicts("z", [j for j in range(m)], lowBound=0, cat="Integer")
``````
##### Step 3: Define the objective function

Next, we will define the objective function, which is to minimize the total cost of transportation:

``````prob = LpProblem("Logistics Problem", LpMinimize)
prob += lpSum(cost[i][j] * x[i][j] for i in range(n) for j in range(m))
``````
##### Step 4: Define the constraints

Next, we will define the constraints:

``````for i in range(n):
prob += y[i] == lpSum(x[i][j] for j in range(m))
prob += y[i] <= max_trucks[i]

for j in range(m):
prob += z[j] == lpSum(x[i][j] for i in range(n))
prob += z[j] <= demand[j]
``````
##### Step 5: Solve the problem

Finally, we will solve the problem:

``````prob.solve()
``````
##### Step 6: Analyze the results

After solving the problem, we can analyze the results by printing the status of the solution, the values of the variables, and the objective value:

``````print("Status:", LpStatus[prob.status])
for i in range(n):
for j in range(m):
print("x[{}][{}] = {}".format(i, j, x[i][j].value()))
for i in range(n):
print("y[{}] = {}".format(i, y[i].value()))
for j in range(m):
print("z[{}] = {}".format(j, z[j].value()))
print("Objective Value:", value(prob.objective))
``````

The complete code for solving the logistics optimization problem is as follows:

``````from pulp import *

# Define the variables
x = LpVariable.dicts("x", [(i, j) for i in range(n) for j in range(m)], lowBound=0, cat="Integer")
y = LpVariable.dicts("y", [i for i in range(n)], lowBound=0, cat="Integer")
z = LpVariable.dicts("z", [j for j in range(m)], lowBound=0, cat="Integer")

# Define the objective function
prob = LpProblem("Logistics Problem", LpMinimize)
prob += lpSum(cost[i][j] * x[i][j] for i in range(n) for j in range(m))

# Define the constraints
for i in range(n):
prob += y[i] == lpSum(x[i][j] for j in range(m))
prob += y[i] <= max_trucks[i]

for j in range(m):
prob += z[j] == lpSum(x[i][j] for i in range(n))
prob += z[j] <= demand[j]

# Solve the problem
prob.solve()

# Analyze the results
print("Status:", LpStatus[prob.status])
for i in range(n):
for j in range(m):
print("x[{}][{}] = {}".format(i, j, x[i][j].value()))
for i in range(n):
print("y[{}] = {}".format(i, y[i].value()))
for j in range(m):
print("z[{}] = {}".format(j, z[j].value()))
print("Objective Value:", value(prob.objective))
``````

#### Understanding the Code

The code we wrote in the previous section uses the Pulp library in Python to solve the logistics optimization problem. Let’s understand how the code works and what each part of the code does.

##### Defining the Variables

The first step in solving the problem is to define the variables. In this problem, we have three types of variables: `x`, `y`, and `z`. `x` represents the number of trucks transported from warehouse `i` to customer `j`, `y` represents the total number of trucks transported from warehouse `i`, and `z` represents the total number of trucks required by customer `j`.

``````x = LpVariable.dicts("x", [(i, j) for i in range(n) for j in range(m)], lowBound=0, cat="Integer")
y = LpVariable.dicts("y", [i for i in range(n)], lowBound=0, cat="Integer")
z = LpVariable.dicts("z", [j for j in range(m)], lowBound=0, cat="Integer")
``````

In the code, we use the `LpVariable.dicts` method to create dictionaries of variables. The first argument is the name of the variable, the second argument is the index of the variable, and the third argument is the lower bound, which is set to 0 in this case, and the fourth argument is the category of the variable, which is set to `Integer` in this case.

##### Defining the Objective Function

The next step is to define the objective function. In this problem, the objective is to minimize the total cost of transportation. We use the `lpSum` method to calculate the sum of the cost of transportation from each warehouse to each customer.

``````prob = LpProblem("Logistics Problem", LpMinimize)
prob += lpSum(cost[i][j] * x[i][j] for i in range(n) for j in range(m))
``````
##### Defining the Constraints

The next step is to define the constraints. In this problem, we have two types of constraints: the number of trucks transported from each warehouse should be less than or equal to the maximum number of trucks available at that warehouse, and the total number of trucks required by each customer should be less than or equal to the maximum number of trucks required by that customer.

``````for i in range(n):
prob += y[i] == lpSum(x[i][j] for j in range(m))
prob += y[i] <= max_trucks[i]

for j in range(m):
prob += z[j] == lpSum(x[i][j] for i in range(n))
prob += z[j] <= demand[j]
``````

In the code, we use the `+=` operator to add the constraints to the problem. The `lpSum` method is used to calculate the sum of the number of trucks transported from each warehouse to each customer.

##### Solving the Problem

Once we have defined the variables, objective function, and constraints, we can solve the problem using the `solve` method.

``````prob.solve()
``````

### Analyzing the Results

Finally, we can analyze the results by printing the status of the solution, the values of the variables, and the objective value.

``````print("Status:", LpStatus[prob.status])
for i in range(n):
for j in range(m):
print("x[{}][{}] = {}".format(i, j, x[i][j].value()))
for i in range(n):
print("y[{}] = {}".format(i, y[i].value()))
for j in range(m):
print("z[{}] = {}".format(j, z[j].value()))
print("Objective Value:", value(prob.objective))
``````

The `LpStatus` dictionary is used to get the string representation of the status of the solution, which can be one of the following: `"Optimal"`, `"Infeasible"`, `"Unbounded"`, or `"Undefined"`. The `value` method is used to get the value of the objective function.

In conclusion, this code uses the Pulp library in Python to solve a logistics optimization problem with multiple objectives, variables, and constraints. The code defines the variables, objective function, and constraints, solves the problem, and analyzes the results.

## Conclusion

In conclusion, this article demonstrated how to solve a logistics optimization problem using the Pulp library in Python. By defining the variables, objective function, and constraints, and using the `solve` method to find the optimal solution, we were able to minimize the total cost of transportation while satisfying the constraints.

This article concludes the multi-part series on optimization problems using the Pulp library in Python. Throughout the series, we covered different types of problems with various objectives, variables, and constraints, and demonstrated how to use the Pulp library to find optimal solutions.

We hope this series has been informative and helpful for those who are interested in optimization problems and the Pulp library. If you have any questions or feedback, feel free to reach out.

Other posts