|
import json |
|
|
|
from greedrl import Problem, Solver |
|
from greedrl.feature import * |
|
from greedrl.variable import * |
|
|
|
features = [local_feature('task_area'), |
|
local_feature('task_roadway'), |
|
local_feature('task_area_group'), |
|
sparse_local_feature('task_item_id', 'task_item_num'), |
|
sparse_local_feature('task_item_owner_id', 'task_item_num'), |
|
variable_feature('worker_task_item'), |
|
variable_feature('worker_used_roadway'), |
|
variable_feature('worker_used_area')] |
|
|
|
variables = [task_demand_now('task_demand_now', feature='task_demand'), |
|
task_demand_now('task_demand_this', feature='task_demand', only_this=True), |
|
feature_variable('task_item_id'), |
|
feature_variable('task_item_num'), |
|
feature_variable('task_item_owner_id'), |
|
feature_variable('task_area'), |
|
feature_variable('task_area_group'), |
|
feature_variable('task_load'), |
|
feature_variable('task_group'), |
|
worker_variable('worker_load_limit'), |
|
worker_variable('worker_area_limit'), |
|
worker_variable('worker_area_group_limit'), |
|
worker_task_item('worker_task_item', item_id='task_item_id', item_num='task_item_num'), |
|
worker_task_item('worker_task_item_owner', item_id='task_item_owner_id', item_num='task_item_num'), |
|
worker_used_resource('worker_used_load', task_require='task_load'), |
|
worker_used_resource('worker_used_area', task_require='task_area'), |
|
worker_used_resource('worker_used_roadway', task_require='task_roadway'), |
|
worker_used_resource('worker_used_area_group', task_require='task_area_group')] |
|
|
|
|
|
class Constraint: |
|
|
|
def do_task(self): |
|
return self.task_demand_this |
|
|
|
def mask_worker_end(self): |
|
return self.worker_used_load < self.worker_load_limit |
|
|
|
def mask_task(self): |
|
|
|
mask = self.task_demand_now <= 0 |
|
|
|
|
|
NT = self.task_item_id.size(1) |
|
worker_task_item = self.worker_task_item[:, None, :] |
|
worker_task_item = worker_task_item.expand(-1, NT, -1) |
|
task_item_in_worker = worker_task_item.gather(2, self.task_item_id.long()) |
|
task_item_in_worker = (task_item_in_worker > 0) & (self.task_item_num > 0) |
|
|
|
worker_task_item_owner = self.worker_task_item_owner[:, None, :] |
|
worker_task_item_owner = worker_task_item_owner.expand(-1, NT, -1) |
|
task_item_owner_in_worker = worker_task_item_owner.gather(2, self.task_item_owner_id.long()) |
|
task_item_owner_in_worker = (task_item_owner_in_worker > 0) & (self.task_item_num > 0) |
|
|
|
|
|
mask |= torch.any(task_item_in_worker & ~task_item_owner_in_worker, 2) |
|
|
|
worker_load_limit = self.worker_load_limit - self.worker_used_load |
|
mask |= (self.task_load > worker_load_limit[:, None]) |
|
|
|
task_area = self.task_area + self.worker_used_area[:, None, :] |
|
task_area_num = task_area.clamp(0, 1).sum(2, dtype=torch.int32) |
|
mask |= (task_area_num > self.worker_area_limit[:, None]) |
|
|
|
tak_area_group = self.task_area_group + self.worker_used_area_group[:, None, :] |
|
tak_area_group_num = tak_area_group.clamp(0, 1).sum(2, dtype=torch.int32) |
|
mask |= (tak_area_group_num > self.worker_area_group_limit[:, None]) |
|
|
|
return mask |
|
|
|
def finished(self): |
|
return torch.all(self.task_demand_now <= 0, 1) |
|
|
|
|
|
class Objective: |
|
|
|
def step_worker_end(self): |
|
area_num = self.worker_used_area.clamp(0, 1).sum(1) |
|
roadway_num = self.worker_used_roadway.clamp(0, 1).sum(1) |
|
item_num = self.worker_task_item.clamp(0, 1).sum(1) |
|
penalty = (self.worker_load_limit - self.worker_used_load) * 10 |
|
return area_num * 100 + roadway_num * 10 + item_num + penalty |
|
|
|
|
|
def make_problem_from_json(data): |
|
if isinstance(data, str): |
|
data = json.loads(data) |
|
problem = Problem() |
|
problem.id = data["id"] |
|
if 'uuid' in data: |
|
problem.uuid = data["uuid"] |
|
|
|
problem.task_item_id = torch.tensor(data["task_item_id"], dtype=torch.int32) |
|
problem.task_item_owner_id = torch.tensor(data["task_item_owner_id"], dtype=torch.int32) |
|
problem.task_item_num = torch.tensor(data["task_item_num"], dtype=torch.int32) |
|
problem.task_area = torch.tensor(data["task_area"], dtype=torch.int32) |
|
problem.task_roadway = torch.tensor(data["task_roadway"], dtype=torch.int32) |
|
problem.task_out_stock_time = torch.tensor(data["task_out_stock_time"], dtype=torch.int32) |
|
problem.task_area_group = torch.tensor(data["task_area_group"], dtype=torch.int32) |
|
|
|
NT = problem.task_item_id.size(0) |
|
problem.task_load = torch.ones(NT, dtype=torch.int32) |
|
problem.task_group = torch.zeros(NT, dtype=torch.int32) |
|
problem.task_demand = torch.ones(NT, dtype=torch.int32) |
|
|
|
problem.worker_load_limit = torch.tensor(data["worker_load_limit"], dtype=torch.int32) |
|
problem.worker_area_limit = torch.tensor(data["worker_area_limit"], dtype=torch.int32) |
|
problem.worker_area_group_limit = torch.tensor(data["worker_area_group_limit"], dtype=torch.int32) |
|
|
|
problem.features = features |
|
problem.variables = variables |
|
problem.constraint = Constraint |
|
problem.objective = Objective |
|
|
|
return problem |
|
|
|
|
|
def make_problem(batch_count, batch_size=1, task_count=100): |
|
assert batch_size == 1 |
|
|
|
NT = task_count |
|
problem_list = [] |
|
for i in range(batch_count): |
|
problem = Problem() |
|
problem.id = i |
|
|
|
device = Solver().device |
|
p = torch.ones(NT, 1000, dtype=torch.float32, device=device) |
|
problem.task_item_id = torch.multinomial(p, 10).to(torch.int32).cpu() |
|
problem.task_item_owner_id = torch.multinomial(p, 10).to(torch.int32).cpu() |
|
problem.task_item_num = torch.randint(0, 5, (NT, 10), dtype=torch.int32) |
|
problem.task_area = torch.randint(0, 5, (NT, 10), dtype=torch.int32).clamp(0, 1) |
|
problem.task_roadway = torch.randint(0, 5, (NT, 200), dtype=torch.int32).clamp(0, 1) |
|
problem.task_area_group = torch.randint(0, 5, (NT, 10), dtype=torch.int32).clamp(0, 1) |
|
|
|
problem.task_load = torch.ones(NT, dtype=torch.int32) |
|
problem.task_group = torch.zeros(NT, dtype=torch.int32) |
|
problem.task_demand = torch.ones(NT, dtype=torch.int32) |
|
|
|
problem.worker_load_limit = torch.tensor([20], dtype=torch.int32) |
|
problem.worker_area_limit = torch.tensor([10], dtype=torch.int32) |
|
problem.worker_area_group_limit = torch.tensor([10], dtype=torch.int32) |
|
|
|
problem.features = features |
|
problem.variables = variables |
|
problem.constraint = Constraint |
|
problem.objective = Objective |
|
|
|
problem_list.append(problem) |
|
|
|
return problem_list |
|
|
|
|
|
if __name__ == '__main__': |
|
import sys |
|
import os.path as osp |
|
sys.path.append(osp.join(osp.dirname(__file__), '../')) |
|
import runner |
|
|
|
runner.run(make_problem) |
|
|