Saya membaca "Pengantar Algoritma" oleh CLRS. Dalam bab 2, penulis menyebutkan "loop invariants". Apa itu invarian loop?
268
Saya membaca "Pengantar Algoritma" oleh CLRS. Dalam bab 2, penulis menyebutkan "loop invariants". Apa itu invarian loop?
Jawaban:
Dengan kata sederhana, invarian loop adalah beberapa predikat (kondisi) yang berlaku untuk setiap iterasi loop. Sebagai contoh, mari kita lihat
for
loop sederhana yang terlihat seperti ini:Dalam contoh ini benar (untuk setiap iterasi) itu
i + j == 9
. Invarian lemah yang juga benar adalah itui >= 0 && i <= 10
.sumber
Saya suka definisi yang sangat sederhana ini: ( sumber )
Dengan sendirinya, loop invarian tidak banyak membantu. Namun, diberikan invarian yang sesuai, dapat digunakan untuk membantu membuktikan kebenaran suatu algoritma. Contoh sederhana dalam CLRS mungkin ada hubungannya dengan pengurutan. Sebagai contoh, biarkan invarian loop Anda menjadi sesuatu seperti, pada awal loop,
i
entri pertama array ini diurutkan. Jika Anda dapat membuktikan bahwa ini memang invarian loop (yaitu bahwa ia berlaku sebelum dan sesudah setiap iterasi loop), Anda dapat menggunakan ini untuk membuktikan kebenaran dari algoritma pengurutan: pada penghentian loop, loop invarian masih puas , dan penghitungi
adalah panjang dari array. Oleh karena itu,i
entri pertama diurutkan berarti seluruh array diurutkan.Contoh yang lebih sederhana: Loops Invariants, Correctness, dan Derivation Program .
Cara saya memahami invarian loop adalah sebagai alat formal, sistematis untuk alasan tentang program. Kami membuat satu pernyataan yang kami fokuskan untuk membuktikan kebenaran, dan kami menyebutnya loop invariant. Ini mengatur logika kita. Meskipun kita dapat berdebat secara informal tentang kebenaran beberapa algoritma, menggunakan loop invarian memaksa kita untuk berpikir dengan sangat hati-hati dan memastikan alasan kita kedap udara.
sumber
Ada satu hal yang banyak orang tidak sadari ketika berhadapan dengan loop dan invarian. Mereka menjadi bingung antara loop invarian, dan loop kondisional (kondisi yang mengontrol terminasi loop).
Seperti yang ditunjukkan orang, loop invarian harus benar
(meskipun sementara itu bisa salah selama tubuh loop). Di sisi lain loop kondisional harus salah setelah loop berakhir, jika loop tidak akan pernah berakhir.
Jadi loop invarian dan kondisi loop harus kondisi yang berbeda.
Contoh yang bagus dari invarian loop kompleks adalah untuk pencarian biner.
Jadi pengulangan loop sepertinya cukup lurus ke depan - ketika mulai> mengakhiri pengakhiran berakhir. Tetapi mengapa loop itu benar? Apa loop invarian yang membuktikan kebenarannya?
Yang invarian adalah pernyataan logis:
Pernyataan ini adalah tautologi logis - selalu benar dalam konteks loop / algoritma spesifik yang kami coba buktikan . Dan itu memberikan informasi berguna tentang kebenaran loop setelah itu berakhir.
Jika kita kembali karena kita menemukan elemen dalam array maka pernyataannya benar, karena jika
A[mid] == a
kemudiana
ada dalam array danmid
harus antara awal dan akhir. Dan jika loop berakhir karenastart > end
tidak ada angka seperti itustart <= mid
danmid <= end
dan karena itu kita tahu bahwa pernyataan ituA[mid] == a
pasti salah. Namun, sebagai akibatnya pernyataan logis keseluruhan masih benar dalam arti nol. (Dalam logika pernyataan if (false) then (something) selalu benar.)Sekarang bagaimana dengan apa yang saya katakan tentang loop kondisional selalu salah ketika loop berakhir? Sepertinya ketika elemen ditemukan dalam array maka loop kondisional benar ketika loop berakhir !? Sebenarnya tidak, karena kondisi loop tersirat benar-benar
while ( A[mid] != a && start <= end )
tetapi kami mempersingkat tes yang sebenarnya sejak bagian pertama tersirat. Persyaratan ini jelas salah setelah loop terlepas dari bagaimana loop berakhir.sumber
a
hadir dalamA
. Secara informal, "jika kuncia
ada dalam array, itu harus terjadi di antarastart
danend
inklusif". Maka itu berarti bahwa jikaA[start..end]
kosong, itua
tidak ada dalam A.Jawaban sebelumnya telah mendefinisikan loop invarian dengan cara yang sangat baik.
Berikut ini adalah cara penulis CLRS menggunakan invarian loop untuk membuktikan kebenaran Penyisipan Sortir.
Algoritma Penyisipan Sortir (seperti yang diberikan dalam Buku):
Loop Invariant dalam hal ini: Sub-array [1 ke j-1] selalu diurutkan.
Sekarang mari kita periksa ini dan buktikan algoritma itu benar.
Inisialisasi : Sebelum iterasi pertama j = 2. Jadi sub-array [1: 1] adalah array yang akan diuji. Karena hanya memiliki satu elemen sehingga diurutkan. Dengan demikian invarian puas.
Pemeliharaan : Ini dapat dengan mudah diverifikasi dengan memeriksa invarian setelah setiap iterasi. Dalam hal ini puas.
Pengakhiran : Ini adalah langkah di mana kami akan membuktikan kebenaran dari algoritma.
Ketika loop berakhir maka nilai j = n + 1. Lagi-lagi loop invarian puas. Ini berarti Sub-array [1 ke n] harus disortir.
Inilah yang ingin kami lakukan dengan algoritma kami. Jadi algoritma kami benar.
sumber
Di samping semua jawaban yang baik, saya kira contoh yang bagus dari How to Think About Algorithms, oleh Jeff Edmonds dapat menggambarkan konsep dengan sangat baik:
sumber
Perlu dicatat bahwa Loop Invariant dapat membantu dalam desain algoritma iteratif ketika dianggap sebagai pernyataan yang menyatakan hubungan penting antara variabel yang harus benar pada awal setiap iterasi dan ketika loop berakhir. Jika ini berlaku, perhitungan sedang menuju ke efektifitas. Jika salah, maka algoritme telah gagal.
sumber
Invarian dalam hal ini berarti suatu kondisi yang harus benar pada titik tertentu dalam setiap iterasi loop.
Dalam pemrograman kontrak, invarian adalah suatu kondisi yang harus benar (berdasarkan kontrak) sebelum dan sesudah metode publik apa pun dipanggil.
sumber
Arti invarian tidak pernah berubah
Di sini loop invarian berarti "Perubahan yang terjadi pada variabel dalam loop (increment atau decrement) tidak mengubah kondisi loop yaitu kondisinya memuaskan" sehingga konsep loop invarian telah muncul
sumber
Properti Loop Invariant adalah kondisi yang berlaku untuk setiap langkah dari eksekusi loop (mis. Untuk loop, saat loop, dll.)
Ini sangat penting untuk Bukti Loop Invarian, di mana orang dapat menunjukkan bahwa suatu algoritma dieksekusi dengan benar jika pada setiap langkah pelaksanaannya properti invarian loop ini berlaku.
Agar suatu algoritma menjadi benar, Loop Invariant harus berlaku di:
Inisialisasi (awal)
Pemeliharaan (setiap langkah setelah)
Pengakhiran (saat selesai)
Ini digunakan untuk mengevaluasi banyak hal, tetapi contoh terbaik adalah algoritma serakah untuk grafik traversal berbobot. Untuk algoritma serakah untuk menghasilkan solusi optimal (jalur melintasi grafik), ia harus mencapai menghubungkan semua node di jalur bobot terendah yang mungkin.
Dengan demikian, properti loop invarian adalah bahwa jalur yang diambil memiliki bobot paling sedikit. Pada awalnya kami belum menambahkan tepi, jadi properti ini benar (dalam hal ini tidak salah). Pada setiap langkah , kita mengikuti batas bobot terendah (langkah serakah), jadi sekali lagi kita mengambil jalur bobot terendah. Pada akhirnya , kami telah menemukan jalur berbobot terendah, jadi properti kami juga benar.
Jika suatu algoritma tidak melakukan ini, kami dapat membuktikan bahwa itu tidak optimal.
sumber
Sulit untuk melacak apa yang terjadi dengan loop. Loop yang tidak berakhir atau berakhir tanpa mencapai perilaku tujuan mereka adalah masalah umum dalam pemrograman komputer. Loop invarian membantu. Loop invarian adalah pernyataan formal tentang hubungan antara variabel dalam program Anda yang berlaku tepat sebelum loop dijalankan (membuat invarian) dan benar lagi di bagian bawah loop, setiap kali melalui loop (mempertahankan invarian) ). Berikut adalah pola umum penggunaan Loop Invariants dalam kode Anda:
... // Loop Invariant harus benar di sini
while (TEST CONDITION) {
// bagian atas loop
...
// bagian bawah loop
// Loop Invariant harus benar di sini
}
// Termination + Loop Invariant = Sasaran
...
Di antara bagian atas dan bawah loop, kemungkinan headway dibuat untuk mencapai tujuan loop. Ini mungkin mengganggu (membuat salah) yang invarian. Inti dari Loop Invariants adalah janji bahwa invarian akan dipulihkan sebelum mengulangi loop body setiap kali. Ada dua keuntungan untuk ini:
Pekerjaan tidak diteruskan ke langkah selanjutnya dengan cara yang rumit dan tergantung data. Masing-masing melewati loop secara independen dari semua yang lain, dengan invarian melayani untuk mengikat pass bersama menjadi satu kesatuan yang berfungsi. Alasan bahwa loop Anda berfungsi dikurangi menjadi alasan bahwa loop invarian dikembalikan dengan setiap melewati loop. Ini memecah perilaku keseluruhan yang rumit dari loop menjadi langkah-langkah kecil yang sederhana, masing-masing yang dapat dianggap secara terpisah. Kondisi pengujian loop bukan bagian dari invarian. Inilah yang membuat loop berakhir. Anda mempertimbangkan secara terpisah dua hal: mengapa loop harus diakhiri, dan mengapa loop mencapai tujuannya ketika itu berakhir. Loop akan berakhir jika setiap kali melalui loop Anda bergerak lebih dekat untuk memenuhi kondisi terminasi. Seringkali mudah untuk memastikan ini: misalnya melangkah variabel counter dengan satu sampai mencapai batas atas yang tetap. Terkadang alasan di balik pemutusan hubungan kerja lebih sulit.
Loop invarian harus dibuat sehingga ketika kondisi terminasi tercapai, dan invarian benar, maka tujuannya tercapai:
invarian + termination => goal
Dibutuhkan latihan untuk membuat invarian yang sederhana dan berhubungan yang menangkap semua pencapaian tujuan kecuali untuk terminasi. Cara terbaik adalah menggunakan simbol matematika untuk mengekspresikan invarian loop, tetapi ketika ini mengarah pada situasi yang terlalu rumit, kita mengandalkan prosa yang jelas dan akal sehat.
sumber
Maaf saya tidak punya izin komentar.
@ Thomas Petricek seperti yang Anda sebutkan
Bagaimana itu invarian loop?
Saya harap saya tidak salah, sejauh yang saya mengerti [1] , Loop invarian akan benar pada awal loop (Inisialisasi), itu akan benar sebelum dan setelah setiap iterasi (Pemeliharaan) dan itu juga akan menjadi benar setelah terminasi loop (Pengakhiran) . Tetapi setelah iterasi terakhir saya menjadi 10. Jadi, kondisi i> = 0 && i <10 menjadi salah dan mengakhiri loop. Itu melanggar properti ketiga (Pemutusan) dari invarian loop.
[1] http://www.win.tue.nl/~kbuchin/teaching/JBP030/notebooks/loop-invariants.html
sumber
Loop invarian adalah rumus matematika seperti
(x=y+1)
. Dalam contoh itu,x
dany
mewakili dua variabel dalam satu lingkaran. Mempertimbangkan perubahan perilaku variabel-variabel tersebut selama eksekusi kode, hampir tidak mungkin untuk menguji semua kemungkinanx
dany
nilai-nilai dan melihat apakah mereka menghasilkan bug. Katakanlahx
adalah bilangan bulat. Integer dapat menampung ruang 32 bit dalam memori. Jika jumlah itu melebihi, terjadi buffer overflow. Jadi kita perlu memastikan bahwa selama eksekusi kode, tidak pernah melebihi ruang itu. untuk itu, kita perlu memahami formula umum yang menunjukkan hubungan antar variabel. Bagaimanapun, kami hanya mencoba memahami perilaku program.sumber
Dengan kata sederhana, itu adalah kondisi LOOP yang benar dalam setiap iterasi loop:
Dalam hal ini kita dapat mengatakan keadaan saya adalah
i<10 and i>=0
sumber
Loop invarian adalah pernyataan yang benar sebelum dan sesudah eksekusi loop.
sumber
Dalam Pencarian Linier (sesuai dengan latihan yang diberikan dalam buku), kita perlu menemukan nilai V dalam array yang diberikan.
Ini sederhana seperti memindai array dari 0 <= k <panjang dan membandingkan setiap elemen. Jika V ditemukan, atau jika pemindaian mencapai panjang array, hentikan saja loopnya.
Sesuai pemahaman saya dalam masalah di atas-
Loop Invariants (Inisialisasi): V tidak ditemukan dalam iterasi k - 1. Iterasi pertama, ini adalah -1 maka kita dapat mengatakan V tidak ditemukan pada posisi -1
Maintainance: Dalam iterasi berikutnya, V tidak ditemukan dalam k-1 berlaku
Pengakhiran: Jika V ditemukan dalam posisi k atau k mencapai panjang array, akhiri loop.
sumber