Ortools - Jobshop - изменение продолжительности задач в зависимости от их ранга на машине

Я работаю с вариантом проблемы мастерской, где я хочу изменить продолжительность задачи в зависимости от их назначения/ранга в расписании машины.

например простым случаем будет то, что первая задача, назначенная на машине, займет на 50% больше времени.

В более общем случае каждая n-я задача на машине потребует на X% больше времени.

Я читал об ограничениях каналов, но я не уверен, как их реализовать в этом сценарии или есть ли другие лучшие альтернативы. Любое направление будет высоко оценено.

Ниже приведен код, который я использую, или документация по инструментам для решения проблемы с магазином.

from __future__ import print_function

import collections

# Import Python wrapper for or-tools CP-SAT solver.
from ortools.sat.python import cp_model

def MinimalJobshopSat():
    """Minimal jobshop problem."""
    # Create the model.
    model = cp_model.CpModel()

    
    jobs_data = [  # task = (machine_id, processing_time).
        [(2, 1), (0, 1), (1, 1)],  # Job0
        [(0, 1), (1, 1)],  # Job1
        [(1, 1), (2, 1)]  # Job2
    ]
    
    machines_count = 1 + max(task[0] for job in jobs_data for task in job)
    all_machines = range(machines_count)
    
    # Computes horizon dynamically as the sum of all durations.
    horizon = sum(task[1] for job in jobs_data for task in job)
    
    # Named tuple to store information about created variables.
    task_type = collections.namedtuple('task_type', 'start end interval')
    # Named tuple to manipulate solution information.
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index duration')
    
    # Creates job intervals and add to the corresponding machine lists.
    all_tasks = {}
    machine_to_intervals = collections.defaultdict(list)
    
    for job_id, job in enumerate(jobs_data):
        for task_id, task in enumerate(job):
            machine = task[0]
            duration = task[1]
            suffix = '_%i_%i' % (job_id, task_id)
            start_var = model.NewIntVar(0, horizon, 'start' + suffix)
            end_var = model.NewIntVar(0, horizon, 'end' + suffix)
            interval_var = model.NewIntervalVar(start_var, duration, end_var,
                                                'interval' + suffix)
            all_tasks[job_id, task_id] = task_type(
                start=start_var, end=end_var, interval=interval_var)
            machine_to_intervals[machine].append(interval_var)
    
    # Create and add disjunctive constraints.
    for machine in all_machines:
        model.AddNoOverlap(machine_to_intervals[machine])
    
    # # Precedences inside a job.
    # Change constraint to only respect the project start date i.e. the first dummy task
    for job_id, job in enumerate(jobs_data):
        for task_id in range(len(job) - 1):
            model.Add(all_tasks[job_id, task_id + 1].start >= all_tasks[job_id, task_id].end)

Измененный вывод, который мы ожидаем для этого случая, будет следующим, где продолжительность первой задачи на каждой машине увеличивается на 50%.

Optimal Schedule Length: 4
Machine 0: job_1_0   job_0_1   
           [0,2]     [2,3]     
Machine 1: job_2_0   job_0_2   job_1_1   
           [0,2]     [2,3]     [3,4]     
Machine 2: job_0_0   job_2_1   
           [0,2]     [2,3]    

person Mehtab Pathan    schedule 13.08.2020    source источник


Ответы (1)


Посмотрите на это ограничение. создает ограничение схемы, которое выполняет транзитивное сокращение приоритетов в последовательность задач.

Теперь вы можете использовать начальный литерал каждой задачи, чтобы указать правильную продолжительность

model.Add(duration[i] == int(nominal_duration * 1.5)).OnlyEnforceIf(start_lit)
model.Add(duration[i] == nominal_duration).OnlyEnforceIf(start_lit.Not())
person Laurent Perron    schedule 13.08.2020