Operation Research Problems Solving in Python: Prepared by Saurav Barua
Operation Research Problems Solving in Python: Prepared by Saurav Barua
Python
Contents
Sl No. Topics Pages
1 Chapter 1: Installation of Google OR Tools for Python 1
2 Chapter 2: Finding Feasible Solution 2-3
3 Chapter 3: Mixed Integer Problem 4-5
4 Chapter 4: Traveling Salesman Problem 6-8
5 Chapter 5: Vehicle Routing Problem with Capacity Constraint 9-14
@Saurav Barua
Chapter One
Installation of Google OR Tools for Python
Install OR-Tools
Though Google created OR-Tools in C++, you can use it with Python, Java, or C# (on
the .NET platform).
After the installation is complete, you are ready to get started with OR-Tools for Python.
1|P a g e
@Saurav Barua
Chapter Two
Finding Feasible Solution
A simple example
Here's a simple example of a linear programming problem.
x + 2y ≤ 14
3x – y ≥ 0
x–y ≤ 2
Program
def LinearProgrammingExample():
"""Linear programming sample."""
# Instantiate a Glop solver, naming it LinearExample.
solver = pywraplp.Solver('LinearProgrammingExample',
pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
# Create the two variables and let them take on any value.
x = solver.NumVar(-solver.infinity(), solver.infinity(), 'x')
y = solver.NumVar(-solver.infinity(), solver.infinity(), 'y')
2|P a g e
@Saurav Barua
# Constraint 1: 3x - y >= 0.
constraint1 = solver.Constraint(0, solver.infinity())
constraint1.SetCoefficient(x, 3)
constraint1.SetCoefficient(y, -1)
# Constraint 2: x - y <= 2.
constraint2 = solver.Constraint(-solver.infinity(), 2)
constraint2.SetCoefficient(x, 1)
constraint2.SetCoefficient(y, -1)
LinearProgrammingExample()
3|P a g e
@Saurav Barua
Chapter Three
Mixed Integer Problem
x+7y ≤ 17.5
x ≤ 3.5
x ≥ 0
y ≥ 0
x, y integers
Program
def main():
# Create the mip solver with the CBC backend.
solver = pywraplp.Solver('simple_mip_program',
pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
infinity = solver.infinity()
# x and y are integer non-negative variables.
x = solver.IntVar(0.0, infinity, 'x')
y = solver.IntVar(0.0, infinity, 'y')
4|P a g e
@Saurav Barua
# x + 7 * y <= 17.5.
solver.Add(x + 7 * y <= 17.5)
# x <= 3.5.
solver.Add(x <= 3.5)
# Maximize x + 10 * y.
solver.Maximize(x + 10 * y)
result_status = solver.Solve()
# The problem has an optimal solution.
assert result_status == pywraplp.Solver.OPTIMAL
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
print('\nAdvanced usage:')
print('Problem solved in %f milliseconds' % solver.wall_time())
print('Problem solved in %d iterations' % solver.iterations())
print('Problem solved in %d branch-and-bound nodes' % solver.nodes())
if __name__ == '__main__':
main()
5|P a g e
@Saurav Barua
Chapter Four
Traveling Salesman Problem
As an alternative to a distance matrix, you could provide a time matrix which contains
the travel times between locations.
The number of vehicles in the problem, which is 1 because this is a TSP. For general
routing problems, the number of vehicles can be greater than 1.
The depot: the starting location for the route. In this case, the depot is 0, which
corresponds to New York City.
Program
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['distance_matrix'] = [
[0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145,
1972],
[2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357,
6|P a g e
@Saurav Barua
579],
[713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453,
1260],
[1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280,
987],
[1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371],
[1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887,
999],
[2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114,
701],
[213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300,
2099],
[2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653,
600],
[875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272,
1162],
[1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017,
1200],
[2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0,
504],
[1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504,
0],
] # yapf: disable
data['num_vehicles'] = 1
data['depot'] = 0
return data
7|P a g e
@Saurav Barua
def main():
"""Entry point of the program."""
# Instantiate the data problem.
data = create_data_model()
transit_callback_index =
routing.RegisterTransitCallback(distance_callback)
if __name__ == '__main__':
main()
8|P a g e
@Saurav Barua
Chapter Five
Vehicle Routing Problem with Capacity Constraint
Capacity Constraints
Overview
The capacitated vehicle routing problem (CVRP) is a VRP in which vehicles with limited
carrying capacity need to pick up or deliver items at various locations.
In more complex CVRPs, each vehicle might carry several different types of cargo, with
a maximum capacity for each type. For example, a fuel delivery truck might carry
several types of fuel, using multiple tanks with differing capacities. To handle problems
like these, just create a different capacity callback and dimension for each cargo type
(making sure to assign them unique names).
Program
9|P a g e
@Saurav Barua
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['distance_matrix'] = [
[
0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388,
354,
468, 776, 662
],
[
548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480,
674,
1016, 868, 1210
],
[
776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278,
1164,
1130, 788, 1552, 754
],
[
696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628,
822,
1164, 560, 1358
],
[
582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514,
708,
1050, 674, 1244
],
[
274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662,
628,
514, 1050, 708
],
[
502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890,
856,
514, 1278, 480
],
[
10 | P a g e
@Saurav Barua
194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354,
320,
662, 742, 856
],
[
308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696,
662,
320, 1084, 514
],
[
194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422,
388,
274, 810, 468
],
[
536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878,
764,
730, 388, 1152, 354
],
[
502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0,
114,
308, 650, 274, 844
],
[
388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0,
194,
536, 388, 730
],
[
354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308,
194, 0,
342, 422, 536
],
[
468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650,
536,
342, 0, 764, 194
],
[
776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152,
274,
388, 422, 764, 0, 798
11 | P a g e
@Saurav Barua
],
[
662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844,
730,
536, 194, 798, 0
],
]
data['demands'] = [0, 1, 1, 2, 4, 2, 4, 8, 8, 1, 2, 1, 2, 4, 4, 8, 8]
data['vehicle_capacities'] = [15, 15, 15, 15]
data['num_vehicles'] = 4
data['depot'] = 0
return data
12 | P a g e
@Saurav Barua
def main():
"""Solve the CVRP problem."""
# Instantiate the data problem.
data = create_data_model()
transit_callback_index =
routing.RegisterTransitCallback(distance_callback)
demand_callback_index = routing.RegisterUnaryTransitCallback(
demand_callback)
routing.AddDimensionWithVehicleCapacity(
demand_callback_index,
0, # null capacity slack
13 | P a g e
@Saurav Barua
if __name__ == '__main__':
main()
14 | P a g e