Комплексний підхід до основних ґендерних питань у сфері безпеки та гігієни праці
ГЕНЕРИСАЊЕ ОСНОВНИХ КОМБИНАТОРНИХ ОБЈЕКАТА
description
Transcript of ГЕНЕРИСАЊЕ ОСНОВНИХ КОМБИНАТОРНИХ ОБЈЕКАТА
ГЕНЕРИСАЊЕ ГЕНЕРИСАЊЕ ОСНОВНИХ ОСНОВНИХ
КОМБИНАТОРНИХ КОМБИНАТОРНИХ ОБЈЕКАТАОБЈЕКАТА
др Ђура Паунићдр Ђура ПаунићДепартман за математику и Департман за математику и
информатику, ПМФ Нови информатику, ПМФ Нови СадСад
Генерисање основних Генерисање основних комбинаторних објекатакомбинаторних објеката
Комбинаторни објекти су врло Комбинаторни објекти су врло погодни за програмирање:погодни за програмирање:
• Захтевају врло мало предзнање за Захтевају врло мало предзнање за формулацију и схватање проблема.формулацију и схватање проблема.
• Поступци су алгоритамске природе Поступци су алгоритамске природе тако да је њихово програмирање тако да је њихово програмирање једноставно.једноставно.
• Ручно генерисање комбинаторних Ручно генерисање комбинаторних објеката је врло досадно и лако се објеката је врло досадно и лако се греши.греши.
Погодни примери у Погодни примери у наставинастави
Комбинације без понављањаКомбинације без понављања Комбинације са понављањемКомбинације са понављањем Варијације са понављањемВаријације са понављањем Пермутације у лексикографском Пермутације у лексикографском
пореткупоретку Општи поступак генериања Општи поступак генериања
комбинаторних објеката бектрекомкомбинаторних објеката бектреком Краљице на шаховској табли.Краљице на шаховској табли.
Комбинације без Комбинације без понављањапонављања
Када се комбинације без понављања Када се комбинације без понављања уреде, коришћењем лексикографског уреде, коришћењем лексикографског
поретка,поретка,
тада се добија следећи низ:тада се добија следећи низ:
(1, 2, 3) (1, 2, 3) (1, 2, 4) (1, 2, 4) (1, 2, 5) (1, 2, 5)
(1, 3, 4) (1, 3, 4) (1, 3, 5) (1, 3, 5) (1, 4, 5) (1, 4, 5)
(2, 3, 4) (2, 3, 4) (2, 3, 5) (2, 3, 5) (2, 4, 5) (2, 4, 5)
(3, 4, 5) (3, 4, 5)
Комбинације без Комбинације без понављањапонављања
(1, 2, 3) (1, 2, 4) (1, (1, 2, 3) (1, 2, 4) (1, 2, 5)2, 5)
Комбинације без Комбинације без понављањапонављања
(1, 3, 4) (1, 3, 5) (1, (1, 3, 4) (1, 3, 5) (1, 4, 5)4, 5)
Комбинације без Комбинације без понављањапонављања
(2, 3, 4) (2, 3, 5) (2, (2, 3, 4) (2, 3, 5) (2, 4, 5)4, 5)
Комбинације без Комбинације без понављањапонављања
(3, 4, 5)(3, 4, 5)
Комбинације без Комбинације без понављањапонављања
constconst maxnmaxn = 20; = 20;typetype niz = array[0 .. maxn] of integer;niz = array[0 .. maxn] of integer;
procedure print(var a : niz;procedure print(var a : niz; k : integer);k : integer);varvar j : integer;j : integer;beginbegin for j := 1 to k dofor j := 1 to k do write(a[j]:4);write(a[j]:4); writelnwritelnend; (* print*) end; (* print*)
Комбинације без Комбинације без понављањапонављања
procedure kombinacije(n, k : integer;procedure kombinacije(n, k : integer;
var ok : boolean);var ok : boolean);
varvar
a : niz;a : niz;
i : integer;i : integer;
beginbegin
if (1 <= n) and (k <= maxn) and if (1 <= n) and (k <= maxn) and
(1 <= k) and (k <= n)(1 <= k) and (k <= n)
thenthen
beginbegin ok := true;ok := true; i := 1;i := 1; a[1] := 0;a[1] := 0; while i > 0 do beginwhile i > 0 do begin while a[i] < n – k + i do beginwhile a[i] < n – k + i do begin a[i] := a[i] + 1;a[i] := a[i] + 1; if i < k then beginif i < k then begin a[i+1] := a[i];a[i+1] := a[i]; i := i + 1i := i + 1 endend else else print(a, k)print(a, k) end;end; i := i - 1i := i - 1 endendendendelseelse ok := falseok := falseend; (* kombinacije *)end; (* kombinacije *)
Рекурзивне комбинације Рекурзивне комбинације без понављањабез понављања
Рекурзивне процедуре се најлакше Рекурзивне процедуре се најлакше реализују тако да се направи реализују тако да се направи унутрашња рекурзивна процедура, а у унутрашња рекурзивна процедура, а у процедури се изведе иницијализација процедури се изведе иницијализација и позове унутрашња процедураи позове унутрашња процедура
procedure rkombinacije(n, k : integer;procedure rkombinacije(n, k : integer;
var ok : integer);var ok : integer);
varvar
a : niz;a : niz;
i : integer;i : integer;
procedure nadji(i : integer);procedure nadji(i : integer);
beginbegin
if i <= k then beginif i <= k then begin
a[i] := a[i-1];a[i] := a[i-1];
while a[i] < n - k + i do beginwhile a[i] < n - k + i do begin
a[i] := a[i] + 1;a[i] := a[i] + 1;
nadji(i+1)nadji(i+1)
endend
endend
else else
print(a, k)print(a, k)
end; (* nadji *)end; (* nadji *)
beginbegin
if (1 <= n) and (k <= maxn) and if (1 <= n) and (k <= maxn) and
(1 <= k) and (k <= n) then(1 <= k) and (k <= n) then
beginbegin
ok := true;ok := true;
a[0] := 0;a[0] := 0;
nadji(1)nadji(1)
endend
elseelse
ok := falseok := false
end; (* rkombinacije *)end; (* rkombinacije *)
Комбинације са Комбинације са понављањемпонављањем
Комбинације са понављањем се Комбинације са понављањем се генеришу истим поступком као и генеришу истим поступком као и комбинације без понављања, јер комбинације без понављања, јер постоји бијекција између комбинација постоји бијекција између комбинација без понављања од без понављања од nn + + kk − 1 − 1 објекта објекта kk--те класе и комбинација са понављањем те класе и комбинација са понављањем од од nn објеката објеката kk-те класе.-те класе.
Ова бијекција се просто реализује Ова бијекција се просто реализује одузимањем редом бројева 0, 1, ..., одузимањем редом бројева 0, 1, ..., kk − − 1 1 од комбинација без понављањаод комбинација без понављања
Комбинације са Комбинације са понављањемпонављањем
(1, 2, 3), (1, 2, 3), (1, 2, 4), (1, 2, 4), (1, 2, 5), (1, 2, 5), (1, (1, 33, , 44), ), (1, (1, 33, , 55)),,
− − 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
(1, 1, 1), (1, 1, 1), (1, 1, 2), (1, 1, 2), (1, 1, 3), (1, 1, 3), (1, (1, 22, , 22), ), (1, (1, 22, , 33)),,
((11, , 44, , 55), ), ((22, , 33, , 44), ), ((22, , 33, , 55), ), ((22, , 44, , 55), ), ((33, , 44, , 55))..
− − 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 0 1 2 1 2
((11, , 33, , 33), ), ((22, , 22, , 22), (), (22, , 22, , 33), ), ((22, , 33, , 33), ), ((33, , 33, , 33))..
Рекурзивне комбинације Рекурзивне комбинације са понављањемса понављањем
procedure printp(var a : nizprocedure printp(var a : niz
k : integer);k : integer);
varvar
j : integer;j : integer;
beginbegin
for j := 0 to k - 1 dofor j := 0 to k - 1 do
write(a[j+1]-j:4);write(a[j+1]-j:4);
writelnwriteln
end; (* printp*)end; (* printp*)
procedure rpkombinacije(n, k : integer;procedure rpkombinacije(n, k : integer;
var ok : boolean);var ok : boolean);
varvar
a : niz;a : niz;
i : integer;i : integer;
procedure nadji(i : integer);procedure nadji(i : integer);
beginbegin
if i = k+1 then if i = k+1 then
printp(a, k)printp(a, k)
else beginelse begin
a[i] := a[i-1];a[i] := a[i-1];
while a[i] < n + i - 1 do beginwhile a[i] < n + i - 1 do begin
a[i] := a[i]+1;a[i] := a[i]+1;
nadji(i+1)nadji(i+1)
endend
endend
end; (* nadji *)end; (* nadji *)
beginbegin
if (1 <= n) and (1 <= k) and if (1 <= n) and (1 <= k) and
(k <= maxn) then begin(k <= maxn) then begin
ok := true;ok := true;
a[0] := 0;a[0] := 0;
nadji(1)nadji(1)
endend
elseelse
ok := falseok := false
end; (* pkombinacije *)end; (* pkombinacije *)
Варијације са Варијације са понављањемпонављањем
Лексикографским уређивањем Лексикографским уређивањем варијација са понављањем добија варијација са понављањем добија сесе следећи низследећи низ
111, 112, 113, 121, 122, 123, 111, 112, 113, 121, 122, 123,
131,131, 132, 133, 211, 212, 132, 133, 211, 212, 213, 213,
221, 222, 223, 231, 232, 233, 221, 222, 223, 231, 232, 233,
311, 312, 313, 321, 322, 323, 311, 312, 313, 321, 322, 323,
331, 332, 333.331, 332, 333.
procedure varip(n, k : integer);procedure varip(n, k : integer);
varvar
a : niz;a : niz;
i : integer;i : integer;
beginbegin
i := 1;i := 1;
a[1] := 0;a[1] := 0;
while i > 0 do beginwhile i > 0 do begin
while a[i] < n do beginwhile a[i] < n do begin
a[i] := a[i] + 1;a[i] := a[i] + 1;
if i < k then beginif i < k then begin a[i+1] := 0;a[i+1] := 0; i := i + 1i := i + 1 endend else else print(a, k)print(a, k) end;end; i := i - 1i := i - 1 endendend; (* varip *)end; (* varip *)
Варијације са Варијације са понављањемпонављањем
Примена варијација са Примена варијација са понављањемпонављањем
for i1 := dgr[1] to ggr[1] dofor i1 := dgr[1] to ggr[1] do
for i2 := dgr[2] to ggr[2] dofor i2 := dgr[2] to ggr[2] do
. . . . . . . . . . . . .. . . . . . . . . . . . .
for ik := dgr[k] to ggr[k] dofor ik := dgr[k] to ggr[k] do
obrada(k, i1, i2, ..., ik);obrada(k, i1, i2, ..., ik);
Нека је процедура Нека је процедура obradaobrada само само испис индексаиспис индекса
procedure obrada(var k : integer;procedure obrada(var k : integer;
var indeks : niz);var indeks : niz);
varvar
j : integer;j : integer;
beginbegin
for j := 1 to k dofor j := 1 to k do
write(indeks[j]:4);write(indeks[j]:4);
writelnwriteln
end; (* obrada *)end; (* obrada *)
procedure indeksi(k : integer;procedure indeksi(k : integer;
var dgr, ggr, indeks : niz);var dgr, ggr, indeks : niz);
varvar
i : integer;i : integer;
beginbegin
i := 1;i := 1;
indeks[1] := dgr[1] - 1;indeks[1] := dgr[1] - 1;
while i > 0 do beginwhile i > 0 do begin
while indeks[i] < ggr[i] do beginwhile indeks[i] < ggr[i] do begin
indeks[i] := indeks[i] + 1;indeks[i] := indeks[i] + 1;
if i < k then beginif i < k then begin
i := i + 1;i := i + 1;
indeks[i] := dgr[i] - 1indeks[i] := dgr[i] - 1
endend
elseelse
obrada(k, indeks)obrada(k, indeks)
end;end;
i := i - 1i := i - 1
endend
end; (* indeksi *)end; (* indeksi *)
ПермутацијеПермутацијеНека су пермутације уређене лексикографски.Нека су пермутације уређене лексикографски.
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 81 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
2 6 5 8 7 4 3 1 2 6 7 1 3 4 5 82 6 5 8 7 4 3 1 2 6 7 1 3 4 5 8 Почев од краја пермутације, уочимо низ Почев од краја пермутације, уочимо низ
растућих елемената (8 7 4 3 1). растућих елемената (8 7 4 3 1). Назовимо овај низ крајњи низ.Назовимо овај низ крајњи низ. У крајњем низу уочимо први елемент (7) који У крајњем низу уочимо први елемент (7) који
је већи од елемента испред крајњег низа (5) је већи од елемента испред крајњег низа (5) и заменимо та два елемента (7 8 5 4 3 1).и заменимо та два елемента (7 8 5 4 3 1).
Напишимо добијени крајњи низ (8 5 4 3 1) Напишимо добијени крајњи низ (8 5 4 3 1) у обрнутом редоследу (1 3 4 5 8).у обрнутом редоследу (1 3 4 5 8).
Процедура за пермутације у Процедура за пермутације у лексикографском уређењулексикографском уређењу
procedure LexiPerm(n : integer;procedure LexiPerm(n : integer;
var ok : boolean);var ok : boolean);
varvar
a : niz;a : niz;
i, j, k, pom : integer;i, j, k, pom : integer;
beginbegin
if (1 <= n) and (n <= maxn) then beginif (1 <= n) and (n <= maxn) then begin
ok := true;ok := true;
for i := 1 to n dofor i := 1 to n do
a[i] := i; a[i] := i;
repeatrepeat
print(a, n);print(a, n);
k := n - 1;k := n - 1;
while (k > 0) and (a[k] > a[k+1]) dowhile (k > 0) and (a[k] > a[k+1]) do
k := k - 1;k := k - 1;
if k > 0 then beginif k > 0 then begin
j := n;j := n;
while a[k] > a[j] dowhile a[k] > a[j] do
j := j - 1;j := j - 1;
pom := a[k];pom := a[k];
a[k] := a[j];a[k] := a[j];
a[j] := pom;a[j] := pom;
i := (n - k) div 2;i := (n - k) div 2;
for j := 1 to i do beginfor j := 1 to i do begin
pom := a[k+j];pom := a[k+j];
a[k+j] := a[n+1-j];a[k+j] := a[n+1-j];
a[n+1-j] := poma[n+1-j] := pom
endend
endend
until k = 0until k = 0
endend
elseelse
ok := falseok := false
end; (* LexiPerm *)end; (* LexiPerm *)
Рекурзивне Рекурзивне пермутацијепермутације
procedure rpermutacije(n : integer;procedure rpermutacije(n : integer;
var ok : boolean);var ok : boolean);
varvar
a : niz;a : niz;
i : integer;i : integer;
procedure nadji(i : integer);procedure nadji(i : integer);
varvar
mesto, temp : integer;mesto, temp : integer;
beginbegin
for mesto := i to n do beginfor mesto := i to n do begin
temp := a[i];temp := a[i];
a[i] := a[mesto];a[i] := a[mesto];
a[mesto] := temp;a[mesto] := temp;
if i < n thenif i < n then
nadji(i + 1)nadji(i + 1)
elseelse
print(a, n);print(a, n);
temp := a[i];temp := a[i];
a[i] := a[mesto];a[i] := a[mesto];
a[mesto] := tempa[mesto] := temp
endend
end; (* nadji *)end; (* nadji *)
beginbegin
if (1 <= n) and (n <= maxn) then if (1 <= n) and (n <= maxn) then
beginbegin
ok := true;ok := true;
for i := 1 to n dofor i := 1 to n do
a[i] := i;a[i] := i;
nadji(1)nadji(1)
endend
elseelse
ok := falseok := false
end; (* rpermutacije *)end; (* rpermutacije *)
Општи поступак Општи поступак претраживањапретраживања
Претходни алгоритми Претходни алгоритми
су углавном били специјални су углавном били специјални
случајеви решавања случајеви решавања следећег следећег
апстрактног проблема:апстрактног проблема:
У скупу свих могућих У скупу свих могућих n--торки, за произвољно торки, за произвољно n, треба , треба наћи скуп решења (бар једно наћи скуп решења (бар једно или све). или све).
При том се При том се n-торка -торка ((rr11,,rr22,...),,...), коначне, коначне, али неодређене дужине, назива али неодређене дужине, назива решење ако задовољава кретеријуме решење ако задовољава кретеријуме за проверу решења. Свака за проверу решења. Свака компонента компонента rrii припада коначном припада коначном скупу скупу SSii могућих елемената за ту могућих елемената за ту компоненту. Скупови компоненту. Скупови SSii могу за сваку могу за сваку компоненту бити различити.компоненту бити различити.
procedure backtrack;procedure backtrack;
varvar
i : integer;i : integer;
beginbegin
i := 1;i := 1;
dopustiv(T[1], S[1], r);dopustiv(T[1], S[1], r);
while i > 0 do beginwhile i > 0 do begin
while not prazan(T[i]) do beginwhile not prazan(T[i]) do begin
izaberi(r[i], T[i]);izaberi(r[i], T[i]);
izbaci(r[i], T[i]);izbaci(r[i], T[i]);
if proveriresenje(r) thenif proveriresenje(r) then
print(r);print(r);
i := i + 1;i := i + 1;
dopustiv(T[i], S[i], r)dopustiv(T[i], S[i], r)
end;end;
i := i - 1i := i - 1
endend
end; (* backtrack *)end; (* backtrack *)
procedure rbacktrack;procedure rbacktrack;
procedure proba(i : integer);procedure proba(i : integer);
beginbegin
dopustiv(T[i], S[i], r);dopustiv(T[i], S[i], r);
while not prazan(T[i]) do beginwhile not prazan(T[i]) do begin
izaberi(r[i], T[i]);izaberi(r[i], T[i]);
izbaci(r[i], T[i]);izbaci(r[i], T[i]);
if proveriresenje(r) thenif proveriresenje(r) then
print(r);print(r);
proba(i + 1)proba(i + 1)
endend
end; (* proba *)end; (* proba *)
beginbegin
proba(1)proba(1)
end; (* rbacktrack *)end; (* rbacktrack *)
Коришћење скупова није увек Коришћење скупова није увек погодно, јер ти скупови могу погодно, јер ти скупови могу бити врло велики. Како сваки бити врло велики. Како сваки коначан скуп може да се коначан скуп може да се линеарно уреди може се линеарно уреди може се претпоставити да су скупови претпоставити да су скупови SSii линеарно уређени. Тада је линеарно уређени. Тада је могуће алгоритам могуће алгоритам модификовати тако да се модификовати тако да се користи само најмањи елемент користи само најмањи елемент у скупу на следећи начин:у скупу на следећи начин:
procedure ebacktrack;procedure ebacktrack;
varvar
i : integer;i : integer;
beginbegin
i := 1;i := 1;
a[1] := - maxint;a[1] := - maxint;
a[i] := nadjisledeci(a[i],S[i],r);a[i] := nadjisledeci(a[i],S[i],r);
while i > 0 do beginwhile i > 0 do begin
while a[i] < granica[i] do beginwhile a[i] < granica[i] do begin
r[i] := a[i];r[i] := a[i];
a[i] := nadjisledeci(a[i],S[i],r);a[i] := nadjisledeci(a[i],S[i],r);
if proveriresenje(r) thenif proveriresenje(r) then
print(r);print(r);
i := i + 1;i := i + 1;
a[i] := - maxinta[i] := - maxint
a[i] := nadjisledeci(a[i],S[i],r) a[i] := nadjisledeci(a[i],S[i],r)
end;end;
i := i - 1i := i - 1
endend
end; (* ebacktrack *)end; (* ebacktrack *)
К Р А ЈК Р А ЈХвала на пажњиХвала на пажњи