Dinamik programlama nedir?


33

Bu soru aptalca geliyorsa şimdiden özür dilerim ...

Bildiğim kadarıyla dinamik programlama kullanarak bir algoritma oluşturmak şu şekilde çalışır:

  1. sorunu tekrarlama ilişkisi olarak ifade eder;
  2. Yinelenme ilişkisini notlandırma yoluyla veya aşağıdan yukarıya bir yaklaşımla gerçekleştirin.

Bildiğim kadarıyla dinamik programlama ile ilgili her şeyi söyledim. Demek istediğim: Dinamik programlama tekrarlama ilişkilerini ifade etmek için ya da onları koda dönüştürmek için araçlar / kurallar / yöntemler / teoremler vermez.

Peki, dinamik programlama ile ilgili özel olan nedir? Belli tür sorunlara yaklaşmak için belirsiz bir yöntem dışında size ne veriyor?


11
Tarihsel factoid (bu yorum size yardımcı olmayacak, ancak dinamik programlama konusunda teori ağırlaştırmak istiyorsanız Bellman aslında iyi bir ipucudur): Bellman şu anda dinamik programlama olarak bilinen şeyi ortaya çıkardığında, "dinamik programlama" olarak adlandırdı. “Çünkü tamamen teorik çalışmalar o zaman işvereniyle uçmayacaktı, bu yüzden aşağılayıcı bir şekilde kullanılamayan daha fazla solucan duyduğu bir şeye ihtiyacı vardı .
G. Bach

3
Bildiğim kadarıyla tam olarak bahsettiğiniz bu iki nokta. Üst üste binen alt sorunlar nedeniyle katlanarak patlamayı önlediğinde özel bir hal alır. Bu kadar. Ah, bu arada, profesörüm "belirsiz yöntem" yerine "algoritmik paradigmayı" tercih ediyor.
Hendrik Jan

“Dinamik programlama” temel olarak bir buzzword gibi görünüyor (buzz'larını kaybettikten beri). Bu elbette faydalı olmadığı anlamına gelmez.
user253751

3
Bir cevaba layık değil, fakat bana göre dinamik programlama "bir problemi özyinelemeli bir şekilde çözmeye çalıştığınızda kullandığınız şeydir, fakat aynı alt problemleri tekrar tekrar gözden geçirerek zaman harcıyorsunuz."
Ocaklar

@hobbs: Kesinlikle, ama beceri olduğunu bulma israf zaman o ilk yol;)
j_random_hacker

Yanıtlar:


27

Dinamik programlama, algoritma tasarımı hakkında düşünmenin bir yolunu sunar. Bu genellikle çok yardımcı olur.

Notlandırma ve aşağıdan yukarıya alma yöntemleri, tekrarlama ilişkilerini koda dönüştürmek için size bir kural / yöntem sunar. Notlandırma, nispeten basit bir fikirdir, ancak en iyi fikirler genellikle!

Dinamik programlama, algoritmanızın çalışma zamanını düşünmek için size yapısal bir yol sunar. Çalışma süresi temel olarak iki sayı ile belirlenir: çözmeniz gereken alt problem sayısı ve her bir alt problemin çözülmesi için geçen süre. Bu, algoritma tasarım problemi hakkında düşünmenin kolay ve kolay bir yolunu sağlar. Bir aday yineleme ilişkiniz olduğunda, ona bakabilir ve çalışma süresinin ne olabileceğini çok hızlı bir şekilde anlayabilirsiniz (örneğin, genellikle kaç tane alt problemin olacağına dair çok hızlı bir şekilde söyleyebilirsiniz). çalışma zamanı; katlanarak çözmeniz gereken birçok alt sorun varsa, tekrarlama muhtemelen iyi bir yaklaşım olmayacaktır). Bu ayrıca aday alt problem ayrıştırmalarını ekarte etmenize yardımcı olur. Örneğin, bir , S [ 1 .. i ] önekiyle veya S [ j . . n ] veya alt dizgi S [ i . . j ] makul olabilir (alt problemlerin sayısı n'de polinomdur), ancak bir alt problemin S'nin bir sonucu ile tanımlanmasının iyi bir yaklaşım olması muhtemel değildir (alt problemlerin sayısı n'de üsteldir). Bu, olası yinelemelerin "arama alanını" ayarlamanızı sağlar.S[1..n]S[1..i]S[j..n]S[i..j]nSn

Dinamik programlama, aday yinelenme ilişkilerini aramak için size yapısal bir yaklaşım sunar. Ampirik olarak, bu yaklaşım genellikle etkilidir. Özellikle, girişin türüne bağlı olarak alt sorunları tanımlamanın ortak yollarını tanıyabileceğiniz bazı sezgisel / ortak modeller vardır. Örneğin:

  • Girişi ise pozitif bir tam sayı , bir subproblem tanımlamak için bir aday yol değiştirerek olup , n daha küçük bir tamsayı , n ' (st 0 n 'n ).nnn0nn

  • Girişi ise dize , bir subproblem tanımlamak için bir aday yollar içerir: yerini S [ 1 .. n ] bir önek ile S [ 1 .. i ] ; yerine S [ 1 .. n ] bir sonek ile S [ j . . n ] ; yerine S [ 1 .. n ] bir alt ile S [ i . . j ]S[1..n]S[1..n]S[1..i]S[1..n]S[j..n]S[1..n]S[i..j]. (Burada alt problem, seçimi ile belirlenir .)i,j

  • Girdi bir liste ise , bir dize için yaptığınız gibi yapın.

  • Girişi ise ağaç , bir subproblem tanımlamak için bir aday yol değiştirmektir T herhangi alt ağaç ile T (yani, bir düğüm çekme x ve yerine T kökü alt ağaç ile x , subproblem seçimiyle belirlenir x ).TTTxTxx

  • Giriş bir çift , her biri için bir alt problemi seçmenin bir yolunu tanımlamak için , x tipine ve y tipine tekrarlı olarak bakın. Diğer bir deyişle, bir subproblem tanımlamak için bir aday yol değiştirmektir ( x , y ) ile ( x ' , y ' ) x ' bir subproblem olan x ve y ' için subproblem olan y . (Ayrıca formun alt problemlerini de düşünebilirsiniz ( x , y(x,y)xy(x,y)(x,y)xxyy Veya ( x , y ) .)(x,y)(x,y)

Ve bunun gibi. Bu size çok faydalı bir sezgisel bakış sunar: sadece yöntemin türüne ait imzayı inceleyerek , alt sorunları tanımlamak için aday yolların bir listesini bulabilirsiniz. Başka bir deyişle, yalnızca sorun ifadesine bakarak - yalnızca girdi türlerine bakarak - bir alt sorunu tanımlamak için bir kaç aday yöntemle karşılaşabilirsiniz.

Bu genellikle çok faydalıdır. Tekrarlama ilişkisinin ne olduğunu söylemez, ancak alt problemin nasıl tanımlanacağı konusunda özel bir seçeneğiniz olduğunda, çoğu zaman karşılık gelen bir tekrarlama ilişkisini çözmek çok zor değildir. Bu nedenle, genellikle dinamik bir programlama algoritmasının tasarımını yapılandırılmış bir deneyime dönüştürür. Hurda kağıda alt sorunları tanımlamak için aday yöntemlerin bir listesini yazarsınız (yukarıdaki sezgisel yöntemi kullanarak). Daha sonra, her aday için, bir tekrarlama ilişkisi yazmayı denersiniz ve çalışma süresini alt problem sayısını ve alt problem başına harcanan zamanı sayarak değerlendirirsiniz. Her adayı denedikten sonra bulabildiğiniz en iyisini elde edersiniz. Algoritma tasarım sürecine bir yapı sağlamak, aksi takdirde algoritma tasarımını korkutucu olabileceğinden, büyük bir yardımdır.


Böylece dinamik programlamanın takip etmesi gereken somut "prosedürler" sağlamadığını onaylıyorsunuz. Dediğin gibi, sadece "düşünmenin bir yolu". DP'nin işe yaramaz olduğunu (aksine!) Tartışmayacağımı, sadece eksik olduğum bir şey olup olmadığını veya daha fazla pratik yapmam gerektiğini anlamaya çalışıyorum.
hey hey,

@ hey, iyi, evet ... ve hayır. Daha fazla ayrıntı için gözden geçirilmiş cevabımı görün. Gümüş bir mermi değildir, ancak genellikle yardımcı olan bazı yarı somut prosedürler sağlar (işe yaraması garanti edilmez, ancak çoğu zaman yardımcı olurlar).
DW

Çok teşekkürler! Uygulama yaparak, tarif ettiğiniz "yarı somut prosedürlerden" daha fazla tanımaya başladım.
hey hey

“Eğer katlanarak çözmeniz gereken birçok alt sorun varsa, tekrarlama muhtemelen iyi bir yaklaşım olmaz”. Birçok problem için bilinen bir polinom zaman algoritması yoktur. Bu neden DP'yi kullanmak için bir kriter olsun?
Chiel ten Brinke 16:15

@ Chiel, DP kullanmanın bir kriteri değil. Üstel zamanlı algoritmalardan memnun kalacağınız bir probleminiz varsa, o zaman belirli parantez içindeki sözleri görmezden gelebilirsiniz. Bu, benim yaptığım genel noktayı göstermeye çalışmak için bir örnek - çok ciddiye almanız veya zor ve hızlı bir kural olarak yorumlamanız gereken bir şey değil.
DW

9

Dinamik programlama anlayışınız doğru ( afaik ) ve sorunuz haklı.

"Dinamik programlama" olarak adlandırdığımız yinelenmelerden elde ettiğimiz ek tasarım alanının en çok özyinelemeli yaklaşımların şemalarına kıyasla daha iyi görülebileceğini düşünüyorum.

A[1..n]

  1. Endüktif Yaklaşım

    Burada fikir, probleminizi küçültmek, daha küçük versiyonu çözmek ve orijinali için bir çözüm bulmaktır. şematik,

    f(A)=g(f(A[1..nc]),A)

    g

    Örnek: Lineer zamanda süperstarları bulma

  2. Böl ve Yönet

    Girdiyi daha küçük parçalara ayırın, her biri için sorunu çözün ve birleştirin. Şematik olarak (iki parça için),

    f(A)=g(f(A[1..c]),f(A[c+1..n]),A)

    Örnekler: Birleştirme / Hızlı Bağlantı, Düzlemde en kısa çift mesafe

  3. Dinamik program

    Sorunu daha küçük sorunlara bölmenin tüm yollarını düşünün ve en iyisini seçin. Şematik olarak (iki parça için),

    f(A)=best{g(f(A[1..c]),f(A[c+1..n]))|1cn1}

    Örnekler: Mesafeyi düzenle, Değişiklik yapma problemi

    best

Bir anlamda, yukarıdan aşağıya statik olarak gittikçe daha az ve daha azını biliyorsunuz ve dinamik olarak daha fazla ve daha fazla karar vermek zorundasınız.

Dinamik programlama hakkında bilgi edinmenin dersi, tüm olası bölümleri denemenin sorun değil (doğru, doğruluk için gerekli olduğu için), çünkü notlama kullanarak verimli olabilir.


"Pruned Dynamic Programming" (uygulandığında), tüm olasılıkları denemek için doğruluk için gerekli DEĞİLDİR.
Ben Voigt

Elbette @BenVoigt. "Bölmenin tüm yolları" ne anlama geldiği konusunda bilinçli olarak belirsiz kaldım; Elbette mümkün olduğu kadar fazla ekarte etmek istiyorum! (Bununla birlikte, tüm bölümleme yöntemlerini deneseniz bile kaba kuvvet elde edemezsiniz, çünkü yalnızca alt sorunlara en uygun çözümlerin kombinasyonlarını araştırırsınız , oysa kaba kuvvet tüm çözümlerin tüm kombinasyonlarını araştırır .)
Raphael


5

Dinamik Programlama, hesaplama süresi için bellek takas etmenize olanak sağlar. Fibonacci klasik örneğini düşünün.

Fib(n)=Fib(n1)+Fib(n2)O(2n)Fib()n

Fib(2)Fib(3)Fib(4)O(n)

mm


1
Sadece sorunun amacını kaçıran not bölümü hakkında konuşuyorsunuz.
Raphael

1
“Dinamik Programlama, hesaplama süresi için bellek takas etmenize izin verir”, lisans dersini yaparken duyduğum bir şey değil ve bu konuya bakmak için harika bir yol. Bu özlü bir örnek ile sezgisel bir cevaptır.
trueshot

Gerçek: Bazen dinamik programlamanın (ve özellikle "Pruned Dynamic Programming") hem zaman hem de alan gereksinimlerini azaltabilmesi dışında.
Ben Voigt

@Ben bire bir ticaret olduğunu söylemedim. Bir yineleme ağacını da budatabilirsiniz. “DP bizi ne alıyor?” Sorusunu yanıtladığımı belirtiyorum. Zamanla işlem yaparak bize daha hızlı algoritmalar kazandırır. Kabul edilen cevabın daha kapsamlı olduğuna katılıyorum, ancak bu da geçerli.
Kittsil 17:15

2

Dinamik programlamanın size sağladığı şeylerden birkaçı biraz daha farklı. Dinamik programlama, üstel bir sayıda aday çözümü bir polinom eşdeğerlik sınıfına indirger, böylece her bir sınıftaki aday çözümler bir anlamda ayırt edilemez.

kAn2nO(n2)f(i,)i

f(i,)=j<i such thatA[j]<A[i]f(j,1)
f(i,1)=1 for all i=1n

O(n2k)

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.