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)
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