Binary Integer Programming¶
Solve a small system with Binary Integer Programming (BIP) exactly. Use pulp python package with COIN library.
We first import all necessary modules
from prp.solvers.simple import CheapestPlaceSolver, PlaybackSolver
import prp.recorder as recorder
import prp.xy as xy
import prp.stats
import prp.utils as utils
import prp.solvers.bip as bip
Parameters¶
We define paths to JSON files of a small warehouse system:
LAYOUT_FILE = "../data/10-layout.json"
INITIAL_STATE_FILE = "../data/10-initial-state.json"
COSTS_FILE = "../data/10-costs.json"
DEPARTURES_FILE = "../data/10-departures.json"
and store the results to a JSON file:
SOLUTION_FILE = "../data/solutions/10-bip-solution.json"
Load a warehouse model from JSON files:
def load_problem():
"""Load a test system with 10 places and 10 pods randomly distributed among them."""
layout = xy.Layout()
with open(LAYOUT_FILE, 'r') as infile:
layout.load_from_json(infile)
warehouse = layout.get_empty_warehouse()
with open(INITIAL_STATE_FILE, 'r') as infile:
recorder.load_initial_state_from_json(infile, warehouse)
with open(DEPARTURES_FILE, 'r') as infile:
departures = recorder.load_departures_from_json(infile)
warehouse.set_departure_generator(departures)
costs = layout.get_costs()
Calculate¶
Sometimes we can solve a problem a little bit faster if we provide an upper bound for the objective function. We can obtain a simple bound if we solve this problem with another method – for example Cheapest place.
def get_cheapest_place_costs(warehouse):
"""Return costs when using cheapest-place solver with costs from station."""
warehouse = prp.stats.copy_warehouse(warehouse)
solver = CheapestPlaceSolver(warehouse, warehouse.costs)
while not warehouse.finished():
place_id = solver.decide_new_place()
warehouse.next(place_id)
return warehouse.total_costs
Optionally, you can switch on logging.
import logging
logging.basicConfig(level=logging.DEBUG)
We use the optional parameter costs_upper_bound to speed up calculation.
upper_costs = get_cheapest_place_costs(warehouse)
(solution, problem) = bip.solve(warehouse, threads=4, costs_upper_bound=upper_costs)
Finally we save the results.
utils.create_missing_directories_of_file(SOLUTION_FILE)
with open(SOLUTION_FILE, 'w') as outfile:
recorder.store_solution_to_json(solution, outfile)
Test¶
Optionally, we can test our optimal solution for consistency
for place_id in solution:
warehouse.next(place_id)
if not warehouse.finished():
print("Problem is NOT solved completely")
and print the results.
print("Total costs {c} at time {t}, average costs {avg}".format(c=warehouse.total_costs,