Я пытаюсь закодировать периодическую проблему маршрутизации транспортных средств с некоторыми ограничениями запасов в AMPL.Я хотел бы динамически добавлять ограничения подуровня.Для того, чтобы сделать это, я был вдохновлен этой формулировкой для TSP:
https://groups.google.com/d/msg/ampl/mVsFg4mAI1c/ZdfRHHRijfUJ
Однако я не могу заставить ее устранить субтуры в моей модели.Я использовал следующее в моем файле модели.
param T; # Number of time-periods
param V; # Number of vehicles
param F; # Number of fuel types
set P ordered; # Number of gas stations
param hpos {P} >= 0;
param vpos {P} >= 0;
set PAIRS := {p in P, j in P};
param dist {(p,j) in PAIRS}
:= sqrt((hpos[j]-hpos[p])**2 + (vpos[j]-vpos[p])**2);
# A binary variable to determine if an arc is traversed.
var H{(p,j) in PAIRS, v in 1..V, t in 1..T} binary;
# A binary variable to determine if a delivery of fuel is made to a station in a given time period.
var StationUsed{p in P, f in 1..F, v in 1..V, t in 1..T} binary;
minimize TransportationCost:
sum {(p,j) in PAIRS} sum {v in 1..V, t in 1..T} dist[p,j] * H[p,j,v,t];
param nSubtours >= 0 integer;
set SUB {1..nSubtours} within P;
subject to Subtour_Elimination {k in 1..nSubtours, m in SUB[k], v in 1..V, t in 1..T, f in 1..F}:
sum {p in SUB[k], j in P diff SUB[k]}
if (p,j) in PAIRS then H[p,j,v,t] else H[j,p,v,t] >=2 * StationUsed[m,f,v,t] ;
Я добавил переменную StationUsed, так как моя проблема, в отличие от TSP, не должна посещать все узлы в каждый период времени.H - моя двоичная переменная решения, определяющая, движется ли транспортное средство по дуге (p, j) за период времени.
Затем я использовал формулировку, аналогичную TSP, в моем файле пробега:
set NEWSUB;
set EXTEND;
let nSubtours := 0;
repeat {
solve;
let NEWSUB := {};
let EXTEND := {member(ceil(Uniform(0,card(P))),P)};
repeat {
let NEWSUB := NEWSUB union EXTEND;
let EXTEND := {j in P diff NEWSUB: exists {p in NEWSUB, v in 1..V, t in 1..T}
((p,j) in PAIRS and H[p,j,v,t] = 1 or (j,p) in PAIRS and H[j,p,v,t] = 1)};
} until card(EXTEND) = 0;
if card(NEWSUB) < card(P) then {
let nSubtours := nSubtours + 1;
let SUB[nSubtours] := NEWSUB;
display SUB;
} else break;
};
# Display the routes
display {t in 1..T, v in 1..V}: {(p,j) in PAIRS} H[p,j,v,t];
Я не уверен, применимо ли вышеуказанное к моей проблеме с несколькими транспортными средствами и несколькими периодами времени.Я попытался определить v и t в let EXTEND, при этом необходимо использовать H, но я не уверен, что это правильный метод.Мои модели запускаются, если сформулированы, как указано выше, однако это не устраняет допуски.Ребята, есть ли у вас какие-либо предложения на этот счет?
ДОБАВЛЕННЫЙ ВОПРОС:
Я нашел вдохновение в этой модели, сформулированной в SAS / OR: (Немного обширно для чтения и не нужнодля моих вопросов)
http://support.sas.com/documentation/cdl/en/ormpex/67518/HTML/default/viewer.htm#ormpex_ex23_sect009.htm
Он динамически устраняет обходы в течение d дней, и я подумал, что это может быть связано с моей проблемой с несколькими транспортными средствами и несколькими периодами (днями).
Чтобы немного уточнить мою проблему.Узел может быть посещен только одним транспортным средством один раз за период времени.Не нужно посещать все узлы в каждый период времени, что является основным отличием от формулировки TSP, где все узлы находятся в цикле.
Я пытался использовать следующий подход:
Ограничение в файле модели такое же, как и раньше.
set P ordered; # Number of nodes
set PAIRS := {p in P, j in P: ord(p) != ord(j)};
param nSubtours >= 0 integer;
param iter >= 0 integer;
set SUB {1..nSubtours} within P;
subject to Subtour_Elimination {s in 1..nSubtours, k in SUB[s], f in F, v in V, t in T}:
sum {p in SUB[s], j in P diff SUB[s]}
if (p,j) in PAIRS then H[p,j,v,t] else H[j,p,v,t] >= 2 * StationUsed[k,f,v,t];
Мой файл запуска выглядит следующим образом:
let nSubtours := 0;
let iter := 0;
param num_components {V, T};
set P_TEMP;
set PAIRS_SOL {1..iter, V, T} within PAIRS;
param component_id {P_TEMP};
set COMPONENT_IDS;
set COMPONENT {COMPONENT_IDS};
param cp;
param cj;
# loop until each day and each vehicles support graph is connected
repeat {
let iter := iter + 1;
solve;
# Find connected components for each day
for {v in V, t in T} {
let P_TEMP := {p in P: exists {f in F} StationUsed[p,f,v,t] > 0.5};
let PAIRS_SOL[iter, v, t] := {(p,j) in PAIRS: H[p, j, v, t] > 0.5};
# Set each node to its own component
let COMPONENT_IDS := P_TEMP;
let num_components[v, t] := card(P_TEMP);
for {p in P_TEMP} {
let component_id[p] := p;
let COMPONENT[p] := {p};
};
# If p and j are in different components, merge the two component
for {(p,j) in PAIRS_SOL[iter, v, t]} {
let cp := component_id[p];
let cj := component_id[j];
if cp != cj then {
# update smaller component
if card(COMPONENT[cp]) < card(COMPONENT[cj]) then {
for {k in COMPONENT[cp]} let component_id[k] := cj;
let COMPONENT[cj] := COMPONENT[cj] union COMPONENT[cp];
let COMPONENT_IDS := COMPONENT_IDS diff {cp};
} else {
for {k in COMPONENT[cj]} let component_id[k] := cp;
let COMPONENT[cp] := COMPONENT[cp] union COMPONENT[cj];
let COMPONENT_IDS := COMPONENT_IDS diff {cj};
};
};
};
let num_components[v, t] := card(COMPONENT_IDS);
display num_components[v, t];
# create subtour from each component not containing depot node
for {k in COMPONENT_IDS: 1 not in COMPONENT[k]} { . #***
let nSubtours := nSubtours + 1;
let SUB[nSubtours] := COMPONENT[k];
display SUB[nSubtours];
};
};
display num_components;
} until (forall {v in V, t in T} num_components[v,t] = 1);
Я получаю много «недопустимого индекса» при запускемодель:
Ошибка в _cmdno 43 при выполнении команды «if» (файл amplin, строка 229, смещение 5372): набор обработки ошибок COMPONENT: недопустимый нижний индекс COMPONENT [4] отброшен.Ошибка в _cmdno 63 при выполнении команды «for» (файл amplin, строка 245, смещение 5951): набор обработки ошибок COMPONENT: недопустимый нижний индекс COMPONENT [3] отброшен.
(...) Выход из строя после 10 предупреждений.
Я думаю, что скрипт выполняет то, что я ищу, но останавливается, когда отбрасывает 10 недействительных подписок.
При попытке отладки я протестировал второй цикл for.
for {p in P_TEMP} {
let component_id[p] := p;
let COMPONENT[p] := {p};
display component_id[p];
display COMPONENT[p];
};
Это отображается правильно, но не раньше, чем появилось несколько ошибок с «сброшен неверный индекс».Кажется, что p проходит через некоторое p не в P_TEMP.Например, когда P_TEMP является набором, состоящим из узлов «1 3 4 5», тогда я получаю «сброшен неверный индекс» для component_id [2] и COMPONENT [2].Я предполагаю, что нечто подобное случается позже в заявлении IF-ELSE.
Как мне избежать этого?
Спасибо, Кристиан