2016-10-28 62 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]} 
当你定义新的健身功能,节省,产生它作为符号序列并保存该序列之前,它被编译成一个函数类

。让它唯一编译的时候是它加载的时候,所以你知道它永远是可加载的东西。这将捕捉错误。

如果您发现自己想要机械地生成这些组合,您可能需要考虑给它们命名,只保存配置中的组合顺序。