def reset(self): # print("Rst!") if(self.env_config['training'] and self.env_config['init']=='rnd' and self.copy_world): self.world = self.copy_world elif(self.env_config['training'] and self.env_config['init']=='rst'): self.world.reset() else: self.world = WorldBuilder.create(80, 16) state, _ = self.state_calculator.world_to_state(self.world) if(Utils.get_demand_sampler()=='ONLINE'): self.set_retailer_step(0) # print(state) return state
def create(x = 80, y = 32): world = World(x, y) world.grid = [[TerrainCell(xi, yi) for yi in range(y)] for xi in range(x)] def default_economy_config(order_cost=0, initial_balance = initial_balance): return ProductUnit.EconomyConfig(order_cost, initial_balance) # facility placement map_margin = 4 size_y_margins = world.size_y - 2*map_margin supplier_x = 10 retailer_x = 70 n_supplies = Utils.get_supplier_num() suppliers = [] supplier_skus = [] supplier_sources = dict() for i in range(n_supplies): supplier_config = SupplierCell.Config(max_storage_capacity=Utils.get_supplier_capacity(i), unit_storage_cost=Utils.get_supplier_unit_storage_cost(i), fleet_size=Utils.get_supplier_fleet_size(i), unit_transport_cost=Utils.get_supplier_unit_transport_cost(i)) if n_supplies > 1: supplier_y = int(size_y_margins/(n_supplies - 1)*i + map_margin) else: supplier_y = int(size_y_margins/2 + map_margin) f = SupplierCell(supplier_x, supplier_y, world, supplier_config, default_economy_config() ) f.idx_in_config = i f.facility_info = Utils.get_supplier_info(i) f.facility_short_name = Utils.get_supplier_short_name() world.agent_echelon[f.id] = 0 world.place_cell(f) suppliers.append(f) sku_info_list = Utils.get_sku_of_supplier(i) for _, sku_info in enumerate(sku_info_list): bom = BillOfMaterials({}, sku_info['sku_name']) supplier_sku_config = ProductUnit.Config(sources=None, unit_manufacturing_cost=sku_info['cost'], sale_gamma=sku_info.get('sale_gamma', 10), bill_of_materials=bom) sku = SKUSupplierUnit(f, supplier_sku_config, default_economy_config(order_cost=f.facility_info['order_cost']) ) sku.idx_in_config = sku_info['sku_name'] f.sku_in_stock.append(sku) sku.distribution = f.distribution sku.storage = f.storage sku.sku_info = sku_info f.storage.try_add_units({sku_info['sku_name']: sku_info['init_stock']}) supplier_skus.append(sku) if sku_info['sku_name'] not in supplier_sources: supplier_sources[sku_info['sku_name']] = [] supplier_sources[sku_info['sku_name']].append(sku) world.agent_echelon[sku.id] = 0 # distribution n_echelon = Utils.get_num_warehouse_echelon() pre_warehouses = suppliers all_warehouses = [] warehouse_skus = [] pre_warehouse_sources = supplier_sources for echelon in range(n_echelon): echelon_gap = (retailer_x-supplier_x)/(n_echelon+1) echelon_x = int(supplier_x+(echelon+1)*echelon_gap) n_warehouses = Utils.get_warehouse_num(echelon) warehouses = [] warehouse_sources = dict() for i in range(n_warehouses): warehouse_config = WarehouseCell.Config(max_storage_capacity=Utils.get_warehouse_capacity(echelon, i), unit_storage_cost=Utils.get_warehouse_unit_storage_cost(echelon, i), fleet_size=Utils.get_warehouse_fleet_size(echelon, i), unit_transport_cost=Utils.get_warehouse_unit_transport_cost(echelon, i)) if n_warehouses > 1: warehouse_y = int(size_y_margins/(n_warehouses - 1)*i + map_margin) else: warehouse_y = int(size_y_margins/2 + map_margin) w = WarehouseCell(echelon_x, warehouse_y, world, warehouse_config, default_economy_config() ) w.idx_in_config = i w.echelon_level = echelon w.facility_info = Utils.get_warehouse_info(echelon, i) w.facility_short_name = Utils.get_warehouse_short_name(echelon) world.agent_echelon[w.id] = 1+echelon world.place_cell(w) warehouses.append(w) WorldBuilder.connect_cells(world, w, *pre_warehouses) sku_info_list = Utils.get_sku_of_warehouse(echelon, i) for _, sku_info in enumerate(sku_info_list): candidate_upstream_suppliers = pre_warehouse_sources[sku_info['sku_name']] upstream_suppliers = [] for s in candidate_upstream_suppliers: if i in s.facility.facility_info['downstream_facilities']: upstream_suppliers.append(s) bom = BillOfMaterials({sku_info['sku_name']: 1}, sku_info['sku_name']) warehouse_sku_config = ProductUnit.Config(sources=upstream_suppliers, unit_manufacturing_cost=sku_info.get('cost', 10), sale_gamma=sku_info.get('sale_gamma', 10), bill_of_materials=bom) sku = SKUWarehouseUnit(w, warehouse_sku_config, default_economy_config(order_cost= w.facility_info['order_cost']) ) sku.idx_in_config = sku_info['sku_name'] w.sku_in_stock.append(sku) sku.distribution = w.distribution sku.storage = w.storage sku.sku_info = sku_info warehouse_skus.append(sku) w.storage.try_add_units({sku_info['sku_name']: sku_info.get('init_stock', 0)}) if sku_info['sku_name'] not in warehouse_sources: warehouse_sources[sku_info['sku_name']] = [] warehouse_sources[sku_info['sku_name']].append(sku) world.agent_echelon[sku.id] = 1+echelon # update downstreaming sku list in supplier_list for s_sku in upstream_suppliers: s_sku.downstream_skus.append(sku) all_warehouses.extend(warehouses) pre_warehouse_sources = warehouse_sources pre_warehouses = warehouses # final consumers n_stores = Utils.get_store_num() stores = [] store_skus = [] for i in range(n_stores): store_config = RetailerCell.Config(max_storage_capacity=Utils.get_store_capacity(i), unit_storage_cost=Utils.get_store_unit_storage_cost(i), fleet_size=1000, unit_transport_cost=10) if n_stores > 1: retailer_y = int(size_y_margins/(n_stores - 1)*i + map_margin) else: retailer_y = int(size_y_margins/2 + map_margin) r = RetailerCell(retailer_x, retailer_y, world, store_config, default_economy_config() ) r.idx_in_config = i r.facility_info = Utils.get_store_info(i) r.facility_short_name = Utils.get_store_short_name() world.agent_echelon[r.id] = 1+n_echelon world.place_cell(r) stores.append(r) WorldBuilder.connect_cells(world, r, *pre_warehouses) sku_info_list = Utils.get_sku_of_store(i) for _, sku_info in enumerate(sku_info_list): candidate_upstream_warehouses = pre_warehouse_sources[sku_info['sku_name']] upstream_warehouses = [] for s in candidate_upstream_warehouses: if i in s.facility.facility_info['downstream_facilities']: upstream_warehouses.append(s) bom = BillOfMaterials({sku_info['sku_name']: 1}, sku_info['sku_name']) retail_sku_config = ProductUnit.Config(sources=upstream_warehouses, unit_manufacturing_cost=sku_info.get('cost', 10), sale_gamma=sku_info.get('sale_gamma', 10), bill_of_materials=bom) if Utils.get_demand_sampler() == "DYNAMIC_GAMMA": sku = SKUStoreUnit(r, retail_sku_config, default_economy_config(order_cost=r.facility_info['order_cost']) ) elif Utils.get_demand_sampler() == "GAMMA": sale_sampler = gamma_sale_sampler(i) sku = OuterSKUStoreUnit(r, retail_sku_config, default_economy_config(order_cost=r.facility_info['order_cost']), sale_sampler ) else: sale_sampler = online_sale_sampler(f"data/OnlineRetail/store{i+1}_new.csv") sku = OuterSKUStoreUnit(r, retail_sku_config, default_economy_config(order_cost=r.facility_info['order_cost']), sale_sampler ) sku.idx_in_config = sku_info['sku_name'] r.sku_in_stock.append(sku) sku.storage = r.storage sku.sku_info = sku_info r.storage.try_add_units({sku_info['sku_name']: sku_info.get('init_stock', 0)}) store_skus.append(sku) world.agent_echelon[sku.id] = 1+n_echelon # update downstreaming sku list in warehouse_list for w_sku in upstream_warehouses: w_sku.downstream_skus.append(sku) for facility in suppliers + all_warehouses + stores: world.facilities[facility.id] = facility for sku in supplier_skus + warehouse_skus + store_skus: world.facilities[sku.id] = sku if sku.sku_info.get('price', 0) > world.max_price: world.max_price = sku.sku_info.get('price', 0) world.total_echelon = Utils.get_total_echelon() return world
def visualization(env, policies, iteration, policy_mode, basestock=False): policy_mode = policy_mode # + f'_{iteration}' renderer = AsciiWorldRenderer() frame_seq = [] evaluation_epoch_len = env.env_config['evaluation_len'] starter_step = env.env_config['episod_duration']+env.env_config['tail_timesteps'] env.set_iteration(1, 1) # env.env_config.update({'episod_duration': evaluation_epoch_len, 'downsampling_rate': 1}) print( f"Environment: Producer action space {env.action_space_producer}, Consumer action space {env.action_space_consumer}, Observation space {env.observation_space}" , flush=True) obss = env.reset() if basestock: from scheduler.inventory_base_stock_policy import ConsumerBaseStockPolicy ConsumerBaseStockPolicy.facilities = env.world.facilities if Utils.get_demand_sampler()=='ONLINE': env.set_retailer_step(starter_step) _, infos = env.state_calculator.world_to_state(env.world) # policies = {} rnn_states = {} rewards = {} for agent_id in obss.keys(): # policies[agent_id] = load_policy(agent_id) rnn_states[agent_id] = policies[agent_id].get_initial_state() rewards[agent_id] = 0 # Simulation loop tracker = SimulationTracker(evaluation_epoch_len, 1, env.agent_ids()) print(f" === evaluation length {evaluation_epoch_len}, it will take about 1 min ....", flush=True) for epoch in range(evaluation_epoch_len): action_dict = {} for agent_id, obs in obss.items(): policy = policies[agent_id] action, new_state, _ = policy.compute_single_action(obs, state=rnn_states[agent_id], info=infos[agent_id], explore=False) action_dict[agent_id] = action # if agent_id.startswith('SKUStoreUnit') and Utils.is_consumer_agent(agent_id): # print(agent_id, action, rewards[agent_id]) # print(obs.tolist()) obss, rewards, dones, infos = env.step(action_dict) step_balances = {} for agent_id in rewards.keys(): step_balances[agent_id] = env.world.facilities[Utils.agentid_to_fid(agent_id)].economy.step_balance.total() # print(env.world.economy.global_balance().total(), step_balances, rewards) tracker.add_sample(0, epoch, env.world.economy.global_balance().total(), step_balances, rewards) # some stats stock_status = env.get_stock_status() order_in_transit_status = env.get_order_in_transit_status() demand_status = env.get_demand_status() tracker.add_sku_status(0, epoch, stock_status, order_in_transit_status, demand_status) frame = renderer.render(env.world) frame_seq.append(np.asarray(frame)) print(tracker.get_retailer_profit()) if not os.path.exists('output'): os.mkdir('output') if not os.path.exists('output/%s' % policy_mode): os.mkdir('output/%s' % policy_mode) if not os.path.exists(f'output/{policy_mode}/iter_{iteration}'): os.mkdir(f'output/{policy_mode}/iter_{iteration}') # tracker.render("output/%s/plot.png" % policy_mode) tracker.render(f'output/{policy_mode}/iter_{iteration}/plot.png') tracker.render_sku(policy_mode, iteration) print(f" === evaluation length end ", flush=True)