2016-10-28 60 views
1

我在寫遺傳算法。爲了在運行時幫助玩這些設置,我試圖將設置(變異率,交叉機會,健身功能...)保存到磁盤。這將允許我修改文件,然後偶爾讀取文件以在運行時更新設置。從控制檯獲得輸入會更容易,但Intellij輸入的能力是非常殘酷的,並且難以使用,所以這就是我正在嘗試的路線。序列化匿名函數

我的問題是這樣的:設置是由記錄表示。許多個人設置都是數字,所以它們很容易保存到磁盤。然而,一些設置功能,不很好地保存:

(defrecord Settings [ 
       gene-set 
       sequence-length 
       fitness-f]) 

(with-out-str (pr 
       (->Settings #{1 2 3} 
          10 
          #(count %))))) 

產量:

"#ai.genetic_algorithm.genetic_algorithm2_2.Settings{:gene-set #{1 3 2}, :sequence-length 10, :fitness-f #object[ai.genetic_algorithm.genetic_algorithm2_2$eval776$fn__777$fn__778 0x1b30c92 \"ai[email protected]1b30c92\"]}" 

因爲這是很好,除了適應度函數的表示方式的大部分。如果我試圖讀取該文件回:

(read-string 
    (with-out-str (pr 
        (->Settings #{1 2 3} 
           10 
           #(count %))))) 

我得到:

ai.genetic-algorithm.genetic-algorithm2-2=> RuntimeException No reader function for tag object clojure.lang.LispReader$CtorReader.readTagged (LispReader.java:1245) 

,並試圖保存/讀取功能時,我只得到這個錯誤。我猜測它無法知道我要求它讀取函數,所以它barf。

有什麼辦法可靠地保存匿名函數文件?

是的,我知道read-string是有潛在危險的。儘管我只是將它用於個人項目,所以我並不擔心這個漏洞。

+0

可能的重複[我如何序列化函數在運行時在Clojure?](http://stackoverflow.com/questions/38753960/how-can-i-serialize-functions-at-runtime-in-clojure) – OlegTheCat

+0

@OlegTheCat哎呀。我不知道我怎麼沒有發現。謝謝。這似乎是非常複雜的,我需要它。我可能只需要nix保存這些功能,儘管這也使事情變得複雜:/ – Carcigenicate

回答

0

如果你改變你的代碼,而不是產生一個功能,再後來從命名空間中提取該功能將其保存到一個文件,你寧可生成的設置表達和表達保存到一個文件,然後向右。然後使用加載該文件的結果作爲新狀態。

user> (let [new-config '{:gene-set #{1 2 3} 
         :sequence-length 10 
         :fitness-f (fn [x] (count x))}] 
      (with-open [w (clojure.java.io/writer "/tmp/config.edn")] 
      (binding [*out* w] 
       (pr new-config)))  
      (load-file "/tmp/config.edn")) 

{:gene-set #{1 3 2}, 
:sequence-length 10, 
:fitness-f #function[user/eval111126/fn--111127]} 
當你定義新的健身功能,節省,產生它作爲符號序列並保存該序列之前,它被編譯成一個函數類

。讓它唯一編譯的時候是它加載的時候,所以你知道它永遠是可加載的東西。這將捕捉錯誤。

如果您發現自己想要機械地生成這些組合,您可能需要考慮給它們命名,只保存配置中的組合順序。