The StreamMemo perpustakaan untuk Coq menggambarkan bagaimana memoize fungsi f : nat -> A
melalui nomor alami. Terutama saat f (S n) = g (f n)
, imemo_make
berbagi perhitungan panggilan rekursif.
Misalkan alih-alih bilangan alami, kami ingin memoize fungsi rekursif atas pohon biner:
Inductive binTree : Set :=
| Leaf : binTree
| Branch : binTree -> binTree -> binTree.
Misalkan kita memiliki fungsi f : binTree -> A
yang bersifat rekursif secara struktural, artinya ada fungsi g : A -> A -> A
sedemikian rupa f (Branch x y) = g (f x) (f y)
. Bagaimana kita membuat tabel memo serupa untuk f
dalam Coq sehingga perhitungan rekursif dibagikan?
Di Haskell, tidak terlalu sulit untuk membuat tabel memo seperti itu (lihat MemoTrie misalnya) dan mengikat. Jelas tabel memo seperti itu produktif. Bagaimana kita bisa mengatur hal-hal untuk meyakinkan bahasa yang diketik secara dependen untuk menerima ikatan seperti itu produktif?
Meskipun saya telah menentukan masalah dalam Coq, saya akan senang dengan jawaban dalam Agda atau bahasa yang diketik dengan dependen lainnya.
sumber
go
nilainya adalah fungsi dari parameter Ukuran. Secara umum, tidak ada pembagian antara panggilan fungsi independen pada nilai yang sama. Ini mungkin dapat diperbaiki dengan menambahkan pernyataan let dalam definisih (Branch l r)
. Kedua, definisi bertingkat yangBT
berarti bahwa dua pohon, jika tidak identik bentuknya, akan memiliki nilai yang berbeda ketika mereka muncul di tingkat yang berbeda. Nilai-nilai berbeda ini tidak akan dibagikan di MemoTrie.Memo
dibranch
. Pemeriksa positif Coq tampaknya menolak ini, membuat segalanya menjadi lebih rumit dalam Coq.Size
tipe - tipe itu terhapus.Saya telah menciptakan "solusi" yang secara rekursif menghafal fungsi rekursif struktur pohon biner dalam Coq. Intisari saya ada di https://gist.github.com/roconnor/286d0f21af36c2e97e74338f10a4315b .
Ini beroperasi mirip dengan solusi Saizan , dengan stratifikasi pohon biner berdasarkan ukuran metrik, dalam kasus saya menghitung jumlah node internal pohon biner, dan menghasilkan aliran malas wadah semua solusi untuk ukuran tertentu. Berbagi terjadi karena pernyataan let di generator aliran yang memegang bagian awal dari aliran yang akan digunakan di bagian selanjutnya dari aliran.
Contoh menunjukkan bahwa untuk
vm_compute
, mengevaluasi pohon biner sempurna dengan 8 level setelah mengevaluasi pohon biner sempurna dengan 9 level jauh lebih cepat daripada hanya mengevaluasi pohon biner sempurna dengan 8 level.Namun, saya ragu untuk menerima jawaban ini karena overhead dari solusi khusus ini buruk sehingga berkinerja jauh lebih buruk daripada memoisasi saya tanpa rekursi struktural untuk contoh input praktis saya. Secara alami, saya ingin solusi yang berkinerja lebih baik di bawah input yang masuk akal.
Saya punya beberapa komentar lebih lanjut di " [Coq-Club] Bagaimana Anda bisa membangun tabel memoisasi coinductive untuk fungsi rekursif atas pohon biner? ".
sumber