Mall-Tenant problem: The Idealist and The...
Transcript of Mall-Tenant problem: The Idealist and The...
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
Mall-Tenant problem: The Idealist and The Greed
Jessin Donnyson 13516112
Program Studi Teknik Informatika
Sekolah Teknik Elektro dan Informatika
Institut Teknologi Bandung, Jl. Ganesha 10 Bandung 40132, Indonesia
Abstract—Dalam makalah ini digambarkan sebuah
permasalahan dunia nyata dimana sebuah mall akan disewakan ke
sejumlah tenant. Pemilihan tenant menjadi poin penting bagi
pengembang untuk memaksimalkan profit. Permasalahan bukan
sekedar knapsack problems biasa, melainkan ekstensifikasi dimana
dimensi ‘profit’, ‘bag’ dan ‘weight’ yang terdefinisi, lebih dari satu
dimensi (multidimensional knapsack problem). Makalah akan
membahas pendekatan pemilihan tenant yang bisa disimulasikan
dengan berbagai paradigma pemrograman: khususnya dynamic
programming dan greedy approach.
Keywords—Dynamic Programming, Greedy approach,
Knapsack problems, Multidimensional knapsack problem,
paradigma pemrograman.
I. PENGANTAR
Dalam kehidupan, kadang kita dipertemukan dengan
permasalahan penyusunan dan pemilihan suatu benda atau
komponen, dengan berbagai tujuan dan target yang ingin
dicapai. Dalam kasus ini, bisa saja setiap benda memiliki nilai
keuntungan dan penggunaan ‘resource’ yang berbeda, dan kita
harus memilih dan mencoba membandingkan semua
kemungkinan kombinasi supaya menghasilkan nilai keuntungan
maksimal.
Salah satu contoh permasalahan konkrit adalah proses
memilih penyewa yang akan menyewa slot / kios dalam suatu
pusat perbelanjaan (mal). Pengembang akan berusaha
semaksimal mungkin untuk mencari penyewa yang akan
mendatangkan keuntungan terbesar untuk mal tsb. baik dari segi
meningkatkan pemasukan dan berbagai aspek lainnya.
Pada makalah ini, akan disimulasikan bagaimana dari daftar
penyewa, dipilih kombinasi penyewa yang menghasilkan profit
maksimum sesuai kebutuhan pengembang dengan
mempertimbangkan slot (ukuran ruang yang disewakan) yang
tersedia dalam mal.
Supaya lebih realistis, profit yang dihasilkan tidak hanya
berupa profit dalam hal uang, namun misal kontribusi
pengunjung, rating mal, dll.
Sebelum membahas simulasi yang digunakan, beberapa
landasan teori yang dibutuhkan adalah Dynamic programming,
Greedy approach, dan Knapsack problems.
II. DYNAMIC PROGRAMMING
Dynamic Programming atau pemrograman dinamis, adalah
suatu paradigma algoritma, dimana sebuah permasalahan
kompleks, dapat dipecah menjadi beberapa sub-masalah, yang
dapat diselesaikan lebih mudah, dan hasilnya dicatat untuk
menghindari adanya proses komputasi ulang [1].
Salah satu properti dari pemrograman dinamis adalah
pemecahan masalah menjadi sub-masalah (seperti dalam
pendekatan divide and conquer) dan terutama digunakan apabila
komputasi yang sama akan dilakukan berulang-ulang. Hal ini
mengimplikasi bahwa pemrograman dinamis tidak cocok
dilakukan jika tidak ada sub-permasalahan yang dapat dipakai
kembali (pencatatan hasil menjadi sia-sia).
Keuntungan digunakannya pemrograman dinamis
dibandingkan dengan pendekatan greedy adalah dalam
pemrograman dinamis, hasil optimum global dapat dijamin, dan
jika ada lebih dari satu solusi, kemungkinan besar dapat
ditunjukan oleh pemrograman dinamis. Walaupun untuk
kebanyakan permasalahan, pendekatan greedy dapat
memberikan komputasi yang sangat cepat dan mendekati hasil
optimum global [2, 3].
A. Memoization
Salah satu penerapan pemrograman dinamis adalah dengan
memoization, yaitu mencoba mencari hasil yang diharapkan dari
‘memo’ atau data container yang tersedia. Jika tidak tersedia,
baru dilakukan komputasi, dan hasilnya dicatat dalam ‘memo’
tsb. supaya dapat digunakan untuk proses selanjutnya jika
diperlukan. Keuntungan metode ini adalah pencatatan hanya
dilakukan jika diperlukan (on demand) [1].
B. Tabulation
Pendekatan lainnya adalah dengan tabulasi, yaitu membuat
tabel dari sub-permaslahan paling sederhana, sampai yang
paling kompleks. Kemudian jika diperlukan, cukup mengakses
hasil yang sudah dikomputasi terlebih dahulu. Dalam
pendekatan ini, semua kemungkinan akan dicoba dan dicatat
hasil komputasinya [1].
III. GREEDY APPROACH
Paradigma pendekatan greedy adalah suatu paradigma
algoritma dimana dengan memanfaatkan heuristic, mencari opsi
/ pilihan optimum lokal, dengan harapan akan menghasilkan
optimum global pada akhirnya [4].
Secara umum, pendekatan greedy tidak akan menghasilkan
solusi optimum global, namun kenyataanya pada kebanyakan
permasalahan, dapat menghasilkan solusi yang menghampiri
optimum global, (dengan mengambil optimum lokal pada setiap
tahapnya) dan yang terpenting: dengan kompleksitas waktu
yang sangat minimum.
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
Pendekatan greedy umumnya menggunakan heuristic
(aturan yang dianggap benar dan dapat menghasilkan
aproksimasi solusi optimum) dan preprocessing data supaya
meminimalisasi kompleksitas saat mencari solusi nantinya.
IV. KNAPSACK PROBLEMS
The knapsack problem adalah suatu permasalahan optimasi
menggunakan kombinatorial: terdapat sekumpulan benda yang
memiliki berat dan nilai, tentukan benda mana saja yang harus
dimasukan dalam himpunan supaya berat tidak melebihi batas,
namun menghasilkan profit paling tinggi [5].
Secara umum, jenis permasalahan yang paling umum adalah
0-1 knapsack problem, dimana banyak benda untuk setiap
jenisya hanya berkisar 0 (tidak dimasukkan) atau 1
(dimasukkan) [6].
Dalam notasi matematis:
∑ 𝑣𝑖𝑥𝑖
𝑛
𝑖=1
dengan mempertimbangkan:
∑ 𝑤𝑖𝑥𝑖
𝑛
𝑖=1
≤ 𝑊, 𝑥𝑖 ∈ {0, 1}.
n = jumlah jenis benda,
w = berat benda
x = banyak benda
v = nilai benda
W = berat kapasitas maksimum
Dalam penyelesaian permasalahan knapsack, walaupun
permasalahan menentukan putusannya (decision problem)
tergolong NP-complete, persoalan optimasi knapsack sendiri
tergolong NP-hard, sehingga solusi optimum tidak dapat
ditentukan / belum ada algoritma yang dapat menentukan solusi
dalam kompleksitas polinomial. Namun kompleksitas dapat
diturunkan menjadi pseudo-polinomial menggunakan
pendekatan pemrograman dinamis (dynamic programming) [7].
A. Pemanfaatan Dynamic Programming
Pada persoaalan ini, didefinisikan tahap – k adalah proses
memasukkan barang k ke dalam himpunan solusi, sedangkan
status y adalah kapasitas muat yang tersisa setelah memasukkan
barang pada tahap sebelumnya.
Relasi rekurens yang didefinisikan adalah:
𝑓0(𝑦) = 0, 𝑦 = 0, 1, … , 𝑀 (basis) (3)
𝑓𝑘(𝑦) = −∞, 𝑦 < 0 (basis) (4)
𝑓𝑘(𝑦) = max {𝑓𝑘−1, 𝑝𝑘 + 𝑓𝑘−1(𝑦 − 𝑤𝑘)} (rekurens) (5)
𝑓𝑘(𝑦) adalah keuntungan optimum dari persoalan pada tahap
k untuk kapasitas sebesar y. 𝑓0(𝑦) = 0 adalah basis knapsack
kosong, sedangkan 𝑓𝑘(𝑦) = −∞ adalah basis knapsack jika
kapasitas lebih kecil daripada beban benda [8]. Berikut pseudo-
codenya:
1. // Values (stored in array v) 2. // Weights (stored in array w) 3. // Number of distinct items (n) 4. // Knapsack capacity (W) 5. 6. for j from 0 to W do: 7. m[0, j] := 0 8. 9. for i from 1 to n do: 10. for j from 0 to W do: 11. if w[i] > j then: 12. m[i, j] := m[i-1, j] 13. else: 14. m[i, j] := max(m[i-1, j], m[i-
1, j-w[i]] + v[i])
B. Multi-objective Knapsack
Dalam perkembangan varian dari knapsack problems,
terdapat suatu varian multi-objective yaitu dimana profit yang
diinginkan mungkin memiliki dimensi lebih dari satu. (contoh:
memaksimalkan profit dan maksimal jumlah barang yang
dibawa) [9].
C. Multi-dimensional Knapsack
Dalam perkembangan varian dari knapsack problems,
terdapat suatu vaian multi-dimensional-knapsack yaitu dimana
‘berat’ yang menjadi kapasitas berdimensi lebih dari satu.
(contoh: berat tidak melebihi x , dan jumlah benda a tidak
melebihi y) [10].
V. PERSIAPAN SIMULASI
Setelah membahas beberapa dasar teori dalam simulasi
penyelesaian masalah, perlu didefinisikan juga domain
permasalahan dan ruang lingkup permasalahan sebelum
mencoba menyelesaikannya. Juga tidak lupa membuat data
sample untuk digunakan pada proses pemecahan masalah.
A. Domain permasalahan
Untuk simulasi permasalahan memilih penyewa (tenant)
dalam mal, diasumsikan setiap tenant memiliki data jenis slot
yang dibutuhkan, profit (uang) yang akan diterima pengembang
(asumsi konstant untuk sepanjang kontrak yang didefinisikan),
estimasi kontribusi peningkatan rating mal (asumsikan hasil
survey popularitas tenant yang dilakukan pengembang). Data
yang diperlukan disederhanakan karena hanya untuk keperluan
simulasi.
Untuk merepresentasikan ‘weight’ dalam knapsack,
digunakan slot yang merepresentasikan ‘ruangan’ yang dapat
disewakan, namun supaya menyerupai kasus pada kenyataanya,
maka slot dibagi menjadi beberapa tipe, dan masing-masing
memiliki jumlah yang terbatas.
Untuk knapsack nya sendiri, berupa abstraksi dari slot yang
terdapat pada setiap lantai mal. Hal ini dilakukan untuk
mensimulasikan peletakan dan penyusunan tenant seperti pada
kenyataanya. Sehingga permasalahan dispesifikasi menjadi
multi-bag knapsack problem.
(1) memaksimalkan
(2)
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
B. Pembatasan Masalah
Dalam simulasi, diasumsikan penentuan jumlah masing-
masing jenis slot ditentukan oleh pengembang setelah melewati
tahap perancangan gedung dan bukan menjadi domain simulasi.
Profit yang dimaksud juga adalah pemasukan konstan yang
diberikan oleh tenant, dan diasumsikan dihitung per tahun,
sehingga profit maksimum yang dioptimasi adalah profit per
tahunnya.
Walaupun pada dasarnya persoalan adalah multi-objective
knapsack, namun diasumsikan semua profit yang diinginkan
dapat direduksi menjadi satu dimensi (satu konstanta) sesuai
proporsi dan kepentingan masing-masing nilai dengan
pendekatan greedy yaitu menggunakan persamaan linier yang
memuat hubungan semua atribut yang ingin dimaksimalkan.
Segala faktor eksternal lainnya disederhanakan dan tidak
masuk domain optimasi dalam persoalan knapsack ini.
C. Data sampel
Sebelum memulai simulasi, diperlukan data yang telah
disebutkan diatas, yaitu data tenant dan data kapasitas mal.
Penciptaan data dilakukan dengan random oleh library Numpy.
Data dibuat dengan cara menentukan untuk masing-masing
kategori tenant, (slot a / b / c / d / e), mean dan standard
deviation dari pesebaran distribusi profit dan ratingnya. Setelah
itu, menggukanan fungsi distribusi normal dari Numpy untuk
menciptakan data pseudo-randomnya.
Berikut contoh hasil pembuatan data tenant dari masing
masing kategori menggunakan kode pada appendix 3 sampai 7:
Tabel 1. Contoh Data Tenant Kategori ‘a’
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
1 148 10 (1, 0, 0, 0, 0)
2 147 10 (1, 0, 0, 0, 0)
3 176 6.92 (1, 0, 0, 0, 0)
… … … …
30 167 10 (1, 0, 0, 0, 0)
Tabel 2. Contoh Data Tenant Kategori ‘b’
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
31 74 7.5 (0, 1, 0, 0, 0)
32 73 9.12 (0, 1, 0, 0, 0)
33 90 8.84 (0, 1, 0, 0, 0)
… … … …
80 53 6.61 (0, 1, 0, 0, 0)
Tabel 3. Contoh Data Tenant Kategori ‘c’
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
81 49 9.85 (0, 0, 1, 0, 0)
82 48 4.99 (0, 0, 1, 0, 0)
83 60 5.46 (0, 0, 1, 0, 0)
… … … …
280 54 6.96 (0, 0, 1, 0, 0)
Tabel 4. Contoh Data Tenant Kategori ‘d’
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
281 24 2.27 (0, 0, 0, 1, 0)
282 24 5.03 (0, 0, 0, 1, 0)
283 30 6.55 (0, 0, 0, 1, 0)
… … … …
430 24 4.03 (0, 0, 0, 1, 0)
Tabel 5. Contoh Data Tenant Kategori ‘e’
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
431 4 4.77 (0, 0, 0, 0, 1)
432 4 0 (0, 0, 0, 0, 1)
433 6 3.76 (0, 0, 0, 0, 1)
… … … …
680 7 3.51 (0, 0, 0, 0, 1)
Jika dilihat sekilas, setiap tenant hanya memiliki bobot
‘weight’ 1 untuk jenis kategori tertentu (misal (0, 1, 0, 0, 0) atau
(0, 0, 0, 1, 0,), untuk kasus sederhana seperti itu, pemilihan
tenant dapat dilakukan hanya dengan sorting profit dan diambil
nilai terbesar pertama sampai nilai kapasitas tertentu setiap
lantai saja.
Maka untuk menambah kompleksitas dan mencoba
menyerupai permasalahan pada kenyataan dimana suatu tenant
dapat menyewa beberapa tipe / beberapa slot sekaligus, maka
akan dilakukan penggabungan data. Penggabungan dilakukan
secara random (menggunakan kode appendix 9 dan 10).
Alasan penggabungan dilakukan belakangan adalah untuk
menjaga keselarasan data profit kontrak, rating, jumlah tenant
per kategori, dengan jenis slot yang diperlukan. Misalnya:
mengindari adanya tenant yang profit kontraknya kecil (tipe e)
tapi menyewa slot tipe a. (data lebih realistis).
Tabel 6. Contoh Data Tenant Kombinasi
Id
tenant Profit kontrak (jt) Rating
Jenis slot
(a, b, c, d, e)
11 141 9.45 (1, 0, 2, 0, 0)
27 282 8.8 (1, 0, 3, 0, 0)
54 128 6.84 (0, 1, 2, 0, 0)
… … … …
672 17 7.2 (0, 0, 0, 0, 2)
Selanjutnya adalah data slot yang dimiliki masing-masing
lantai dalam mal tsb. Pembuatan data juga dilakukan dengan
library Numpy untuk menciptakan data yang random.
Berikut hasil pembuatan data slot mal yang akan digunakan
pada tahap berikutnya (menggunakan kode appendix 11):
Tabel 7. Jumlah Masing-masing Slot
Lantai ‘a’ ‘b’ ‘c’ ‘d’ ‘e’
1 2 6 26 14 18
2 2 8 36 22 25
3 1 6 33 25 22
4 2 6 30 10 24
5 2 16 19 15 21
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
VI. PEMECAHAN MASALAH
Setelah mendefinisikan berbagai teori dan data yang akan
digunakan dalam simulasi, berikutnya adalah pelaksanaan
simulasi dan analisis permasalahan itu sendiri.
A. Perkiraan Kompleksitas
Sebelum memulai mencoba membuat kode penyelesaianya,
jika sekilas kita menghitung kompleksitasnya:
𝑂(#𝑡𝑒𝑛𝑎𝑛𝑡 × 𝑆𝑎1 × 𝑆𝑎2 × … × 𝑆𝑒5)
(Nb: Sa1 menandakan jumlah slot tipe a di lantai 1, Se5 adalah
jumlah slot tipe e di lantai 5)
Sekedar gambaran, jika menggunakan data pada tabel 7, dan
sekitar 400 tenant, jumlah komputasi maksimumnya (worst
case) adalah 2.14 * 10^29. Sebagai pembanding, jika dalam satu
detik dapat melakukan 10^8 komputasi, diperlukan 6.8 * 10^13
tahun untuk menyelesaikannya. Namun untuk kepentingan
simulasi, komputasi akan tetap dilakukan walaupun jumlah data
dikurangi.
B. Percobaan Dynamic Programming
Saat melakukan percobaan, (dengan kode appendix 17),
dengan menggunakan sample hanya 13 tenant dan kondisi ‘bag’
seperti pada tabel 7, didapatkan hasil nilai maksimum 2280
(profit multi dimensi direduksi menjadi satu dimensi dengan
kode appendix 16 sesuai keterangan dalam pembatasan
masalah).
Dari tabel yang digunakan dalam dynamic programming,
dapat disimpulkan tenant mana saja yang diambil, dan dengan
menggunakan kode appendix 18, hasil yang didapat adalah
tenant berikut :
(no, profit, rating, a b c d e)
[1. , 148., 10., 1., 0., 0., 0., 0.],
[6. , 143., 10., 1., 0., 1., 0., 0.],
[7. , 166., 8.96, 1., 0., 1., 0., 0.],
[8. , 144., 10., 1., 0., 0., 0., 0.],
[9. , 183., 9.37, 1., 0., 1., 0., 0.],
[10. , 149., 9.34, 1., 0., 0., 0., 0.],
[11. , 134., 9.45, 1., 0., 0., 0., 0.],
[12. , 184., 9.33, 1., 0., 0., 0., 0.],
[13. , 190., 8.37, 1., 0., 0., 0., 0.]
Artinya: tenant dengan nomor 1, 6, 7, 8, 9, 10, 11, 12, 13 akan
mendapat jatah jika hanya ada 13 tenant.
Yang perlu diperhatikan adalah bahwa jumlah slot a yang
tersedia ada 9, dan jumlah slot a yang dipakai tenant yang
terpilih juga 9, ini artinya tenant yang dipilih sudah
memaksimalkan profit yang akan didapat pengembang. Hasil ini
menunjukkan bahwa problema ini dapat diselesaikan dengan
optimum menggunakan pendekatan dynamic programming.
Walaupun hanya 13 tenant, komputasi yang dilakukan
mencapai 1238798 atau 1.2 juta komputasi. Tentu jumlah ini
tergolong besar untuk 13 jenis ‘barang’ dalam knapsack
problem. Melalui contoh diatas, penulis berusaha mencari
jumlah sample yang cukup sesuai untuk menunjukkan bahwa
problema dapat diselesaikan walaupun di satu pihak, pendekatan
dynamic programming ini tidak scalable.
C. Grafik Jumlah Komputasi
Jika percobaan dilakukan kembali, namun kali ini mencatat
hubungan jumlah tenant dan jumlah komputasi yang dilakukan
mulai dari hanya ada 1 tenant sampai terdapat 13 tenant (kode
appendix 20), didapatkan hasil:
Output: [(13, 1238798), (12, 779080), (11, 447802), (10,
247517), (9, 113852), (8, 52541), …, (3, 43), (2, 7), (1, 1)]
Sebagai gambaran data tsb. dalam bentuk grafik:
Gambar 1. Grafik Jumlah Komputasi(y) dan Jumlah
Tenant(x)
Sumber(kode appendix 21)
Walaupun sekilas tampak seperti jumlah bertumbuh secara
eksponensial, namun jika dibuat grafik hubungan jumlah tenant
dengan logaritma dari jumlah komputasi, didapatkan grafik
seperti berikut:
Gambar 2. Grafik Log Jumlah Komputasi(y) dan Jumlah
Tenant(x)
Sumber(kode appendix 22)
Dari grafik ini disimpulkan bahwa kompleksitas algoritma,
masih dikatakan polinomial (pseudo-polinomial), walaupun
orde polinomnya sangat besar. Dengan demikian, teori bahwa
problema dapat diselesaikan dalam kompleksitas pseudo-
polinomial dapat dibuktikan.
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
Kembali ke permasalahan, terlihat jelas bahwa pendekatan
dynamic programming ini tidak terlalu dapat diandalkan, karena
pada kenyataanya, datanya tidak sesederhana dan sesedikit ini,
faktor pertimbangan akan jauh lebih rumit dan juga ‘weight’
yang digunakan akan berdimensi lebih banyak lagi.
Maka dari itu, dibutuhkan pendekatan lain yang lebih scalable
terutama dalam hal waktu komputasi. Salah satu pendekatan
yang sesuai adalah: Greedy.
VII. PEMECAHAN MASALAH II
Salah satu kelebihan pendekatan greedy adalah dengan
melakukan preprocessing data dan menerapkan berbagai
heuristic, sehingga waktu komputasi dapat ditekan. Dalam
kasus ini, juga diperlukan beberapa tahap preprocessing data.
A. Sorting Tenant
Pertama-tama perlu dilakukan sorting tenant sesuai profit
yang diberikan, namun dalam data sample yang digunakan, akan
terjadi bias jika dilakukan terhadap profit, karena tenant tipe a
cenderung memiliki profit tertinggi. Sehingga dilakukan sorting
terhadap efisiensi tenant yang didefinisikan sebagai: profit / cost
slot yang diperlukan.
Untuk cost yang didefinisikan, ditentukan secara tentative:
misalkan slot tipe a diberi nilai 150 sedangkan tipe e hanya
bernilai 5.
Pada kasus ini, cost slot disamakan dengan rata-rata profit
tenant per kategori (a-e) (mengikuti mean yang digunakan saat
penciptaan data tenant). Hal ini didasarkan pada intuitif bahwa
tenant yang menghasilkan profit lebih banyak dari tenant sejenis
(kategori sama & memakai jumlah slot yang sama), akan lebih
diutamakan.
Berikut tabel 8 dan tabel 9 hasil kode appendix 23 dan 24:
Tabel 8. Contoh Data Tenant + efisiensi
Id
tenant
Profit
kontrak
(jt)
Rating
Jenis slot
(a, b, c, d, e)
Eff
1 148 10 (1, 0, 0, 0, 0) 1.667
2 147 10 (1, 0, 0, 0, 0) 1.435
3 176 6.92 (1, 0, 0, 0, 0) 1.130
… … … …
30 167 10 (1, 0, 0, 0, 0) 1.793
Tabel 9. Contoh Data Tenant Terurut Eff
Id
tenant
Profit
kontrak
(jt)
Rating
Jenis slot
(a, b, c, d, e)
Eff
74 102 10 (0, 1, 0, 0, 0) 2.720
58 87 10 (0, 1, 0, 0, 0) 2.520
95 56 8.59 (0, 0, 1, 0, 0) 1.88
… … … …
283 30 6.55 (0, 0, 1, 0, 0) 0.78
B. Uji Coba Greedy
Berbeda dengan pendekatan dynamic programming dimana
semua kemungkinan yang diperlukan akan dicoba, karena dalam
pendekatan greedy sudah dilakukan preprocessing data dengan
diurutkan berdasarkan ‘prioritas’, maka saat memilih, cukup
memeriksa apakah suatu tenant dapat masuk di lantai ke – n, jika
ya, masukkan dalam himpunan solusi ke – n. Jika tidak dapat
dimasukkan ke lantai manapun, masukkan kedalam himpunan
yang tidak dipilih.
Untuk mencari solusi dengan pendekatan greedy, digunakan
kode appendix 25: didapatkan hasil profit sebesar 15713 dan
kali ini, semua data tenant digunakan. Jumlah komputasi yang
diperlukan tentu saja sangat minimum, yaitu: (maksimal /
worstcase):
𝑂(#𝑡𝑒𝑛𝑎𝑛𝑡 × #𝑙𝑎𝑛𝑡𝑎𝑖)
Dalam kasus ini, hanya 544 * 5 = 2720, sangat jauh lebih
sedikit dibandingkan pendekatan dynamic programming.
Hasil dari pendekatan greedy pun dapat menunjukkan tenant
mana saja yang dimasukkan dalam lantai yang mana (kode
appendix 27):
Output:
Lantai 1 = [645, 601, 501, 583, 619, 647, 74, 81, 584, 58,
453, 567, 57, 40, 331, 28, 378, 267, …, 208, 202, 115, 340,
214, 233, 277, 365, 293, 427, 381, 324]
Lantai 2 = [38, 78, 65, 67, 68, 42, 49, 589, 33, 526, 631, 15,
1, 603, 577, 662, …,341, 361, 414]
Lantai 3 = [12, 75, 50, 69, 66, 43, 39, 517, 490, 678, 614,
671, ..., 420, 334]
Lantai 4 = [8, 9, 47, 46, 41, 34, 45, 71, 654, 652, 641, 482,
472, 439, 582, 445, 502, 458…10, 392, 320, 315, 364, 298]
Lantai 5 = [5, 23, 60, 36, 48, …, 291, 319, 200, 199, 395,
183, 376, 235, 82, 196, 160, 327, 269, 144, 148]
* Hasil tidak ditampilkan semua
Hasil diatas, jika dirangkum menurut jumlah tenant per
lantai, didapatkan hasil [60, 75, 70, 60, 49] dimana artinya
314/544 tenant mendapatkan tempat dalam gedung. Terlihat
kurang baik karena hanya 57% yang dimasukkan, namun jika
kita meninjau lagi sisa slot dalam gedung yang tidak terpakai:
Output:
[[ 1., 0., 0., 0., 0., 0.],
[ 2., 0., 0., 0., 0., 0.],
[ 3., 0., 0., 0., 0., 0.],
[ 4., 0., 0., 0., 0., 0.],
[ 5., 0., 0., 0., 0., 0.]]
Ternyata semua slot habis dipakai! Apakah hal ini
membuktikan bahwa pendekatan greedy menjamin solusi
efektif dan optimum untuk semua kasus?
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
Jika kita ingat kembali, pada bagian pembuatan data, data
slot yang dibutuhkan tenant pada umumnya berupa data singular
atau hanya memiliki bobot untuk satu jenis slot saja misal (0, 0,
0, 0, 1) atau (0, 0, 1, 0, 0). Sehingga, sisa sisa slot dapat dengan
mudah dipenuhi oleh tenant-tenant dengan kebutuhan slot
seperti ini.
Dengan kata lain, pendekatan greedy akan optimal jika
terdapat pecahan terkecil yang dapat memenuhi slot sisa sekecil
apapun. Dengan bertambahnya data, dan ketersediaan tenant
(‘object’ dalam kasus knapsack), akan lebih mudah bagi
pendekatan greedy untuk mendapatkan hasil mendekati
optimum global.
VIII. KESIMPULAN
Berdasarkan percobaan untuk memasukan tenant dengan
bobot lima dimensi, dan profit berdimensi dua: didapatkan
pendekatan dynamic programming dapat dilakukan dan
menjamin kompleksitas Pseudo-polinomial.
Walaupun dikatakan polinomial, namun polinomial tsb. dapat
berkembang dengan orde besar terutama jika dimensi ‘weight’
barang (dalam kasus uji: slot) dan jumlah ‘bag’ (dalam kasus
uji: lantai) bertambah. Terbukti dari percobaan dan grafik yang
menunjukkan pertumbuhan jumlah komputasi.
Pendekataan lain yang dapat dipakai untuk kasus ini adalah
greedy dengan bantuan heuristic. Dalam percobaan ini,
pendekatan greedy dapat bekerja mendekati optimum, dan
dibuktikan dengan semua slot terpakai. Hasil yang mendekati
optimum dapat dicapai apabila terdapat ‘object’ yang dapat
memiliki ‘weight’ dalam satuan terkecil untuk setiap jenis
‘weight’ yang dibatasi oleh pembatas muatan (capacity).
Walaupun pendekatan greedy memerlukan preprocessing,
namun kompleksitasnya tetap jauh lebih kecil dibandingkan
dynamic programming.
Pendekatan greedy bisa dikatakan jauh lebih cocok untuk
diterapkan dalam kasus uji seperti ini karena paling tidak
menghasilkan solusi mendekati optimum, dibandingkan
dynamic programming yang tidak menghasilkan solusi karena
keterbatasan waktu komputasi jika dihadapkan dengan jumlah
‘object’ dan ‘bag’ yang besar.
IX. APPENDIX
Appendix diberikan secara terpisah karena keterbatasan
halaman.
X. ACKNOWLEDGMENT
Terimakasih kepada Tony (IF ITB 2016) yang sudah turut
membantu dan mendukung kelancaran pembuatan makalah ini,
terutama dalam hal konsultasi algoritma dan penerapan yang
efektif.
REFERENCES
[1] Https://www.geeksforgeeks.org/dynamic-programming-set-1/
(diakses 6 Mei 2018)
[2] Cormen, T. H.; Leiserson, C. E.; Rivest, R. L.; Stein, C. (2001),
Introduction to Algorithms (2nd ed.), MIT Press & McGraw–Hill,
ISBN 0-262-03293-7. pp. 344.
[3] W.-K. Chen, Linear Networks and Systems (Book style). Belmont,
CA: Wadsworth, 1993, pp. 123–135.
[4] Black, Paul E. (2 February 2005). "greedy algorithm". Dictionary
of Algorithms and Data Structures. U.S. National Institute of
Standards and Technology (NIST)
[5] Mathews, G. B. (25 June 1897). "On the partition of numbers"
(PDF). Proceedings of the London Mathematical Society. 28: 486–
490. doi:10.1112/plms/s1-28.1.486l
[6] Kellerer, Pferschy, and Pisinger 2004, p. 472
[7] Poirriez, Vincent; Yanev, Nicola; Andonov, Rumen (2009). "A
hybrid algorithm for the unbounded knapsack problem". Discrete
Optimization. 6 (1): 110–124.
[8] http://informatika.stei.itb.ac.id/~rinaldi.munir/Stmik/2017-
2018/Program-Dinamis-(2018).pdf (diakses 7 Mei 2018)
[9] https://arxiv.org/ftp/arxiv/papers/1007/1007.4063.pdf (diakses 7
Mei 2018)
[10] Gens, G. V. and Levner, E. V. (1979). "Complexity and
Approximation Algorithms for Combinatorial Problems: A
Survey". Central Economic and Mathematical Institute, Academy
of Sciences of the USSR, Moscow.
PERNYATAAN
Dengan ini saya menyatakan bahwa makalah yang saya tulis
ini adalah tulisan saya sendiri, bukan saduran, atau terjemahan
dari makalah orang lain, dan bukan plagiasi.
Bandung, 3 Desember 2017
Ttd (scan atau foto ttd)
Jessin 13516112
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
IX. APPENDIX
Kode 1: Import
1. %matplotlib inline 2. import numpy as np 3. import warnings 4. 5. warnings.filterwarnings(action='ignore')
Kode 2: Fungsi formatting atribut popularitas
1. def format_popularity(tenant_popularity): 2. """ Format popularity to range between 0 - 10, and with 2 decimal value """ 3. 4. tenant_popularity[tenant_popularity < 0] = 0 5. tenant_popularity[tenant_popularity > 10] = 10 6. tenant_popularity = np.around(tenant_popularity, 2) 7. 8. return tenant_popularity
Kode 3: Generate tenant kategori ‘a’
1. np.random.seed(seed=21) 2. 3. tenant_id = np.arange(1, 31) 4. tenant_profit = np.random.normal(150, 25, 30) // 1 5. tenant_popularity = np.random.normal(9, 1.5, 30) 6. tenant_popularity = format_popularity(tenant_popularity) 7. 8. zeros = np.zeros((30, 1)) 9. ones = np.ones((30,1)) 10. tenant_slot = np.hstack((ones,zeros,zeros,zeros,zeros)) 11. 12. # merge the data 13. tenant_data_a = np.vstack((tenant_id, tenant_profit, tenant_popularity)).T 14. tenant_data_a = np.hstack((tenant_data_a, tenant_slot))
Kode 4: Generate tenant kategori ‘b’
1. np.random.seed(seed=21) 2. 3. tenant_id = np.arange(31, 81) 4. tenant_profit = np.random.normal(75, 15, 50) // 1 5. tenant_popularity = np.random.normal(8, 1.5, 50) 6. tenant_popularity = format_popularity(tenant_popularity) 7. 8. zeros = np.zeros((50, 1)) 9. ones = np.ones((50,1)) 10. tenant_slot = np.hstack((zeros,ones,zeros,zeros,zeros)) 11. 12. # merge the data 13. tenant_data_b = np.vstack((tenant_id, tenant_profit, tenant_popularity)).T 14. tenant_data_b = np.hstack((tenant_data_b, tenant_slot))
Kode 5: Generate tenant kategori ‘c’
1. np.random.seed(seed=21) 2. 3. tenant_id = np.arange(81, 281) 4. tenant_profit = np.random.normal(50, 10, 200) // 1 5. tenant_popularity = np.random.normal(6, 1.5, 200)
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
6. tenant_popularity = format_popularity(tenant_popularity) 7. 8. zeros = np.zeros((200, 1)) 9. ones = np.ones((200,1)) 10. tenant_slot = np.hstack((zeros,zeros,ones,zeros,zeros)) 11. 12. # merge the data 13. tenant_data_c = np.vstack((tenant_id, tenant_profit, tenant_popularity)).T 14. tenant_data_c = np.hstack((tenant_data_c, tenant_slot))
Kode 6: Generate tenant kategori ‘d’
1. np.random.seed(seed=21) 2. 3. tenant_id = np.arange(281, 431) 4. tenant_profit = np.random.normal(25, 5, 150) // 1 5. tenant_popularity = np.random.normal(4, 1.5, 150) 6. tenant_popularity = format_popularity(tenant_popularity) 7. 8. zeros = np.zeros((150, 1)) 9. ones = np.ones((150,1)) 10. tenant_slot = np.hstack((zeros,zeros,ones,zeros,zeros)) 11. 12. # merge the data 13. tenant_data_d = np.vstack((tenant_id, tenant_profit, tenant_popularity)).T 14. tenant_data_d = np.hstack((tenant_data_d, tenant_slot))
Kode 7: Generate tenant kategori ‘e’
1. np.random.seed(seed=21) 2. 3. tenant_id = np.arange(431, 681) 4. tenant_profit = np.random.normal(5, 1.5, 250) // 1 5. tenant_popularity = np.random.normal(2, 2.5, 250) 6. tenant_popularity = format_popularity(tenant_popularity) 7. 8. zeros = np.zeros((250, 1)) 9. ones = np.ones((250,1)) 10. tenant_slot = np.hstack((zeros,zeros,ones,zeros,zeros)) 11. 12. # merge the data 13. tenant_data_e = np.vstack((tenant_id, tenant_profit, tenant_popularity)).T 14. tenant_data_e = np.hstack((tenant_data_e, tenant_slot))
Kode 8: Gabungkan kelima jenis tenant
1. tenant = np.vstack((tenant_data_a , tenant_data_b, tenant_data_c , tenant_data_d , tenant_data_e)) 2. tenant.shape
Kode 9: Fungsi penggabungan tenant
1. def combine(tenant_data, t1, t2): 2. 3. try: 4. tenant_1 = tenant_data[t1] 5. tenant_2 = tenant_data[t2] 6. 7. # sum profit 8. tenant_1[1] += tenant_2[1] 9. 10. # avg popularity 11. tenant_1[2] = max((tenant_1[2] , tenant_2[2])) 12. 13.
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
14. # sum the necesary slot 15. for i in range(3,8): 16. tenant_1[i] += tenant_2[i] 17. 18. # delete second entry 19. tenant_data = np.delete(tenant_data, t2, axis=0) 20. 21. return tenant_data 22. 23. except: 24. return tenant_data
Kode 10: Pemanggilan fungsi penggabung
1. tenant_count_init = tenant_count = tenant.shape[0] 2. 3. # reduce tenant to below 80% by merging some tenant 4. while(tenant_count > 0.80 * tenant_count_init): 5. 6. tenant_partner = np.random.randint(0, tenant_count * 4, tenant_count) # each tenant only has 2
5% change to be merged 7. 8. for i in range(0, tenant_count): 9. if i < tenant_partner[i]: 10. tenant = combine(tenant, i, tenant_partner[i]) 11. 12. tenant_count = tenant.shape[0] 13. 14. tenant.shape
Kode 11: Generate slot dalam mal
1. np.random.seed(seed=23) 2. 3. building_floor = np.arange(1,6) 4. slot_type_a = np.random.normal(3, 1, 5) // 1 5. slot_type_b = np.random.normal(10, 3, 5) // 1 6. slot_type_c = np.random.normal(30, 10, 5) // 1 7. slot_type_d = np.random.normal(20, 5, 5) // 1 8. slot_type_e = np.random.normal(20, 5, 5) // 1 9. 10. # merge the data 11. building = np.vstack((building_floor, slot_type_a, slot_type_b, slot_type_c, slot_type_d, slot_typ
e_e)).T
Kode 12: Json object dari slot mal
1. json_building = {} 2. for floor in building: 3. 4. temp = {} 5. for i in range(1, len(floor)): 6. temp[chr(i + 96)] = floor[i] 7. 8. json_building[floor[0]] = temp
Kode 13: merubah building menjadi tuples untuk JSON indexing
1. def capacity_list(building): 2. 3. index = [] 4. for floor in building: 5. for i in range(1, len(floor)): 6. index.append(floor[i])
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
7. 8. return tuple(index)
Kode 14: mengecek ketersediaan slot
1. def enough_slot(tenant, floor_slot): 2. 3. for i in range(1, len(floor_slot)): 4. if floor_slot[i] < tenant[2 + i]: 5. return False 6. return True
Kode 15: mengurangi slot lantai
1. def reduce_slot(tenant, building, floor): 2. 3. temp = copy.deepcopy(building) 4. for i in range(1, len(temp[floor])): 5. temp[floor][i] -= tenant[2 + i] 6. 7. return temp
Kode 16: estimasi profit (reduksi dimensi)
1. def estimated_value(tenant): 2. 3. return int(tenant[1] + (2**tenant[2])/10)
Kode 17: pendekatan dynamic programming
1. def solve(tenant_number, building): 2. global dpdict 3. global table_c, compute_c 4. 5. # if tenant number out of bound 6. try: 7. tenant[tenant_number] is not None 8. except: 9. return 0 10. 11. if (tenant[tenant_number] is not None): 12. 13. item = tenant[tenant_number] 14. capacity_tuple = capacity_list(building) 15. 16. try: 17. # check if json dict available 18. if dpdict[item[0]][capacity_tuple] is not None: 19. 20. table_c += 1 21. return dpdict[item[0]][capacity_tuple] 22. 23. except Exception as e : 24. 25. # set dict value 26. if item[0] not in dpdict.keys(): 27. dpdict[item[0]] = {} 28. dpdict[item[0]][capacity_tuple] = solve(tenant_number + 1, building) 29. 30. # check if it's available for each floor 31. for i in range(0, 5): 32. 33. if enough_slot(item, building[i]): 34.
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
35. # value from DP dict 36. old_value = dpdict[item[0]][capacity_tuple] 37. 38. # computed new value 39. new_building = reduce_slot(item, building, i) 40. new_value = solve(tenant_number + 1, new_building) + estimated_value(item) 41. 42. # Re write dict 43. dpdict[item[0]][capacity_tuple] = max(old_value, new_value) 44. 45. compute_c += 1 46. return dpdict[item[0]][capacity_tuple] 47. 48. 49. # Run the function 50. tenant = tenant[:13] 51. dpdict = {} 52. table_c = compute_c = 0 53. 54. solve(0, building)
Kode 18: menampilkan hasil dynamic programming
1. def list_tenant(building): 2. 3. ans = [] 4. w = capacity_list(building) 5. for i in range (len(tenant) - 1): 6. 7. curr_tenant = tenant[i] 8. 9. # tenant not included 10. if dpdict[curr_tenant[0]][w] == dpdict[tenant[i + 1][0]][w]: 11. continue 12. 13. 14. for j in range(0, len(building)): 15. wtemp = capacity_list(reduce_slot(curr_tenant, building, j)) 16. try: 17. if dpdict[curr_tenant[0]][w] == dpdict[tenant[i + 1][0]][wtemp] + estimated_value(
curr_tenant) : 18. ans.append(curr_tenant) 19. w = wtemp 20. break 21. except: 22. pass 23. 24. i = len(tenant) - 1 25. if dpdict[tenant[i][0]][w] > 0: 26. ans.append(tenant[i]) 27. 28. return ans 29. 30. # Run the function 31. list_tenant(building)
Kode 19: persiapan data untuk di plot
1. res = [] 2. for i in range(-13, 0): 3. 4. tenant = tenant[:-i] 5. dpdict = {} 6. table_c = compute_c = 0 7.
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
8. solve(0, building) 9. 10. res.append((-i, table_c + compute_c)) 11. print(res)
Kode 20: plot grafik
1. import matplotlib.pyplot as plt 2. 3. plt.plot(*zip(*res)) 4. plt.show()
Kode 21: plot grafik logaritma
1. from math import log 2. 3. reslog = [(elem1, log(elem2)) for elem1, elem2 in res] 4. plt.plot(*zip(*reslog)) 5. plt.show()
Kode 22: kalkulasi efisiensi
1. def tenant_eff(tenant): 2. 3. mean = 0 4. mean += tenant[3] * 150 5. mean += tenant[4] * 75 6. mean += tenant[5] * 50 7. mean += tenant[6] * 25 8. mean += tenant[7] * 5 9. 10. return estimated_value(tenant) / mean
Kode 23: kalkulasi efisiensi
1. eff = [[tenant_eff(x)] for x in tenant] 2. tenant_greed = np.hstack((tenant, eff))
Kode 24: Sort greedy
1. tenant_greed = tenant_greed[tenant_greed[:,8].argsort()][::-1]
Kode 25: Greedy algorithm
1. def solve_g(tenant, building): 2. 3. global compute_c 4. 5. result = [[] for _ in range(0,5)] 6. not_used = [] 7. profit = 0 8. 9. count = 0 10. for each_tenant in tenant: 11. 12. flag = True 13. for i in range(0, 5): 14. print("checking", i) 15. if enough_slot(each_tenant, building[i]): 16. 17. # computed new value 18. building = reduce_slot(each_tenant, building, i)
Makalah IF2120 Matematika Diskrit – Sem. I Tahun 2017/2018
19. profit += estimated_value(each_tenant) 20. 21. # insert tenant into building 22. result[i].append(each_tenant) 23. flag = False 24. 25. print("put in", i) 26. compute_c += 1 27. break 28. 29. if flag: 30. not_used.append(each_tenant) 31. 32. return result, not_used, building, profit
Kode 26: menjalankan kode 25
1. result, not_used, leftover, profit = solve_g(tenant, building)
Kode 27: tenant yang dipakai disetiap lantai
1. for floor in result: 2. print([int(tenant[0]) for tenant in floor])