288. Integer Programming

288.1. IP (Integer Programming)

288.2. Selection and Logical Relations on Binary Variables

288.2.1. Cardinality Constraints

Given a subset :

Example

We want to select at least 2 of items 1, 2, 3

Example

We want to select at most 2 of items 1, 2, 3

Example

We want to select exactly 2 of items 1, 2, 3

288.2.2. Logical OR

Given a subset :

Example

Select item 1 or item 2, or both

288.2.3. Conditional Selection: “If X, then Y”

(Implication Constraints)

Example

If item 1 is selected, then item 2 must also be selected

Valid?
0 0
0 1
1 0
1 1
Example

If you choose project A, then you cannot choose project B (mutually exclusive).

Valid?
0 0
0 1
1 0
1 1
Example

For binary variables works

If you choose project A, then you must not choose either project B or C.

Valid?
1 0 0
1 1 0
1 1 1
0 1 1
0 0 1

288.2.4. Conditional OR: “If not X, then select Y and Z”

Example

If you do not choose item 1, then you must choose both item 2 and item

If , then

LHS RHS Valid?
0 1 1 2 2
0 1 0 1 2
0 0 0 0 2
1 0 0 0 0
1 1 0 1 0
1 1 1 2 0

288.2.5. XOR / Exclusive Conditions

Example

You can select item 1 or item 2, but not both

Sum Valid?
0 1 1
1 0 1
1 1 2
0 0 0

288.3. Constraint Activation and Relaxation via Binary Indicators

288.3.1. Base Case: At Least One of Two Constraints Satisfied

You are given 2 constraints

We want at least one of these two constraints to be satisfied.

Binary Indicator Variables

Define:

Let and be upper bounds on how much each constraint’s LHS can exceed :

Big-M Reformulation

We relax each constraint as follows:

When , the original constraint is enforced

When , the original constraint can be violated by up to

At Least One Constraint Enforced

We require:

288.3.2. General Formulation for Constraints with At Least Satisfied

  1. Introduce a binary variable for each constraint , where:
  1. Use “big-M” constraint to relax when , like:

Where

  1. Impose a condition that at least of the constraints must be satisfied:

288.4. Fixed Charge Constraints (Setup Costs)

Decision Variables

Objective Function

Capacity Constraints

Demand Fullfilment

Logical Linking of and

To ensure if any production occurs at factory :

Binary & Non-negative Constraints

General Form (Big-M Formulation)

Where must be set to the upper bound of

288.5. Facility Location

Problem Definition
Set Covering Select the minimum number of facilities such that every demand point is within a specified coverage distance of at least one facility
Maximum Covering Select a fixed number of facilities to maximize the number of demand points covered within a specified distance
Fixed Charge Location Determine which facilities to open and how to assign demand to them to minimize the total cost

288.5.1. Set Covering Problem

Question: How to allocate as few facilities as possible to cover all demand nodes?

Complete Formulation

288.5.2. Maximum Covering Problem

Question: How to allocate at most facilities to cover as many demand nodes as possible?

Complete Formulation

Fixed Charge Location Problems

Question: How to allocate some facilities to minimize the total shipping and construction costs?

Uncapacitated Facility Location Problem (UFL)

Complete Formulation

Capacitated Facility Location Problem (CFL)

If locations have a capacity, we may add constraint

Where:

Example

Parameters

  • : weekly operating cost of distribution center
  • : shipping cost per book from distribution center to region
  • : capacity of distribution center
  • : book demand of region

Decision variable

  • : binary variable
  • : number of books shipped from distribution center to region

Supply

WA NV NE PA FL Demand
()
NorthWest 8000
SouthWest 12000
MidWest 9000
SouthEast 14000
NorthEast 17000

Fixed Costs () and Capacity ()

Operation Cost () 40000 30000 25000 40000 30000
Capacity () 20000 20000 15000 25000 15000

Shipping Cost ()

WA NV NE PA FL
NorthWest 2.4 3.25 4.05 5.25 6.95
SouthWest 3.5 2.3 3.25 6.05 5.85
MidWest 4.8 3.4 2.85 4.3 4.8
SouthEast 6.8 5.25 4.3 3.25 2.1
NorthEast 5.75 6 4.75 2.75 3.5

Binary Decision Variable

WA
NV
NE
PA
FL

model.py

model.py
from pyomo.environ import *
from pyomo.dataportal import DataPortal

model = AbstractModel()

# Sets
model.I = Set(doc='Regions (demand points)')
model.J = Set(doc='Candidate distribution centers')

# Parameters
model.D = Param(model.I, within=NonNegativeReals, doc='Demand at region i')
model.K = Param(model.J, within=NonNegativeReals, doc='Capacity at distribution center j')
model.f = Param(model.J, within=NonNegativeReals, doc='Fixed cost to open center j')
model.c = Param(model.I, model.J, within=NonNegativeReals, doc='Shipping cost from j to i')

# Decision Variables
model.x = Var(model.J, within=Binary, doc='1 if center j is opened')
model.y = Var(model.I, model.J, within=NonNegativeReals, doc='Units shipped from j to i')

# Objective Function: Minimize total cost
def total_cost_rule(model):
    fixed = sum(model.f[j] * model.x[j] for j in model.J)
    shipping = sum(model.c[i, j] * model.y[i, j] for i in model.I for j in model.J)
    return fixed + shipping
model.TotalCost = Objective(rule=total_cost_rule, sense=minimize)

# Constraints

# Capacity Constraint: Total shipped from center ≤ capacity if opened
def capacity_rule(model, j):
    return sum(model.y[i, j] for i in model.I) <= model.K[j] * model.x[j]
model.CapacityConstraint = Constraint(model.J, rule=capacity_rule)

# Demand Constraint: Total received by region ≥ its demand
def demand_rule(model, i):
    return sum(model.y[i, j] for j in model.J) >= model.D[i]
model.DemandConstraint = Constraint(model.I, rule=demand_rule)

# Load data from .dat file
data = DataPortal()
data.load(filename='data.dat', model=model)

# Create an instance of the model
instance = model.create_instance(data)

# Create solver
solver = SolverFactory('glpk')
solver.options['tmlim'] = 60

# Solve with solver timeout (optional)
results = solver.solve(instance, tee=True)

# Display results
instance.display()
data.dat
set I := NorthWest SouthWest MidWest SouthEast NorthEast;
set J := WA NV NE PA FL;

param: D :=
NorthWest 8000
SouthWest 12000
MidWest 9000
SouthEast 14000
NorthEast 17000;

param: f :=
WA 40000
NV 30000
NE 25000
PA 40000
FL 30000;

param: K :=
WA 20000
NV 20000
NE 15000
PA 25000
FL 15000;

param c:
        WA     NV     NE     PA     FL :=
NorthWest 2.4   3.25   4.05   5.25   6.95
SouthWest 3.5   2.3    3.25   6.05   5.85
MidWest   4.8   3.4    2.85   4.3    4.8
SouthEast 6.8   5.25   4.3    3.25   2.1
NorthEast 5.75  6      4.75   2.75   3.5 ;

Output:

Variables:
x : 1 if center j is opened
    Size=5, Index=J
    Key : Lower : Value : Upper : Fixed : Stale : Domain
     FL :     0 :   1.0 :     1 : False : False : Binary
     NE :     0 :   0.0 :     1 : False : False : Binary
     NV :     0 :   1.0 :     1 : False : False : Binary
     PA :     0 :   1.0 :     1 : False : False : Binary
     WA :     0 :   0.0 :     1 : False : False : Binary
y : Units shipped from j to i
    Size=25, Index=I*J
    Key                 : Lower : Value   : Upper : Fixed : Stale : Domain
      ('MidWest', 'FL') :     0 :  1000.0 :  None : False : False : NonNegativeReals
      ('MidWest', 'NE') :     0 :     0.0 :  None : False : False : NonNegativeReals
      ('MidWest', 'NV') :     0 :     0.0 :  None : False : False : NonNegativeReals
      ('MidWest', 'PA') :     0 :  8000.0 :  None : False : False : NonNegativeReals
      ('MidWest', 'WA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthEast', 'FL') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthEast', 'NE') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthEast', 'NV') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthEast', 'PA') :     0 : 17000.0 :  None : False : False : NonNegativeReals
    ('NorthEast', 'WA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthWest', 'FL') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthWest', 'NE') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthWest', 'NV') :     0 :  8000.0 :  None : False : False : NonNegativeReals
    ('NorthWest', 'PA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('NorthWest', 'WA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthEast', 'FL') :     0 : 14000.0 :  None : False : False : NonNegativeReals
    ('SouthEast', 'NE') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthEast', 'NV') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthEast', 'PA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthEast', 'WA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthWest', 'FL') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthWest', 'NE') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthWest', 'NV') :     0 : 12000.0 :  None : False : False : NonNegativeReals
    ('SouthWest', 'PA') :     0 :     0.0 :  None : False : False : NonNegativeReals
    ('SouthWest', 'WA') :     0 :     0.0 :  None : False : False : NonNegativeReals

Objectives:
  TotalCost : Size=1, Index=None, Active=True
      Key  : Active : Value
      None :   True : 268950.0

Constraints:
  CapacityConstraint : Size=5
      Key : Lower : Body : Upper
      FL :  None :  0.0 :   0.0
      NE :  None :  0.0 :   0.0
      NV :  None :  0.0 :   0.0
      PA :  None :  0.0 :   0.0
      WA :  None :  0.0 :   0.0
  DemandConstraint : Size=5
      Key       : Lower   : Body    : Upper
        MidWest :  9000.0 :  9000.0 :  None
      NorthEast : 17000.0 : 17000.0 :  None
      NorthWest :  8000.0 :  8000.0 :  None
      SouthEast : 14000.0 : 14000.0 :  None
      SouthWest : 12000.0 : 12000.0 :  None

288.6. Machine Scheduling

Problem Definition
One
Machine
Single Machine
Serial Production
Scheduling jobs one after another on a single machine
Multiple
Machines
Multiple Parallel
Machines
Scheduling jobs on two or more identical machines working in parallel; each job can be assigned to any machine
Flow Shop All jobs follow the same sequence of machines; each job visits every machine in the same order
Job Shop Each job has its own specific sequence of machines to follow

288.6.1. Single Machine Serial Production

Notation

Job Order Constraints

We must ensure that either job comes before job or vice versa, but not both

If job is before job ()

If job is before job ():

These two cases can be rewritten using a big- formulation:

Where:

Complete Formulation

Interpretation

If jobs are run in order , the completion times are:

So, the completion time of a job depends on the sum of processing times of all jobs before it in the schedule

Optional: Release Times

If jobs have release times , meaning each job cannot start before , then we add:

288.6.2. Multiple Parallel Machines

We aim to assign jobs to machines such that:

Notation

Objective

Minimize makespan

Complete Formulation

model.py
from pyomo.environ import *

model = AbstractModel()

model.MACHINES = Set()
model.JOBS = Set()

model.p = Param(model.JOBS, within=PositiveReals)

model.x = Var(model.MACHINES, model.JOBS, domain=Binary)
model.w = Var(domain=NonNegativeReals)

def obj_rule(m):
    return m.w
model.Obj = Objective(rule=obj_rule, sense=minimize)

def job_assignment_rule(m, j):
    return sum(m.x[i, j] for i in m.MACHINES) == 1
model.JobAssignment = Constraint(model.JOBS, rule=job_assignment_rule)

def machine_completion_rule(m, i):
    return sum(m.p[j] * m.x[i, j] for j in m.JOBS) <= m.w
model.MachineCompletion = Constraint(model.MACHINES, rule=machine_completion_rule)

288.6.3. Flow Shop

288.6.4. Job Shop

288.7. Vehicle Routing

288.7.1. Traveling Salesperson

Objective

Minimize the total travel cost

Constraints

  1. Flow Balancing

For node

  1. Subtours

a. Miller-Tucker-Zemlin (MTZ)

b. Subtour Elimination Constraint (SEC)

For every subset with :

This ensures that no subset of nodes forms a closed tour independent of the main tour.

Complete Formulation