Uklapanje pravougaonih dvodimenzionalnih elemenata na ortogonalnoj tabli


Izvori Wikipedia, besplatna enciklopedija

Heuristika

Packing problem

Problem pakovanja u prostoru

A least wasted first heuristic algorithm for the rectangular packing problem

Rešavanje problema uklapanja dvodimenzionalnih pravougaonih elemenata na ortogonalnoj tabli podrazumeva uklapanje određenog broja elemenata na jednoj tabli fiksnih dimenzija tako da površina table bude maksimalno popunjena elementima, a da pri tome vreme neophodno za uklapanje bude što kraće. Kao rešenje ovog problema napisana su četiri algoritma koji su implementirani kroz programski kod u kompjuterskom programu koji je razvijen zbog testiranja njihovog kvaliteta. Program kao i otvoreni programski kod koji sadrži opis algoritama možete preuzeti na linkovima koji se nalaze na dnu ove stranice. Algoritmi ugrađeni u program su razvijeni pomoću Heurističkih metoda i ne predstavljaju potpuno rešenje ovog problema zasnovano na sveobuhvatnoj naučnoj, matematičkoj analizi.

Termin Heuristika ( Grčki - "Εὑρίσκω" , Srpski - "pronađi" ili "otkrij" ) se odnosi na rešavanje problema, učenja i otkrivanja, metodama i tehnikama zasnovanim na iskustvu. Ove tehnike se koriste da ubrzaju proces pronalaženja zadovoljavajućeg, delimičnog rešenja problema u slučajevima kada sveobuhvatno istraživanje za pronalaženje potpunog, optimalnog rešenja problema nije pratktično. Najpoznatija Heuristička metoda jeste metoda 'probe i greške' koja može da se koristi za rešavanje većine svakodnevnih problema.

Za razvoj algoritma korišćene su klasične Heurističke metode :

  • Kada imate teškoća sa shvatanjem problema, pokušajte da nacrtate sliku ( predstavite problem vizuelno )

  • Kada ne možete da pronađete rešenje, probajte da predpostavite da imate rešenje i vidite šta možete da zaključite iz toga ( ovo je takozvano “proučavanje problema u nazad” )

  • Ako je problem isuviše uopšten, pokušajte da ga proučite kroz konkretan primer

  • Pokušajte prvo da rešite kompleksniji deo problema ( takozvani “paradoks pronalazača” - ambiciozniji plan može da ima veće šanse za uspeh )

Posmatranje procesa uklapanja elemenata

Za potrebe procesa uklapanja elemenata neophodni su nam:

JEDNA TABLA,

NIZ od n ELEMENATA ( n >= 1 i n <= i ) .

Tablu i elemente karakteriši DUŽINA i ŠIRINA.

Ove dve karakteristike sa svojim vrednostima se nazivaju DIMENZIJE.

Sam pojam 'DUŽINA' ne podrazumeva veću vrednost u odnosu na 'ŠIRINU'.

Opsezi vrednosti za dimenzije table :

dužina table ( D > 0 i D <= m)

širina table ( Š > 0 i Š <= k)

Opsezi vrednosti za dimenzije elemenata :

dužina elementa ( d > 0 i d<= D ) element ne sme da ima veću dužinu od dužine table .

širina elementa( š > 0 i š<= Š ) element ne sme da ima veću širinu od širine table.

Grafički prikaz table i elemenata :

Zbog preciznosti ceo proces uklapanja ćemo posmatrati u okviru XY koordinatnog sistema.

Posle pet pokušaja uklapanja elemenata na tabli dolazimo do nekoliko bitnih saznanja :

Tabla pre uklapanja može da se pozicionira bilo gde u okviru koordinatnog sistema i orijentiše horizontalno ili vertikalno u odnosu na koordinatni sistem. Horizontalna orijentacija je slučaj kada se tabla svojom dužom stranom oslanja na X osu. Vertikalna orijentacija je slučaj kada se tabla svojom dužom stranom oslanja na Y osu. Orijentacija i raspored elemenata pre uklapanja nisu bitni. Elementi u toku uklapanja mogu da se rotiraju i uklapaju horizontalno ili vertikalno. Uklapanje elemenata na tabli može biti nasumično ili redom duž X ili duž Y ose koordinatnog sistema, na slobodnoj površini table koju ćemo nazvati POZICIJA za uklapanje. Pod slobodnom površinom table, POZICIJOM za uklapanje podrazumeva se onaj deo table na koji može da se uklopi neki od preostalih elemenata, a na kome se već ne nalazi nijedan od predhodno uklopljenih elemenata. Sam oblik pozicije ne mora da bude četvorougaon, kao elementi. Odabir elementa koji će sledeći biti uklopljen zavisi od mogućnosti elementa da se uklopi na posmatranu poziciju. Kada postoji više elemenata koji mogu da se uklope na posmatranoj poziciji, odabir je po slučajnom principu. Neophodno je pakovati elemente kompaktno, jedan do drugog, uz podudaranje dimenzija elemenata i dimenzija pozicije kako bi površina table bila bolje popunjena. Uklapanje je završeno onda kada više nema elemenata za uklapanje, svi elementi su uklopljeni ili kada je tabla potpuno popunjena, površina uklopljenih elemenata je jednaka površini table ili kada više nema odgovarajućih pozicija na tabli za uklapanje elemenata, na slobodnoj površini na tabli nije moguće uklopiti nijedan od preostalih elemenata. Algoritam koji bi trebalo napraviti na osnovu predhodnih zapažanja je suviše kompleksan tako da u daljem proučavanju ovog problema uvodimo sledeća ograničenja :

Tabla je postavljena u koordinatni početak koordinatnog sistema i horizontalno orijentisana. Elementi su pre uklapanja orijentisani horizontalno i poređani po veličini površine od najvećeg ka najmanjem. Elementi u toku uklapanja ne smeju da se rotiraju. Uklapanje elemenata mora biti redom duž X ose table, isključivo s horizontalnom orijentacijom.

Uslovi za pronalaženje slobodnih pozicija u skladu sa zahtevom za način uklapanja elemenata :

Slobodna pozicija mora da bude četvorougaonog oblika, s određenim koordinatama donjeg levog ugla, dužinom i širinom, na koju može da se uklopi makar jedan od preostalih elemenata za uklapanje. Koordinate pozicije mogu isključivo da budu iste kao koordinate donjeg desnog ili gornjeg levog ugla predhodno uklopljenog elementa. Ukoliko je pozicija drugačijeg oblika neophodno je izvršiti prilagođavanje površine pozicije. Ovo se radi tako što se od posmatrane pozicije pravi više novih pozicija koje moraju da ispune predhodne uslove. Ako novonastale pozicije ne ispunjavaju uslove bivaju odbačene. Redosled pozicija se određuje na osnovu vrednosti koordinata donjeg levog ugla pozicije, prvo po Y, a zatim po X osi. Ovakav redosled pozicija omogućava da se elementi uklapaju na način kao što je određeno. Kada više nema slobodnih pozicija uklapanje se završava.

Uslovi za izbor sledećeg elementa za uklapanje :

Sledeći element za uklapanje bira se na osnovu izračunate vrednosti za procenat uklapanja elementa za posmatranu poziciju. Početni procenat uklapanja svih elemenata je nula. Ako element sa svojim dimenzijama može da se smesti u posmatranu poziciju, procenat uklapanja se uvećava za jedan. Ako element ima istu vrednost za dužinu kao i pozicija, procenat uklapanja se uvećava za jedan. Favorizujemo one elemente koji se tačno uklapaju po dužini pozicije. Ako element ima istu vrednost za širinu kao i pozicija, procenat uklapanja se uvećava za jedan. Favorizujemo one elemente koji se tačno uklapaju po širini pozicije. Kada se izračunaju vrednosti za procenat uklapanja za sve elemente, oni se poređaju na osnovu iste. Ukoliko ima više elemenata s istim vrednostima za procenat uklapanja, redosled se odredi na osnovu površine, a zatim na osnovu dužine elementa. Biramo prvi element u nizu i ukoliko je procenat uklapanja elementa veći od nule uklapamo ga na poziciju tako da se donji levi ugao elementa poklopi s donjim levim uglom pozicije. Ukoliko je procenat uklapanja elementa jednak nuli, to znači da nema elemenata koji mogu da se uklope na posmatranu poziciju i ta pozicija se odbacuje. Kada više nema elemenata, uklapanje se završava.

Primer uklapanja :

Sobzirom da je na početku uklapanja tabla prazna, prva slobodna pozicija je u stvari celokupna površina table s donjim levim uglom smeštenim u koordinatnom početku koordinatnog sistema. Izračunat procenat uklapanja svih elemenata je jedan, pa biramo onaj s najvećom površinom, a to je element broj jedan. Kad ga smestimo u donji levi ugao pozicije, dobijamo slobodnu površinu koja ne ispunjava uslov za novu poziciju zbog svog oblika pa ga moramo prilagoditi. To radimo tako što ga delimo na najlogičniji način, u skladu sa zahtevom za način uklapanja elemenata, duž X ose od gornjeg desnog ugla elementa broj jedan do desne ivice pozicije jedan. Sada smo dobili dve nove pozicije za uklapanje koje su poređane kao što je određeno u uslovima za nove pozicije. Predhodna pozicija broj jedan je izbrisana s liste pozicija.

Sledi uklapanje elemenata na novonastalu poziciju jedan. Od preostalih elemenata odabran je element broj 2. Kada ga uklopimo dobijamo približno isti oblik slobodne površine za nove pozicije kao i u predhodnom slučaju, pa primenjujemo isti način prilagođavanja slobodne površine. Dobijamo dve nove pozicije. Kada sortiramo novonastale i već postojeće pozicije dobijemo redosled za uklapanje kao na slici ispod.

Uklapanje se nastavlja, uklapanjem preostalih elemenata i pronalaženjem novih pozicija na isti način kao u predhodnim slučajevima. Belom bojom je označena pozicija koja je odbačena jer u nju ne može da se uklopi ni jedan element po dužini.

Posle analize problema kroz grafičku prezentaciju, vrlo lako možemo napraviti algoritam. Ispod se vidi algoritam u vidu programskog koda koji je i ugrađen u program. U pitanju je funkcija 'int Algoritam1DužinaX()' koja vraća celobrojnu vrednost ukupne površine svih uklopljenih elemenata. Obratite pažnju na deo algoritma gde se vidi način izračunavanja koordinata i dimenzija novih pozicija.

int Algoritam1DužinaX()

{

//

// Uklapanje elemenata isključivo horizontalno duž X ose.

//

// Algoritam je jednoprolazan,

// a to znači da će se uklapanje svih elemenata izvršiti samo jednom.

// na osnovu počenog rasporeda elemenata.

//

// Izbor elemenata za uklapanje je na osnovu rasporeda,

// koji je dobijen, sortiranjem elemenata na osnovu

// vrednosti procenta uklapanja i dimenzija elemenata.

//

// Ovakav algoritam je najbrži za predviđeni način uklapanja elemenata,

// ali je procenat popunjenosti table u većini slučajeva mali i zavisi

// isključivo od procenta uklapanja elemenata na posmatranoj poziciji.

//

// Algoritam sadrži optimizaciju koja vrši prilagođavanje površine

// pozicije za uklapanje duž X ose.

//

int broj_elemenata;

int spakovana_površina; // suma vrednosti površina svih spakovanih elemenata

int brojač_elemenata;

int procenat_uklapanja_elementa;

int indeks_elementa;

int dužina_elementa;

int širina_elementa;

int površina_elementa;

int X; // X koordinata pozicije

int Y; // Y koordinata pozicije

int dužina_pozicije;

int širina_pozicije;

int Xmax;// maksimalna dužina pozicije

int Ymax;// maksimalna širina pozicije

int X11;

int Y11;

int dužina11;

int širina11;

int X12;

int Y12;

int dužina12;

int širina12;

spakovana_površina = 0;

// izbriši sadržaj tabele 'Spakovano1D',

// podaci o spakovanim elementima

Spakovano1D.Rows.Clear();

// izbriši sadržaj tabele 'Pozicije'

// podaci o slobodnim pozicijama za uklapanje elemenata

Pozicije.Rows.Clear();

// ubaci u tabelu 'Pozicije', koordinate i dimenzije početne pozicije na tabli

X = 0;

Y = 0;

Pozicije.Rows.Add(X.ToString("000"), // X koordinata

Y.ToString("000"), // Y koordinata

Tabla_X.ToString("000"), // dužina table

Tabla_Y.ToString("000") // širina table

);

// uklapaj sve dok postoje pozicije na koje mogu da se pakuju elementi

while(Pozicije.RowCount>1)

{

// uklapaj sve dok postoje elementi za uklapanje

broj_elemenata = ElementiKopija.RowCount;

if(broj_elemenata > 0)

{

// ubaci vrednosti za dužinu i širinu prve pozicije iz tabele 'Pozicije'

dužina_pozicije = int.Parse(Pozicije[2,0].Value.ToString());

širina_pozicije = int.Parse(Pozicije[3,0].Value.ToString());

// izračunaj procenat uklapanja za svaki element za prvu poziciju

for(brojač_elemenata=0;brojač_elemenata<broj_elemenata;brojač_elemenata++)

{

// dužina elementa

dužina_elementa = int.Parse(ElementiKopija[0,brojač_elemenata].Value.ToString());

// širina elementa

širina_elementa = int.Parse(ElementiKopija[1,brojač_elemenata].Value.ToString());

// početni procenat uklapanja prvog elementa

procenat_uklapanja_elementa = 0;

// da li su ne dozvoljene vrednosti dimenzija elementa

if( dužina_pozicije < dužina_elementa || širina_pozicije < širina_elementa )

{

// element nije uklopiv na posmatranu poziciju

procenat_uklapanja_elementa = 0 ;

}

else

{

// da li je element s horizontalnom orjentacijom

if(dužina_elementa>=širina_elementa)

{

// element može da se uklopi

procenat_uklapanja_elementa++;

// favorizuj tačno uklapanje po X osi

if( dužina_pozicije == dužina_elementa )

{

// ako je dužina elementa jednaka dužini pozicije

procenat_uklapanja_elementa++;

}

// favorizuj tačno uklapanje po Y osi

if( širina_pozicije == širina_elementa )

{

// ako je širina elementa jednaka širini pozicije

procenat_uklapanja_elementa++;

}

}

}

// ubaci vrednost procenta uklapanja za posmatrani element u tabelu

ElementiKopija[3,brojač_elemenata].Value = procenat_uklapanja_elementa.ToString("000");

}

// sortiraj elemente u tabeli na osnovu vrednosti

// procenta uklapanja i veličine površine i dužine

ElementiKopija.Sort(ElementiKopija.Columns[3], ListSortDirection.Descending);

// pročitaj vrednost procenta uklapanja prvog elementa u tabeli

procenat_uklapanja_elementa = int.Parse(ElementiKopija[3,0].Value.ToString());

// ako je prvi element na spisku s najvećom vrednošću za uklapanje veći od nule

if(procenat_uklapanja_elementa > 0)

{

// prvi element je uklopiv

// ubaci koordinate pozicije,

// dimenzije i indeks elementa

// na spisak spakovanih elemenata

Spakovano1D.Rows.Add(Pozicije[0,0].Value.ToString(),// X pozicije

Pozicije[1,0].Value.ToString(),// Y pozicije

ElementiKopija[0,0].Value.ToString(),// dužina elementa

ElementiKopija[1,0].Value.ToString(),// širina elementa

ElementiKopija[4,0].Value.ToString());// indeks

// suma vrednosti površna spakovanih elemenata

površina_elementa = int.Parse(ElementiKopija[2,0].Value.ToString());

spakovana_površina = spakovana_površina + površina_elementa;

//

X11 = 0;

Y11 = 0;

dužina11 = 0;

širina11 = 0;

X12 = 0;

Y12 = 0;

dužina12 = 0;

širina12 = 0;

// Pronađi nove pozicije ako postoje

X = int.Parse(Pozicije[0,0].Value.ToString());

Y = int.Parse(Pozicije[1,0].Value.ToString());

Xmax = int.Parse(Pozicije[2,0].Value.ToString());

Ymax = int.Parse(Pozicije[3,0].Value.ToString());

dužina_elementa = int.Parse(ElementiKopija[0,0].Value.ToString());

širina_elementa = int.Parse(ElementiKopija[1,0].Value.ToString());

// Ako je element kraći od dužine pozicije na kojoj je uklopljen

if(dužina_elementa<Xmax)

{

X11 = X + dužina_elementa;

Y11 = Y;

dužina11 = Tabla_X - X11;

širina11 = širina_elementa;

}

// Ako je element kraći od širine pozicije na kojoj je uklopljen

if(širina_elementa<Ymax)

{

X12 = X;

Y12 = Y + širina_elementa;

dužina12 = Tabla_X - X12;

širina12 = Ymax - širina_elementa;

// ako je pozicija neodgovarajuća,

// izbriši je i prilagodi ostatak površine za uklapanje

// ovo je prilagođavanje površine duž X ose

if(širina12<najmanja_širina_elementa)

{

širina11 = širina11 + širina12;

širina_elementa = Ymax;

}

}

// Ako je element kraći od dužine pozicije na kojoj je uklopljen

if(dužina_elementa<Xmax)

{

Pozicije.Rows.Add(X11.ToString("000"),

Y11.ToString("000"),

dužina11.ToString("000"),

širina11.ToString("000"));

}

// Ako je element kraći od širine pozicije na kojoj je uklopljen

if(širina_elementa<Ymax)

{

Pozicije.Rows.Add(X12.ToString("000"),

Y12.ToString("000"),

dužina12.ToString("000"),

širina12.ToString("000"));

}

// izbriši popunjenu poziciju sa spiska

Pozicije.Rows.RemoveAt(0);

// sortiraj preostale pozicije po Y, a zatim po X osi

Pozicije.Sort(Pozicije.Columns[1], ListSortDirection.Ascending);

// izbriši spakovan element sa spiska elemenata i sve njegove varijante po indeksu

broj_elemenata = ElementiKopija.RowCount;

indeks_elementa = int.Parse(ElementiKopija[4,0].Value.ToString());

for(brojač_elemenata=0;brojač_elemenata<broj_elemenata;brojač_elemenata++)

{

if(indeks_elementa.ToString("000") == ElementiKopija[4,brojač_elemenata].Value.ToString())

{

ElementiKopija.Rows.RemoveAt(brojač_elemenata);

broj_elemenata--;

brojač_elemenata--;

}

}

}

else

{

// procenat_uklapanja <= 0,

// ne postoji nijedan element,

// koji se može spakovati na prvu poziciju

// izbriši poziciju sa spiska

Pozicije.Rows.RemoveAt(0);

}

}

else

{

Pozicije.RowCount = 1;

}

}

broj_spakovanih_elemenata = Spakovano1D.RowCount - 1;

return spakovana_površina;

}

Na slici ispod možete videti kako izgleda raspored uklopljenih elemenata, u toku realnog rada programa s istovetnim uslovima za uklapanje elemenata kao i u predhodnom proučavanju problema. Primenjen je prvi algoritam koji je u opcijama označen kao 'Algoritam 1', pakovanje elemenata je duž X ose, s horizontalnom orijentacijom elemenata i prilagođavanjem pozicije za uklapanje.

Ovaj program je razvijen za potrebe ispitivanja različitih vrsta algoritama za uklapanje pravougaonih dvodimenzionalnih elemenata na jednoj ortogonalnoj tabli fiksnih dimenzija 600 x 400 piksela. Broj elemenata koje treba uklopiti je ograničen na stotinu elemenata. Dimenzije elemenata ne smeju da budu veće od dimenzija table na kojoj se vrši uklapanje, i manje od 10 x 10 piksela. Klikom na sliku programa započinjete preuzimanje besplatne verzije programa. Za ispravan rad programa neophodan je .Net framework 4.0 ( ^ ) ! Grafički korisnički interfejs programa se sastoji od nekoliko elementa preko kojih korisnik kontroliše rad programa. 'Raspored elemenata na tabli' zauzima najveći deo prozora programa i namenjen je za vizuelnu kontrolu pakovanja elemenata. Spakovani elementi su numerisani na osnovu rednog broja u tabeli 'Dimenzije elemenata' koja sadrži dimenzije svih elemenata koji treba da budu spakovani na tabli. 'Izbriši dimenzije' je dugme koje omogućava brisanje sadržaja tabele i resetovanje svih promenljivih unutar programa na inicijalne vrednosti. 'Učitaj dimenzije' je dugme koje omogućava učitavanje dimenzija elemenata u tabelu iz dokumenta 'Dimenzije elemenata.txt' koji se nalazi u folderu gde je i izvršna verzija programa. 'Uklopi' je dugme koje omogućava startovanje uklapanja elemenata na tabli.

'Statistika uklapanja elemenata' sadrži neke bitne vrednosti koje su nastale kao rezultat pakovanja elemenata. Broj uklopljenih elemenata od ukupnog broja elemenata i njihova ukupna površina. Vreme utrošeno za uklapanje elemenata koje se odnosi isključivo na rad samog algoritma za uklapanje, a ne i na vreme neophodno za prikaz rezultata. Procenat popunjenosti table. 'Opcije uklapanja elemenata' sadrže četiri algoritma za uklapanje elemenata i tri podopcije koje se odnose na način uklapanja elemenata na tabli i podešavanje željenog procenta popunjenosti table. Opis algoritama možete pronaći u okviru programskog koda. Podopcije 'Po osi table' i 'Orjentacija elemenata' određuju forsirani način uklapanja elemenata, kako im ime kaže, elementi će biti pakovani isključivo duž određene ose sa zadatom orjenacijom elementa. Željeni procenat popunjenosti table je vrednost koja utiče na rad programa, tako što program prekida uklapanje elemenata onda kada dostigne željeni procenat popunjenosti table bez obzira da li je moguće uklapanje elemenata sa većim procentom popunjenosti table. U realnom radu procenat popunjenosti može da bude veći od željenog, a u zavisnosti od takozvane 'upakljivosti' elemenata često dostiže svih sto procenata, vidi sliku iznad. Zbog sporosti rada kućnih kompjutera nije preporučljivo da vrednost željenog procenta popunjenosti table bude veća od 98%. Dostupnost ove tri podopcije zavisi od toga da li ih odabrani algoritam podržava ili ne. Konkretno prvi i drugi algoritam ne podržavaju opciju željeni procenat popunjenosti, a drugi i četvrti algoritam ne podržavaju opciju 'Orjentacija elemenata' jer imaju ugrađenu rotaciju elemenata u toku uklapanja zbog povećanja procenta popunjenosti table. Program sadrži 'Test meni' koji se aktivira desnim klikom u okviru koga su opcije za rad s generatorom dimenzija elemenata 'Generator dimenzija 2D elemenata' i 'Generiši dimenzije elemenata' kao i opcije za testiranje programa 'Testiraj program' i 'Prikaži rezultat poslednjeg testa'.

Opcija 'Generator dimenzija 2D elemenata' pokreće podprogram 'Generator dimenzija pravougaonih 2D elemenata' ( ^ ). Podešavanjem opcija u ovom podprogramu utiče se na broj elemenata za koji će biti izračunate dimenzije, kao i na način na koji će biti izračunate. Klikom na dugme 'Generiši' podprogram generiše vrednosti dimenzija, a zatim ih snimi u tekstualni dokument 'Dimenzije elemenata.txt' odakle mogu da se učitaju preko opcije programa 'Učitaj dimenzije'. Kompletan opis programa 'Generator dimenzija pravougaonih 2D elemenata' možete videti klikom na sliku programa.

Opcija 'Generiši dimenzije elemenata' automatski pokreće generator dimenzija elemenata, a izračunate vrednosti dimenzija direktno ubacuje u tabelu glavnog programa tako da ne moraju da se učitavaju.

https://sites.google.com/site/periczeljkosmederevo/generator-dimenzija-pravougaonih-dvodimenzionalnih-elemenata

Dimenzije su generisane na osnovu odabranih opcija u podprogramu. Opcija 'Testiraj program' pokreće testiranje programa koje se sastoji od 33 uzastopno ponovljenih uklapanja elemenata za odabrani algoritam, za obe ose table, sa željenim procentom popunjenosti koji je podesio korisnik. Broj elemenata i vrednosti dimenzija zavise od podešavanja u podprogramu 'Generator dimenzija pravougaonih 2D elemenata'. Pre odabira opcije 'Testiraj program' mora da se odabere opcija uklapanja elemenata 'Algoritam 2' ili 'Algoritam 4', a zatim da se odredi vrednost procenta popunjenosti table i da se izvrši podešavanje opcija u podprogramu za generisanje dimenzija elemenata. Algoritam za koji se vrši testiranje može lako da se promeni promenom programskog koda. Svrha testa je da se ustanovi prosečna brzina uklapanja i prosečan procenat popunjenosti table. Rezultat testa se automatski prikazuje po završetku testiranja, a poslednji rezultat testa se može pogledati odabirom opcije 'Prikaži rezultat poslednjeg testa'. Ovaj program uz malo reprogramiranja može da se modifikuje da ima varijabilne parametre za količinu i dimenzije tabli, tako da se uklapanje elemenata odvija u tom smeru da se uklope svi elementi i da se dobije najveći procenat iskorišćenosti.