Bisakah Jacobian yang diperkirakan dengan perbedaan hingga menyebabkan ketidakstabilan dalam metode Newton?

13

Saya telah menerapkan pemecah Euler mundur dalam python 3 (menggunakan numpy). Untuk kenyamanan saya sendiri dan sebagai latihan, saya juga menulis fungsi kecil yang menghitung perkiraan perbedaan hingga dari gradien sehingga saya tidak selalu harus menentukan Jacobian secara analitis (jika itu mungkin!).

Menggunakan deskripsi yang disediakan dalam Ascher dan Petzold 1998 , saya menulis fungsi ini yang menentukan gradien pada titik x:

def jacobian(f,x,d=4):
    '''computes the gradient (Jacobian) at a point for a multivariate function.

    f: function for which the gradient is to be computed
    x: position vector of the point for which the gradient is to be computed
    d: parameter to determine perturbation value eps, where eps = 10^(-d).
        See Ascher und Petzold 1998 p.54'''

    x = x.astype(np.float64,copy=False)
    n = np.size(x)
    t = 1 # Placeholder for the time step
    jac = np.zeros([n,n])
    eps = 10**(-d)
    for j in np.arange(0,n):
        yhat = x.copy()
        ytilde = x.copy()
        yhat[j] = yhat[j]+eps
        ytilde[j] = ytilde[j]-eps
        jac[:,j] = 1/(2*eps)*(f(t,yhat)-f(t,ytilde))
    return jac

Saya menguji fungsi ini dengan mengambil fungsi multivariat untuk pendulum dan membandingkan Jacobian simbolis dengan gradien yang ditentukan secara numerik untuk berbagai titik. Saya senang dengan hasil tes, kesalahannya sekitar 1e-10. Ketika saya memecahkan ODE untuk pendulum menggunakan Jacobian yang didekati, itu juga bekerja dengan sangat baik; Saya tidak bisa mendeteksi perbedaan antara keduanya.

Kemudian saya mencoba mengujinya dengan PDE berikut (persamaan Fisher dalam 1D):

tkamu=x(kxkamu)+λ(kamu(C-kamu))

menggunakan diskritisasi perbedaan hingga.

Sekarang metode Newton meledak di catatan waktu pertama:

/home/sfbosch/Fisher-Equation.py:40: RuntimeWarning: overflow encountered in multiply
  du = (k/(h**2))*np.dot(K,u) + lmbda*(u*(C-u))
./newton.py:31: RuntimeWarning: invalid value encountered in subtract
  jac[:,j] = 1/(2*eps)*(f(t,yhut)-f(t,yschlange))
Traceback (most recent call last):
  File "/home/sfbosch/Fisher-Equation.py", line 104, in <module>
    fisher1d(ts,dt,h,L,k,C,lmbda)
  File "/home/sfbosch/Fisher-Equation.py", line 64, in fisher1d
    t,xl = euler.implizit(fisherode,ts,u0,dt)
  File "./euler.py", line 47, in implizit
    yi = nt.newton(g,y,maxiter,tol,Jg)
  File "./newton.py", line 54, in newton
    dx = la.solve(A,b)
  File "/usr/lib64/python3.3/site-packages/scipy/linalg/basic.py", line 73, in solve
    a1, b1 = map(np.asarray_chkfinite,(a,b))
  File "/usr/lib64/python3.3/site-packages/numpy/lib/function_base.py", line 613, in asarray_chkfinite
    "array must not contain infs or NaNs")
ValueError: array must not contain infs or NaNs

Ini terjadi untuk berbagai nilai eps, tetapi anehnya, hanya ketika ukuran langkah spasial PDE dan ukuran langkah waktu ditetapkan sehingga kondisi Courant-Friedrichs-Lewy tidak terpenuhi. Kalau tidak berhasil. (Ini adalah perilaku yang Anda harapkan jika menyelesaikan dengan meneruskan Euler!)

Untuk kelengkapan, berikut adalah fungsi untuk Metode Newton:

def newton(f,x0,maxiter=160,tol=1e-4,jac=jacobian):
    '''Newton's Method.

    f: function to be evaluated
    x0: initial value for the iteration
    maxiter: maximum number of iterations (default 160)
    tol: error tolerance (default 1e-4)
    jac: the gradient function (Jacobian) where jac(fun,x)'''

    x = x0
    err = tol + 1
    k = 0
    t = 1 # Placeholder for the time step
    while err > tol and k < maxiter:
        A = jac(f,x)
        b = -f(t,x)
        dx = la.solve(A,b)
        x = x + dx
        k = k + 1
        err = np.linalg.norm(dx)
    if k >= maxiter:
        print("Maxiter reached. Result may be inaccurate.")
        print("k = %d" % k)
    return x

(Fungsi la.solve adalah scipy.linalg.solve.)

Saya yakin bahwa implementasi Euler terbelakang saya adalah dalam rangka, karena saya telah mengujinya menggunakan fungsi untuk Jacobian dan mendapatkan hasil yang stabil.

Saya dapat melihat di debugger bahwa newton () mengelola 35 iterasi sebelum kesalahan terjadi. Jumlah ini tetap sama untuk setiap eps yang saya coba.

Pengamatan tambahan: ketika saya menghitung gradien dengan FDA dan fungsi menggunakan kondisi awal sebagai input dan membandingkan keduanya sambil memvariasikan ukuran epsilon, kesalahan tumbuh sebagai epsilon menyusut. Saya berharap itu menjadi besar pada awalnya, kemudian menjadi lebih kecil, kemudian lebih besar lagi saat epsilon menyusut. Jadi kesalahan dalam implementasi Jacobian saya adalah asumsi yang masuk akal, tetapi jika demikian, itu sangat halus sehingga saya tidak dapat melihatnya. EDIT: Saya memodifikasi jacobian () untuk menggunakan maju alih-alih perbedaan pusat, dan sekarang saya mengamati perkembangan kesalahan yang diharapkan. Namun, newton () masih gagal bertemu. Mengamati dx dalam iterasi Newton, saya melihat bahwa itu hanya tumbuh, bahkan tidak ada fluktuasi: hampir dua kali lipat (faktor 1.9) dengan setiap langkah, dengan faktor semakin besar semakin.

Ascher dan Petzold menyebutkan bahwa perbedaan perkiraan untuk Jacobian tidak selalu bekerja dengan baik. Bisakah seorang Jacobian yang didekati dengan perbedaan hingga menyebabkan ketidakstabilan dalam metode Newton? Atau penyebabnya di tempat lain? Bagaimana lagi saya bisa mendekati masalah ini?

Stephen Bosch
sumber
1
"Saya yakin bahwa implementasi Euler yang terbelakang saya sesuai, karena saya telah mengujinya menggunakan fungsi untuk Jacobian dan mendapatkan hasil yang stabil." Mohon klarifikasi. Apakah Anda mengatakan bahwa Anda menjalankan masalah yang sama dengan Jacobian yang tepat dan solusi menyatu dengan solusi yang tepat dari PDE? Itu informasi penting.
David Ketcheson
@ Davidvideteson Ya, itulah yang saya katakan. Mohon maaf jika terminologi saya salah atau tidak lengkap. (Saya kira saya seharusnya mengatakan, "Saya mendapatkan hasil yang stabil dan diharapkan.")
Stephen Bosch

Jawaban:

3

Lebih dari komentar panjang daripada yang lain:

Menggunakan deskripsi yang disediakan dalam Ascher dan Petzold 1998, saya menulis fungsi ini yang menentukan gradien pada titik x:

Lihatlah kode untuk selisih perkiraan SUNDIALS 'untuk mendapatkan ide yang lebih baik dari apa yang harus Anda lakukan dalam implementasi. Ascher dan Petzold adalah buku yang bagus untuk memulai, tetapi SUNDIALS sebenarnya digunakan dalam pekerjaan produksi, dan karenanya telah diuji lebih baik. (Juga, SUNDIALS terkait dengan DASPK, yang digarap Petzold.)

Ascher dan Petzold menyebutkan bahwa perbedaan perkiraan untuk Jacobian tidak selalu bekerja dengan baik. Bisakah seorang Jacobian yang didekati dengan perbedaan hingga menyebabkan ketidakstabilan dalam metode Newton?

Secara empiris, perkiraan Jacobian dapat menyebabkan kegagalan konvergensi dalam metode Newton. Saya tidak tahu bahwa saya akan menganggap mereka sebagai "ketidakstabilan"; dalam beberapa kasus, tidak mungkin untuk mencapai toleransi kesalahan yang diinginkan dalam kriteria terminasi. Dalam kasus lain, itu bisa bermanifestasi sebagai ketidakstabilan. Saya hampir yakin ada hasil yang lebih kuantitatif tentang fenomena ini dalam buku metode numerik Higham, atau diskusi Hairer dan Wanner tentang metode-W.

Atau penyebabnya di tempat lain? Bagaimana lagi saya bisa mendekati masalah ini?

Tergantung di mana Anda pikir kesalahannya. Jika Anda sangat percaya diri dalam penerapan Euler mundur Anda, saya tidak akan mulai dari sana. Pengalaman telah membuat saya paranoid dalam implementasi metode numerik saya, jadi jika itu saya, saya akan mulai dengan mengkodekan beberapa masalah tes yang sangat mendasar (beberapa masalah linear kaku dan kaku, persamaan panas dengan perkiraan perbedaan hingga terpusat, hal-hal seperti itu) dan saya akan menggunakan metode solusi buatan untuk meyakinkan diri saya bahwa saya tahu akan menjadi apa solusinya, dan apa yang harus saya bandingkan.

Namun, Anda sudah melakukan itu:

Saya yakin bahwa implementasi Euler terbelakang saya adalah dalam rangka, karena saya telah mengujinya menggunakan fungsi untuk Jacobian dan mendapatkan hasil yang stabil.

Itu akan menjadi hal berikutnya yang akan saya uji: gunakan Jacobian analitik. Setelah itu, Anda mungkin juga melihat nilai eigen ekstrem dari perbedaan terbatas Anda Jacobian jika Anda berada di wilayah yang tidak stabil dari Euler terbelakang. Melihat nilai eigen ekstrem dari Jacobian analitis Anda sebagai dasar perbandingan mungkin memberi Anda wawasan. Dengan asumsi mereka semua memeriksa, masalahnya mungkin ada di Newton.

Geoff Oxberry
sumber
Terima kasih atas analisis yang bijaksana (ditambah petunjuk SUNDIALS dan sumber alternatif). Profesor saya menyarankan pengaturan lambda = 0, dengan alasan bahwa FDA dari PDE kemudian menjadi linier, jadi kami berharap FDA Jacobian sama dengan Jacobian analitik. Ketika saya melakukan ini, ia mengatur tiga timesteps, newton () menekan maxiter setiap kali, sebelum akhirnya meledak seperti sebelumnya.
Stephen Bosch
Dia juga mengatakan itu bukan praktik umum untuk menggunakan Jacobian yang diperkirakan untuk memecahkan PDE dan menyarankan bahwa mungkin ada masalah karena banyak derajat kebebasan (tanpa memberikan penjelasan, meskipun baru saja melihat diskusi Hairer dan Wanner tentang metode-W, Saya dapat melihat bahwa itu mungkin tidak sepele).
Stephen Bosch
1
Pernyataan profesor Anda agak mengejutkan, mengingat banyaknya literatur tentang subjek tersebut, misalnya ulasan terkenal ini oleh Knoll dan Keyes . Saya mungkin harus mengutip makalah ini dalam jawaban saya, karena sumber-sumber dalam daftar pustaka juga dapat membantu dalam mendiagnosis masalah Anda.
Geoff Oxberry