Saya ingin membuat pohon sintaksis abstrak acak
(def terminal-set #{'x 'R})
(def function-arity {'+ 2, '- 2, '* 2, '% 2})
(def function-set (into #{} (keys function-arity)))
(def terminal-vec (into [] terminal-set))
(def function-vec (into [] function-set))
;; protected division
(defn % [^Number x ^Number y]
(if (zero? y)
0
(/ x y)))
dengan ukuran yang ditentukan
(defn treesize [tree] (count (flatten tree)))
mengikuti algoritma dari buku Sean Luke, 2013, Essentials of Metaheuristics, Lulu, edisi kedua, tersedia di https://cs.gmu.edu/~sean/book/metaheuristics/
Kami secara acak memperluas cakrawala pohon dengan simpul bukan daun hingga jumlah simpul bukan daun, ditambah bintik-bintik yang tersisa, lebih besar atau sama dengan ukuran yang diinginkan. Kami kemudian mengisi slot yang tersisa dengan simpul daun:
Misalnya
(+ (* x (+ x x)) x)
berukuran 7.
Algoritme dalam buku ini menggunakan pointer/referensi Q
yang sangat nyaman di sana. Dalam kasus saya, saya harus menggunakan semacam rekursi untuk membangun pohon. Masalahnya adalah saya tidak bisa menjaga status size
pohon di antara semua algoritma menggunakan rekursi yang menghasilkan pohon yang lebih besar:
(defn ptc2-tree
"Generate a random tree up to its `max-size`.
Note: `max-size` is the number of nodes, not the same as its depth."
[max-size]
(if (> 2 max-size)
(rand-nth terminal-vec)
(let [fun (rand-nth function-vec)
arity (function-arity fun)]
(cons fun (repeatedly arity #(ptc2-tree (- max-size arity 1)))))))
Saya juga mencoba menggunakan atom
untuk ukuran tetapi masih tidak mendapatkan ukuran pohon yang saya inginkan, mungkin terlalu kecil atau terlalu besar tergantung implementasinya.
Selain itu saya juga harus mengacak lokasi tempat saya memasukkan simpul/pohon baru.
Bagaimana cara menulis algoritma ini?
EDIT: Sentuhan terakhir untuk solusi yang tepat:
(defn sequentiate [v]
(map #(if (seqable? %) (sequentiate %) %) (seq v)))