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.

_images/figure-small-test-system-layout.png

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.

_images/figure-small-test-system-init-state.png

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)