Döngü değişmez nedir?


268

CLRS tarafından "Algoritmaya Giriş" i okuyorum. 2. bölümde yazarlar "döngü değişmezlerinden" bahsediyorlar. Döngü değişmez nedir?


4
Bu açıklayan oldukça iyi görünüyor cs.miami.edu/~burt/learning/Math120.1/Notes/LoopInvar.html
Tom Gullen


Birisi döngü değişmez kavramına dayalı gerçek bir algoritmik kodlama problemini çözmek istiyorsa, lütfen HackerRank'ta bu soruna bakın . Ayrıca, yerleştirme sıralama sorununu yalnızca kavramı ayrıntılı olarak açıklamak için kullanmışlardır.
RBT

Bir de not başvurabilir burada teorik anlayış için.
RBT

Yanıtlar:


345

Basit bir deyişle, bir döngü değişmezi, döngünün her yinelemesi için geçerli olan bir yüklem (koşul) 'dur. Örneğin, forşöyle görünen basit bir döngüye bakalım :

int j = 9;
for(int i=0; i<10; i++)  
  j--;

Bu örnekte (her yineleme için) doğrudur i + j == 9. Aynı zamanda daha zayıf bir değişmez de doğrudur i >= 0 && i <= 10.


29
Bu mükemmel bir örnek. Çoğu zaman bir öğretmenin döngü değişmezini tanımladığını duyduğumda, basitçe 'döngü durumu' ya da benzer bir şey olmuştur. Örneğin, değişmezin çok daha fazla olabileceğini göstermektedir.
Brian S

77
Bu iyi bir örnek görmüyorum çünkü döngü değişmezi biraz döngü hedefi olmalıdır ... CLRS bir sıralama algoritmasının doğruluğunu kanıtlamak için kullanır. Ekleme sıralaması için, döngünün i ile yinelendiğini varsayalım, her döngünün sonunda, dizi i-öğeye kadar sıralanır.
çatışma

5
evet, bu örnek yanlış değil, sadece yeterli değil. Döngü değişmezinin sadece kendisi için değil, hedefi sunması gerektiği için @Clash up.
Jack

7
@Tomas Petricek - döngü sona erdiğinde, i = 10 ve j = -1; yani verdiğiniz daha zayıf değişmez örnek doğru olmayabilir (?)
Raja

7
Yukarıdaki yorumları kabul etsem de bu cevabı iptal ettim çünkü ... amaç burada tanımlanmadı. Uygun olan herhangi bir hedefi tanımlayın ve örnek harika.
Flavius

119

Bu çok basit tanımı beğendim: ( kaynak )

Döngü değişmezi, bir döngünün her yinelemesinden hemen önce ve hemen sonra mutlaka doğru olan bir koşuldur (program değişkenleri arasında). (Bunun bir yineleme yoluyla gerçekliği veya sahteliği hakkında hiçbir şey söylemediğini unutmayın.)

Kendi başına, bir döngü değişmezi pek bir şey yapmaz. Bununla birlikte, uygun bir değişmez verildiğinde, bir algoritmanın doğruluğunu kanıtlamaya yardımcı olmak için kullanılabilir. CLRS'deki basit örnek muhtemelen sıralama ile ilgilidir. Örneğin, döngü değişmezinizin döngü başlangıcında i, bu dizinin ilk girdileri sıralanır. Bunun gerçekten bir döngü değişmez olduğunu kanıtlayabilirseniz (yani her döngü yinelemesinden önce ve sonra tutar), bir sıralama algoritmasının doğruluğunu kanıtlamak için bunu kullanabilirsiniz: döngünün sona ermesinde döngü değişmezi hala tatmin olur , ve sayaç idizinin uzunluğudur. Bu nedenle, ilk igirişler sıralanır, tüm dizinin sıralandığı anlamına gelir.

Daha da basit bir örnek: Döngü Değişkenleri, Doğruluk ve Program Türetme .

Bir döngü değişmezini anlama şeklim, programlar hakkında akıl yürütmenin sistematik ve resmi bir aracıdır. Doğruluğu kanıtlamaya odaklandığımız tek bir açıklama yaparız ve buna döngü değişmezi diyoruz. Bu bizim mantığımızı düzenler. Bazı algoritmaların doğruluğu hakkında gayri resmi olarak tartışabilirken, bir döngü değişmezi kullanmak bizi çok dikkatli düşünmeye zorlar ve akıl yürütmemizin hava geçirmez olmasını sağlar.


10
"Her yinelemeden hemen sonra" ifadesinin, döngü sona erdikten sonra nasıl sona erdiğine bakılmaksızın içerdiğine dikkat edilmelidir.
Robert S. Barnes

Bu cevap için çok teşekkürler! Bundan en büyük amaç, bu döngü değişmezine sahip olmanın amacı, algoritmanın doğruluğunu kanıtlamaya yardımcı olmaktır. Diğer cevaplar sadece döngü değişmezine odaklanır!
Neekey

39

Döngüler ve değişmezlerle uğraşırken birçok insanın hemen fark etmediği bir şey var. Döngü değişmezi ile döngü koşullu (döngünün sonlandırılmasını kontrol eden durum) arasında karışırlar.

İnsanlar işaret ettiği gibi, döngü değişmezi doğru olmalıdır

  1. döngü başlamadan önce
  2. döngünün her yinelemesinden önce
  3. döngü sona erdikten sonra

(döngü gövdesi sırasında geçici olarak yanlış olsa da). Öte yandan, döngü sona erdikten sonra döngü koşullu yanlış olmalıdır , aksi takdirde döngü hiçbir zaman sona ermeyecektir.

Bu nedenle, döngü değişmez ve döngü koşulu farklı koşullar olmalıdır .

Karmaşık bir döngü değişmezine iyi bir örnek ikili arama içindir.

bsearch(type A[], type a) {
start = 1, end = length(A)

    while ( start <= end ) {
        mid = floor(start + end / 2)

        if ( A[mid] == a ) return mid
        if ( A[mid] > a ) end = mid - 1
        if ( A[mid] < a ) start = mid + 1

    }
    return -1

}

Bu yüzden döngü koşulu oldukça düz görünüyor - start> end olduğunda döngü sona erer. Peki döngü neden doğrudur? Doğruluğunu kanıtlayan döngü değişmez nedir?

Değişmez mantıksal ifadedir:

if ( A[mid] == a ) then ( start <= mid <= end )

Bu ifade mantıklı bir totolojidir - kanıtlamaya çalıştığımız belirli döngü / algoritma bağlamında her zaman doğrudur . Ve döngü sona erdikten sonra döngünün doğruluğu hakkında yararlı bilgiler sağlar.

Öğeyi dizide bulduğumuz için dönersek, ifade açıkça doğrudur, çünkü eğer A[mid] == ao zaman adizide ise ve midbaşlangıç ​​ve bitiş arasında olması gerekir. Ve döngü sona erdiği çünkü eğer start > endo şekilde hiçbir numara olabilir start <= mid ve mid <= end bu nedenle açıklamanın biliyoruz A[mid] == afalse olmalıdır. Bununla birlikte, sonuç olarak, genel mantıksal ifade null anlamında hala doğrudur. (Mantıkta (false) ifadesi (bir şey) her zaman doğruysa ifade.)

Şimdi döngü sona erdiğinde döngü koşullu olarak yanlış olması hakkında ne söyledim? Öğe dizide bulunduğunda, döngü sona erdiğinde döngü koşullu doğrudur !? Aslında öyle değildir, çünkü zımni döngü while ( A[mid] != a && start <= end )koşulludur, ancak ilk kısım ima edildiği için gerçek testi kısaltırız. Bu koşul, döngünün nasıl sona erdiğine bakılmaksızın döngüden sonra açıkça yanlıştır.


Mantıksal bir ifadeyi döngü değişmezi olarak kullanmak çok zordur, çünkü tüm mantıksal ifadeler her ne zaman olursa olsun, her koşulda doğru olabilir.
acgtyrant

Garantisi yoktur çünkü O kadar tuhaf ben düşünmelidir amevcuttur A. Gayri resmi olarak, "anahtar adizide mevcutsa, arasında startve endkapsayıcı olması gerekir " olacaktır. Daha sonra, eğer A[start..end]boşsa, aA'da mevcut değildir.
scanny

33

Önceki cevaplar çok iyi bir şekilde bir döngü değişmezi tanımladı.

Aşağıda CLRS yazarları Ekleme Sıralamasının doğruluğunu kanıtlamak için döngü değişmezini nasıl kullandılar .

Ekleme Sıralama algoritması (Kitapta verildiği gibi):

INSERTION-SORT(A)
    for j ← 2 to length[A]
        do key ← A[j]
        // Insert A[j] into the sorted sequence A[1..j-1].
        i ← j - 1
        while i > 0 and A[i] > key
            do A[i + 1] ← A[i]
            i ← i - 1
        A[i + 1] ← key

Bu durumda Döngü Değişmez: Alt dizi [1 ila j-1] her zaman sıralanır.

Şimdi bunu kontrol edelim ve algoritmanın doğru olduğunu kanıtlayalım.

Başlatma : İlk yinelemeden önce j = 2. Dolayısıyla alt dizi [1: 1] test edilecek dizidir. Tek bir elemanı olduğu için sıralanır. Böylece değişmez tatmin olur.

Bakım : Bu, her yinelemeden sonra değişmezi kontrol ederek kolayca doğrulanabilir. Bu durumda tatmin olur.

Sonlandırma : Bu, algoritmanın doğruluğunu kanıtlayacağımız adımdır.

Döngü sona erdiğinde j = n + 1 değeri. Yine döngü değişmez tatmin olur. Bu, Alt dizi [1 ila n] 'nin sıralanması gerektiği anlamına gelir.

Algoritmamızla bunu yapmak istiyoruz. Dolayısıyla algoritmamız doğrudur.


1
Kabul ediyorum ... fesih bildirimi burada çok önemlidir.
Gaurav Aradhye

18

Tüm iyi cevapların yanı sıra , Jeff Edmonds'un Algoritmalar Hakkında Nasıl Düşünüleceğinden harika bir örnek olduğunu tahmin ediyorum :

ÖRNEK 1.2.1 "Find-Max İki Parmak Algoritması"

1) Özellikler: Bir giriş örneği, bir öğe L (1..n) listesinden oluşur. Çıkış, L (i) maksimum değere sahip olacak şekilde bir indeks i'den oluşur. Aynı değere sahip birden fazla giriş varsa, bunlardan herhangi biri döndürülür.

2) Temel Adımlar: İki parmak yöntemine karar verirsiniz. Sağ parmağınız listede ilerliyor.

3) İlerleme Ölçüsü: İlerleme ölçüsü, sağ parmağınızın liste boyunca ne kadar ilerlemesidir.

4) Döngü Değişmezi: Döngü değişmezi, sol parmağınızın sağ parmağınızla şimdiye kadar karşılaşılan en büyük girdilerden birine işaret ettiğini belirtir.

5) Ana Adımlar: Her yineleme, sağ parmağınızı listede bir giriş aşağı taşırsınız. Sağ parmağınız şimdi sol parmak girişinden daha büyük bir girişi gösteriyorsa, sol parmağınızı sağ parmağınızla olacak şekilde hareket ettirin.

6) İlerleme: Sağ parmağınız bir girişi hareket ettirdiği için ilerleme kaydedersiniz.

7) Döngü Değişmezliğini Koru: Döngü değişmezinin aşağıdaki gibi korunduğunu bilirsiniz. Her adım için, yeni sol parmak öğesi Max (eski sol parmak öğesi, yeni öğe). Döngü değişmezine göre bu Maks (Maks (daha kısa liste), yeni öğe). Matematiksel olarak, bu Maks (daha uzun liste).

8) Döngü Değişmezini Belirleme: Başlangıçta her iki parmağınızı ilk elemana doğru çevirerek döngü değişmezini oluşturursunuz.

9) Çıkış Koşulu: Sağ parmağınız listeyi geçmeyi bitirdiğinizde yapılır.

10) Son: Sonunda sorunun şu şekilde çözüldüğünü biliyoruz. Çıkış koşuluna göre, sağ parmağınız tüm girişlerle karşılaştı. Döngü değişmezine göre, sol parmağınız bunların maksimumunu gösterir. Bu girdiyi döndür.

11) Sonlandırma ve Çalışma Süresi: Gereken süre, listenin uzunluğunun sabit sürelerinden birkaçıdır.

12) Özel Durumlar: Aynı değere sahip birden fazla giriş olduğunda veya n = 0 veya n = 1 olduğunda ne olacağını kontrol edin.

13) Kodlama ve Uygulama Detayları: ...

14) Resmi Kanıt: Algoritmanın doğruluğu yukarıdaki adımlardan sonra gelir.


Bence bu cevap gerçekten bir değişmezin sezgisel özü üzerine "parmağını koyar".
scanny

6

Bir Döngü Değişmezinin, her yinelemenin başında ve döngü sona erdiğinde doğru olması gereken değişkenler arasındaki önemli ilişkileri ifade eden bir iddia olarak değerlendirildiğinde yinelemeli algoritmaların tasarımına yardımcı olabileceği unutulmamalıdır. Bu geçerliyse, hesaplama etkinlik yolundadır. False olursa, algoritma başarısız olmuştur.


5

Bu durumda değişmez, her döngü yinelemesinde belirli bir noktada doğru olması gereken bir durum anlamına gelir.

Sözleşme programlamasında, bir değişmez, herhangi bir genel yöntem çağrılmadan önce ve sonra doğru olması gereken bir durumdur (sözleşme ile).


4

Değişmezin anlamı asla değişmez

Burada döngü değişmezi, döngü döngü değişkeni kavramının gelmesi için döngüdeki değişime (artış veya eksiltme) gerçekleşen değişiklik döngü koşulunu değiştirmez, yani koşul tatmin edicidir demektir.


2

Döngü Değişmez Özelliği, döngüler yürütme işleminin her adımı için geçerli olan bir koşuldur (yani döngüler, döngüler vb. İçin)

Bu, bir döngü değişmez özelliği için önemlidir, burada yürütme işleminin her adımında bu döngü değişmez özelliği tutulursa, bir algoritmanın doğru çalıştığını gösterebilir.

Bir algoritmanın doğru olması için, Döngü Değişmezinin şu konumda tutması gerekir:

Başlatma (başlangıç)

Bakım (sonraki her adımda)

Fesih (bittiğinde)

Bu, bir sürü şeyi değerlendirmek için kullanılır, ancak bunun en iyi örneği, ağırlıklı grafik geçişi için açgözlü algoritmalardır. Açgözlü bir algoritmanın optimal bir çözüm (grafik boyunca bir yol) vermesi için, tüm düğümleri mümkün olan en düşük ağırlık yoluna bağlaması gerekir.

Dolayısıyla, döngü değişmez özelliği, alınan yolun en az ağırlığa sahip olmasıdır. At başından bu özellik (bu durumda, sahte değildir) doğrudur bu yüzden, herhangi kenarları eklemediniz. At her adımda , böylece yine biz düşük ağırlık yolunu alıyorsun, düşük ağırlık kenarı (açgözlü adım) izleyin. Sonunda , en düşük ağırlıklı yolu bulduk, bu nedenle mülkümüz de doğrudur.

Bir algoritma bunu yapmazsa, bunun uygun olmadığını kanıtlayabiliriz.


1

Döngülerde neler olduğunu takip etmek zordur. Hedef davranışlarına ulaşmadan sonlanmayan veya sonlanmayan döngüler bilgisayar programlamasında yaygın bir sorundur. Döngü değişmezleri yardım eder. Döngü değişmezi, programınızda değişkenler arasındaki ilişki hakkında, döngü hiç çalıştırılmadan hemen önce geçerli olan (değişmezi oluşturma) ve döngü boyunca her seferinde (değişmezi koruyarak) tekrar doğrudur. ). Kodunuzda Loop Invariants kullanımının genel deseni:

... // Döngü Değişmezi burada doğru olmalıdır
(TEST KOŞULU) {
// döngünün üstü
...
// döngünün altı
// Döngü Değişmezliği burada doğru olmalıdır
}
// Sonlandırma + Döngü Değişmezi = Amaç
...
Döngünün üstü ve altı arasında, döngünün hedefine ulaşmak için muhtemelen yol ilerlemektedir. Bu, değişmezi rahatsız edebilir (yanlış yapabilir). Döngü Değişmezlerinin noktası, döngü gövdesini her seferinde tekrar etmeden önce değişmezin geri yükleneceği vaadidir. Bunun iki avantajı vardır:

İş, karmaşık, veriye bağlı yollarla bir sonraki geçişe iletilmez. Her biri diğerlerinden bağımsız olarak döngüden geçer, değişmez geçişleri birlikte çalışan bir bütün olarak birleştirmeye yarar. Döngünüzün çalıştığı mantık, döngü değişmezinin döngüden her geçişte geri yükleneceği gerekçesiyle azaltılır. Bu, döngünün karmaşık genel davranışını, her biri ayrı ayrı düşünülebilecek küçük basit adımlara böler. Döngünün test koşulu değişmez parçanın bir parçası değildir. Döngüyü sonlandıran şey budur. İki şeyi ayrı ayrı düşünürsünüz: döngü neden sona ermelidir ve döngü sona erdiğinde neden hedefe ulaşır. Döngü boyunca her seferinde sonlandırma koşulunu yerine getirmek için yaklaşırsanız döngü sona erer. Bunu sağlamak genellikle kolaydır: örn. sabit bir üst sınıra ulaşana kadar bir sayaç değişkenini birer birer basamaklamak. Bazen fesih sebebi daha zordur.

Döngü değişmezi, sonlandırma durumuna ulaşıldığında ve değişmez doğru olduğunda, hedefe ulaşıldığında yaratılmalıdır:

invariant + termination => goal
Sonlandırma hariç tüm hedefe ulaşmayı yakalayan basit ve ilgili değişmezler oluşturmak pratik gerektirir. Döngü değişmezlerini ifade etmek için matematiksel semboller kullanmak en iyisidir, ancak bu aşırı karmaşık durumlara yol açtığında, açık nesir ve sağduyuya güveniriz.


1

Üzgünüm, yorum iznim yok.

Bahsettiğiniz gibi @Tomas Petricek

Aynı zamanda daha zayıf bir değişmez, i> = 0 && i <10 olmasıdır (çünkü bu devam koşuludur!) "

Nasıl bir döngü değişmezidir?

Umarım yanılmıyorum, anladığım kadarıyla [1] , Döngü değişmezi döngünün başlangıcında (Başlatma) doğru olacaktır, her yinelemeden önce ve sonra (Bakım) sonra da doğru olacaktır. döngünün sonlandırılması (Sonlandırma) . Ancak son yinelemeden sonra i 10 olur. Dolayısıyla, i> = 0 && i <10 koşulu yanlış olur ve döngüyü sonlandırır. Döngü değişmezinin üçüncü özelliğini (Fesih) ihlal eder.

[1] http://www.win.tue.nl/~kbuchin/teaching/JBP030/notebooks/loop-invariants.html


Benim tahminim bu doğrudur, çünkü döngü aslında bu koşullar altında çalışmaz.
muiiu

0

Döngü değişmezi gibi matematiksel bir formüldür (x=y+1). Bu örnekte xve ybir döngüdeki iki değişkeni temsil eder. Bu değişkenlerin kodun yürütülmesi sırasında değişen davranışları göz önüne alındığında, mümkün olan tüm değerleri ve değerleri test etmek xve yherhangi bir hata üretip üretmediklerini görmek neredeyse imkansızdır . Diyelim ki xbir tam sayı. Tamsayı, bellekte 32 bit alan tutabilir. Bu sayı aşılırsa, arabellek taşması oluşur. Bu nedenle, kodun yürütülmesi boyunca asla bu alanı aşmadığından emin olmalıyız. bunun için değişkenler arasındaki ilişkiyi gösteren genel bir formülü anlamamız gerekir. Sonuçta, sadece programın davranışını anlamaya çalışıyoruz.


0

Basit bir ifadeyle, her döngü yinelemesinde geçerli olan bir LOOP koşulu:

for(int i=0; i<10; i++)
{ }

Bu konuda ben diyebilirim ki i<10 and i>=0


0

Döngü değişmezi, döngü yürütülmesinden önce ve sonra doğru olan bir iddiadır.


-1

Doğrusal Arama'da (kitapta verilen alıştırmaya göre), verilen dizide V değerini bulmamız gerekir.

Diziyi 0 <= k <uzunluktan taramak ve her öğeyi karşılaştırmak kadar basittir. V bulunursa veya tarama dizi uzunluğuna ulaşırsa, döngüyü sonlandırın.

Yukarıdaki problemdeki anlayışım uyarınca-

Döngü Değişmezleri (Başlatma): V k - 1 yinelemesinde bulunamadı. İlk yineleme, bu -1 olur, dolayısıyla V'nin -1 konumunda bulunamadı diyebiliriz.

Bakım: Bir sonraki yinelemede, k-1'de bulunmayan V doğru

Sonlandırma: K konumunda veya k konumunda bulunan V dizinin uzunluğuna ulaşırsa, döngüyü sonlandırın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.