Мой вопрос касается кода проблемы планирования проекта с ограничением ресурсов в cplex. Я пытаюсь применить к нему приоритетное прерывание

Я работаю над RCPSP и хочу применить к нему Preemption.
Я разделил продолжительность каждой задачи на равные части. Теперь после этого я не могу применить ограничения приоритета к каждой отдельной единице длительности задачи.

using CP;

int NbTasks = ...;
int NbRsrcs = ...;
range RsrcIds = 1..NbRsrcs;  

int Capacity[r in RsrcIds] = ...;    

tuple Task {                        
  key int id;
  int     pt;
  int     dmds[RsrcIds];
  {int}   succs;            
  {int}   pred;
}
{Task} Tasks=...;


tuple sub_task { 
  Task task; 
  int p_no;
 }

 {sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..t.pt  };  
 dvar interval itvs[t in Tasks]  size t.pt;
 dvar interval a[p in sub_activities] size 1;
 cumulFunction rsrcUsage[r in RsrcIds] = 
   sum (p in sub_activities: p.task.dmds[r]>0) pulse(a[p], p.task.dmds[r]);
 minimize max(t in Tasks) endOf(itvs[t]);

subject to {
  forall (r in RsrcIds)
  rsrcUsage[r] <= Capacity[r];
  forall (t1 in Tasks, t2id in t1.succs)
    endBeforeStart(itvs[t1], itvs[<t2id>]);
}     

execute {
  for (var p in sub_activities) {
    writeln("subactivity of " + p.task.id + " - " + p.p_no + " starts at " + a[p].start + " Ends at " + a[p].end);  
  } 
}

Заранее спасибо.


person Rahul Ghate    schedule 14.02.2019    source источник


Ответы (2)


Во-первых, вы должны добавить некоторые ограничения, которые говорят, что каждая задача, представленная интервалом itvs [t], охватывает набор отдельных действий a [‹t, i›], что-то вроде: span (itvs [t], all (i in 1. .t.pt) a [‹t, i›])

А затем предположим, что отдельные действия данной задачи t образуют цепочку с такими ограничениями, как: endBeforeStart (a [‹t, i-1›], [‹t, i›])

Но обратите внимание, что для этой превентивной версии проблемы вы потеряете один из основных интересов CP Optimizer, который заключается в том, что он избегает перечисления времени. Здесь, если задачи полностью вытеснены, вы должны разделить каждую задачу длительностью D на отдельные действия D. Если вы знаете, что у вас есть некоторые ограничения на приоритетное выполнение задач (например, что каждое отдельное действие имеет минимальную продолжительность, превышающую единицу времени), это можно использовать в модели для создания меньшего количества под-действий.

person Philippe Laborie    schedule 14.02.2019
comment
Отметил и большое спасибо, сэр, за вашу помощь. - person Rahul Ghate; 15.02.2019
comment
Чтобы уменьшить количество дополнительных действий, я определил две целочисленные переменные smin и smax, которые являются минимальной и максимальной продолжительностью дополнительных действий. Подзадача кортежа была объявлена ​​как {sub_task} sub_activities = {‹t, i› | t в Задачах, i в 1..t.pt div t.smin}; а переменная решения определяется как dvar interval a [p in sub_activities] необязательный размер p.task.smin..p.task.smax; и к приведенному выше коду добавлены некоторые ограничения. код продолжает работать и не предлагает решения. Не могли бы вы сообщить мне, какие изменения и ограничения нужно добавить? - person Rahul Ghate; 05.03.2019
comment
Не могли бы вы прикрепить полную модель? - person Philippe Laborie; 07.03.2019
comment
кортеж Задача {key int id; int pt; int dmds [RsrcIds]; {int} succs; int smin; int smax; } {Task} Задачи = ...; кортеж sub_task {Задача задача; int p_no;} {sub_task} sub_activities = {‹t, i› | t в Задачах, i в 1..t.pt div t.smin}; dvar interval itvs [t in Tasks] size t.pt; dvar interval a [p in sub_activities] необязательный размер p.task.smin..p.task.smax; cumulFunction rsrcUsage [r в RsrcIds] = сумма (p в sub_activities: p.task.dmds [r] ›0) pulse (a [p], p.task.dmds [r]); минимизировать max (p в sub_activities) endOf (a [p]); - person Rahul Ghate; 11.03.2019
comment
при условии {forall (r в RsrcIds) rsrcUsage [r] ‹= Capacity [r]; forall (t1 в задачах, t2id в t1.succs) endBeforeStart (itvs [t1], itvs [‹t2id›]); forall (t в задачах, i в 1..t.pt) span (itvs [t], all (i в 1..t.pt) a [‹t, i›]); forall (p в sub_activities) {forall (s in sub_activities: s.task == p.task && s.p_no == p.p_no + 1) {endBeforeStart (a [p], a [s]); присутствиеОф (а [s]) = ›присутствиеОф (а [р]); выполнить {for (var p in sub_activities) {writeln (subactivity of + p.task.id + - + p.p_no + start at + a [p] .start + End at + a [p] .end); }} - person Rahul Ghate; 11.03.2019

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

forall (t in Tasks) {
  sum(p in sub_activities: p.task==t) lengthOf(a[p]) == t.pt;
}

Кроме того, учитывая, что целочисленное деление округляет результат в меньшую сторону, вы можете пропустить некоторые вспомогательные действия, поэтому я бы предпочел использовать что-то вроде:

{sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..1+(t.pt div t.smin )}; 

Кроме того, размер охватывающих задач не может быть t.pt, но он будет больше, если приоритетное прерывание разрешено, поэтому он должен быть примерно таким:

dvar interval itvs[t in Tasks] size t.pt..H; // H being a large number

Наконец (но это только для того, чтобы немного ускорить разрешение), вы можете переформулировать выражение makepan в цели, используя интервалы, охватывающие задачи, а не части (это будет включать меньше переменных):

minimize max(t in Tasks) endOf(itvs[t]);

Кроме того, если у вас есть максимальная продолжительность для частей, вам необходимо предотвратить, чтобы две последовательные части были смежными (в противном случае, я полагаю, это будет считаться одной и той же частью), поэтому цепочка интервальных переменных для частей должна иметь минимальную задержку из 1:

forall(p in sub_activities){ 
  forall(s in sub_activities: s.task==p.task && s.p_no==p.p_no+1){ 
    endBeforeStart(a[p],a[s],1); 
    presenceOf(a[s])=> presenceOf(a[p]); 
  }
}
person Philippe Laborie    schedule 11.03.2019
comment
Сэр, в этой модели под-действия делятся на единицу продолжительности, и если дается минимальная задержка 1 (forall (p in sub_activities) {forall (s in sub_activities: s.task == p.task && s.p_no ==) p.p_no + 1) {endBeforeStart (a [p], a [s], 1); availabilityOf (a [s]) = ›presentOf (a [p]);}}) создает промежуток, который нежелателен. мы требуем, чтобы действия были разделены только тогда, когда их ресурсы ограничены, в противном случае они должны быть сохранены как единое целое. как мы можем сделать это? - person Rahul Ghate; 14.03.2019