Python 实现¶
from pathlib import Path
from optagent import OptModel, solve
def read_instance(filename):
lines = Path(filename).read_text(encoding="utf-8").splitlines()
header = lines[0].split()
n_tasks = int(header[2])
n_machines = int(header[3])
task_lengths = [int(value) for value in lines[1].split() if value != "0"]
if len(task_lengths) != n_tasks:
raise ValueError("task length count does not match the instance header")
return n_tasks, n_machines, task_lengths
def main(input_file, output_file=None, time_limit=5):
n_tasks, n_machines, task_lengths = read_instance(input_file)
makespan_lb = sum(task_lengths) // n_machines
model = OptModel()
# machine_tasks[k] contains exactly the tasks assigned to machine k.
machine_tasks = [
model.set(n_tasks)
for k in range(n_machines)
]
model.constraint(model.partition(machine_tasks))
lengths = model.array(task_lengths)
lengths_lambda = model.lambda_function(lambda task: lengths[task // 1])
machine_makespan = [
model.sum(tasks, lengths_lambda) for tasks in machine_tasks
]
makespan = model.max(machine_makespan)
model.minimize(makespan)
solution = solve(
model,
time_limit_s=float(time_limit),
objective_threshold={0: makespan_lb},
)
if not solution.feasible:
print(f"No feasible schedule found; Status = {solution.feasible}")
return solution
lines = []
for machine in range(n_machines):
items = machine_tasks[machine].value
line = (
f"Makespan machine {machine}: {machine_makespan[machine].value} | "
f"Items: {' '.join(map(str, items))}"
)
print(line)
lines.append(line)
if output_file is not None:
Path(output_file).write_text("\n".join(lines) + "\n", encoding="utf-8")
return solution
本地运行¶
在 notebook 所在目录执行以下 cell,即可调用并行机调度实例。
INSTANCE_DIR = Path.cwd() / "instances"
print("Instances:", INSTANCE_DIR)
solution_pms = main(INSTANCE_DIR / "p_cmax-n120-m3.txt", time_limit=1)