Beispiel #1
0
    def to_tsplib95(self):
        arcs = TupList(self.data["arcs"])
        nodes = (arcs.take("n1") + arcs.take("n2")).unique()
        pos = {k: v for v, k in enumerate(nodes)}
        arc_dict = arcs.to_dict(result_col="w",
                                indices=["n1", "n2"],
                                is_list=False).to_dictdict()
        arc_weights = [[]] * len(nodes)
        for n1, n2dict in arc_dict.items():
            n1list = arc_weights[pos[n1]] = [0] * len(n2dict)
            for n2, w in n2dict.items():
                n1list[pos[n2]] = w

        if len(nodes)**2 == len(arcs):
            edge_weight_format = "FULL_MATRIX"
        elif abs(len(nodes)**2 - len(arcs) * 2) <= 2:
            edge_weight_format = "LOWER_DIAG_ROW"
        else:
            # TODO: can there another possibility?
            edge_weight_format = "LOWER_DIAG_ROW"
        dict_data = dict(
            name="TSP",
            type="TSP",
            comment="",
            dimension=len(nodes),
            edge_weight_type="EXPLICIT",
            edge_weight_format=edge_weight_format,
            edge_weights=arc_weights,
        )
        return tsp.models.StandardProblem(**dict_data)
Beispiel #2
0
    def calculate_inventories(self):
        """
        Calculates the inventory of each customer at each hour of the time horizon
        :return: A dictionary whose keys are the indexes of the customers
            and whose values are dictionaries containing two elements:
                - a list 'tank_quantity' containing the value of the inventory at each hour
                - an integer 'location' corresponding to the index of the customer
        For example: {2:  {'tank_inventory': [15000, 14000, 13000, 16000, ... , 14000, 13000], 'location': 2},
                      3:  {'tank_inventory': [4000, 4000, 4000, 1000, ..., 3000, 3000], 'location': 3}}
        """
        customers = self.instance.get_id_customers()
        _get_customer = lambda c, p: self.instance.get_location_property(c, p)
        # we need three things: consumption, initial stock and arrivals
        # we store each as a dictionary where each customer has a numpy array of length = horizon

        # 1. we get consumptions from forecasts
        consumption = (customers.to_dict(None).vapply(
            _get_customer, "Forecast").vapply(lambda v: -np.array(v)).vapply(
                lambda v: v[0:self.horizon]))

        # 2. we get initial tanks and assign them to the first period
        initial_tank = consumption.vapply(lambda v: np.zeros(self.horizon))
        for k, v in initial_tank.items():
            v[0] = _get_customer(k, "InitialTankQuantity")

        # 3. we now use the solution to get the arrivals with routes
        shifts = self.solution.get_all_shifts()
        all_operations = TupList(operation
                                 for route_list in shifts.take("route")
                                 for operation in route_list)
        # for each route we take the location, the time and how much.
        # we only get customers and round the time and make positive the quantity
        arrivals_tup = (all_operations.take(
            ["location", "arrival",
             "quantity"]).vfilter(lambda v: self.is_customer(v[0])).vapply(
                 lambda v: (v[0], floor(v[1] / self.unit), -round(v[2], 3))))
        # we initialize at 0 and increase when a truck arrives:
        arrivals = consumption.vapply(lambda v: np.zeros(self.horizon))
        for customer, time, quantity in arrivals_tup:
            arrivals[customer][time] += quantity

        # we take advantage of both pytups broadcasting and numpys broadcasting
        # then we accumulate over periods
        stocks = (consumption + arrivals + initial_tank).vapply(np.cumsum)
        site_inventories = SuperDict()
        for _id, quantity_arr in stocks.items():
            site_inventories[_id] = dict(tank_quantity=quantity_arr,
                                         location=_id)
        return site_inventories