Overview¶
In this tutorial we will load problem settings of a pod repositioning problem, create a solver, and store the solution to a JSON file.
Load Problem Settings¶
First we need to include all necessary python modules. If the prp module is not installed in any standard python directory we need to adjust the search path
import sys
sys.path.append('../') # noqa: E402
before import the modules.
import math
import prp.recorder as recorder
from prp.core.warehouse import Warehouse
import prp.xy as xy
import prp.utils
from prp.core.objects import INVALID_ID
Now we define a function which will load a warehouse problem from json files.
def load_problem():
We load an empty layout from a JSON file ../data/10-layout.json with prp.xy.Layout(). The JSON file contains coordinates of places and stations. Layout() reads this file and creates a corresponding empty warehouse. You can also you the Layout() class to derive costs from the layout. In this case the costs are Manhattan distances between the place and the places.
Warehouse layout.
layout = xy.Layout()
with open("../data/10-layout.json", 'r') as infile:
layout.load_from_json(infile)
warehouse = layout.get_empty_warehouse()
costs = layout.get_costs()
warehouse.set_costs(costs)
We fill the warehouse with pods. We use positions of pods stored in ../../examples/use-custom-solver.py.
Initial positions of the pod.
with open("../data/10-initial-state.json", 'r') as infile:
recorder.load_initial_state_from_json(infile, warehouse)
Finally we load a sequence of departures from “../data/10-departures.json” and return the warehouse. (The departures are sequences of tuples (place,stations) ).
with open("../data/10-departures.json", 'r') as infile:
departures = recorder.load_departures_from_json(infile)
warehouse.set_departure_generator(departures)
return warehouse
Create custom solver¶
We create a class MySolver. It will send a pod to a free place with the smallest costs. On initalization, we will save a reference to our warehouse, because we will frequently use it.
class MySolver:
def __init__(self, warehouse: Warehouse):
self.warehouse = warehouse
The method decide_new_place() tells where to send a pod which leaves a picking station. If no pod leaves the system, decide_new_place() returns (INVALID_ID,*INVALID_ID*). In this case we must return INVALID_ID.
def decide_new_place(self):
(pod, station_id) = self.warehouse.next_arrival_to_storage()
if pod == INVALID_ID:
return INVALID_ID
Otherwise, check all available places in for the next decision and select one with the smallest costs from picking station to the place. Before return our decision, we print some debugging information.
cheapest_place_so_far = INVALID_ID
costs_so_far = math.inf
for place_id in self.warehouse.available_places:
curr_costs = self.warehouse.costs.from_station(station_id, place_id)
if curr_costs < costs_so_far:
cheapest_place_so_far = place_id
costs_so_far = curr_costs
print("Pod {} from {} arrives to place {} at t {}.".format(
pod, station_id, cheapest_place_so_far, self.warehouse.t + 1))
return cheapest_place_so_far
Run the warehouse¶
We load our system and our solver.
warehouse = load_problem()
solver = MySolver(warehouse)
We will store our decisions in a list of places.
solution = []
Now run the system step-wise until it finished. In each step, use our solver to decide were to put the current pods.
while not warehouse.finished():
place_id = solver.decide_new_place()
solution.append(place_id)
warehouse.next(place_id)
Finally print our results
print("Total costs: {} at time {}.".format(warehouse.total_costs, warehouse.t))
and store our solution to a JSON file.
SOLUTION_FILE = "../data/solutions/10-cheapest-place-solution.json"
prp.utils.create_missing_directories_of_file(SOLUTION_FILE)
with open(SOLUTION_FILE, 'w') as outfile:
recorder.store_solution_to_json(solution, outfile)