File size: 5,711 Bytes
db26c81 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
from greedrl.feature import *
from greedrl.variable import *
from greedrl.function import *
from greedrl import Problem
features = [local_category('task_group'),
global_category('task_priority', 2),
variable_feature('distance_this_to_task'),
variable_feature('distance_task_to_end')]
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_weight'),
feature_variable('task_group'),
feature_variable('task_priority'),
feature_variable('task_due_time2', feature='task_due_time'),
task_variable('task_due_time'),
task_variable('task_service_time'),
task_variable('task_due_time_penalty'),
worker_variable('worker_basic_cost'),
worker_variable('worker_distance_cost'),
worker_variable('worker_due_time'),
worker_variable('worker_weight_limit'),
worker_used_resource('worker_used_weight', task_require='task_weight'),
worker_used_resource('worker_used_time', 'distance_matrix', 'task_service_time', 'task_ready_time',
'worker_ready_time'),
edge_variable('distance_last_to_this', feature='distance_matrix', last_to_this=True),
edge_variable('distance_this_to_task', feature='distance_matrix', this_to_task=True),
edge_variable('distance_task_to_end', feature='distance_matrix', task_to_end=True)]
class Constraint:
def do_task(self):
return self.task_demand_this
def mask_worker_end(self):
return task_group_split(self.task_group, self.task_demand_now <= 0)
def mask_task(self):
mask = self.task_demand_now <= 0
mask |= task_group_priority(self.task_group, self.task_priority, mask)
worker_used_time = self.worker_used_time[:, None] + self.distance_this_to_task
mask |= (worker_used_time > self.task_due_time2) & (self.task_priority == 0)
# 容量约束
worker_weight_limit = self.worker_weight_limit - self.worker_used_weight
mask |= self.task_demand_now * self.task_weight > worker_weight_limit[:, None]
return mask
def finished(self):
return torch.all(self.task_demand_now <= 0, 1)
class Objective:
def step_worker_start(self):
return self.worker_basic_cost
def step_worker_end(self):
feasible = self.worker_used_time <= self.worker_due_time
return self.distance_last_to_this * self.worker_distance_cost, feasible
def step_task(self):
worker_used_time = self.worker_used_time - self.task_service_time
feasible = worker_used_time <= self.task_due_time
feasible &= worker_used_time <= self.worker_due_time
cost = self.distance_last_to_this * self.worker_distance_cost
return torch.where(feasible, cost, cost + self.task_due_time_penalty), feasible
def make_problem(batch_count, batch_size=1, task_count=100):
assert batch_size == 1
N = task_count // 2 # 订单数, 一个订单有pickup, delivery两个任务
problem_list = []
for i in range(batch_count):
problem = Problem()
problem.id = i
problem.worker_weight_limit = torch.tensor([50], dtype=torch.float32)
problem.worker_ready_time = torch.tensor([0], dtype=torch.float32)
problem.worker_due_time = torch.tensor([1000000], dtype=torch.float32)
problem.worker_basic_cost = torch.tensor([100], dtype=torch.float32)
problem.worker_distance_cost = torch.tensor([1], dtype=torch.float32)
task_demand = torch.randint(1, 10, (N,), dtype=torch.int32)
problem.task_demand = torch.cat([task_demand, task_demand], 0)
task_weight = torch.ones(N, dtype=torch.float32)
problem.task_weight = torch.cat([task_weight, task_weight * -1], 0)
task_group = torch.arange(N, dtype=torch.int32)
problem.task_group = torch.cat([task_group, task_group], 0)
task_priority = torch.zeros(N, dtype=torch.int32)
problem.task_priority = torch.cat([task_priority, task_priority + 1], 0)
task_ready_time = torch.zeros(N, dtype=torch.float32)
problem.task_ready_time = torch.cat([task_ready_time, task_ready_time], 0)
task_due_time = torch.randint(10000, 100000, (N,), dtype=torch.float32)
problem.task_due_time = torch.cat([task_due_time, task_due_time * 2], 0)
task_service_time = torch.zeros(N, dtype=torch.float32)
problem.task_service_time = torch.cat([task_service_time, task_service_time])
task_due_time_penalty = torch.ones(N, dtype=torch.float32)
problem.task_due_time_penalty = torch.cat([task_due_time_penalty, task_due_time_penalty])
loc = torch.rand(N + 1, 2, dtype=torch.float32)
distance_matrix = torch.norm(loc[:, None, :] - loc[None, :, :], dim=2) * 1000
distance_matrix = distance_matrix.to(torch.float32)
index = torch.cat([torch.zeros(N + 1, dtype=torch.int64), torch.arange(N, dtype=torch.int64) + 1])
index1 = index[:, None]
index2 = index[None, :]
problem.distance_matrix = distance_matrix[index1, index2]
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)
|