我在写遗传算法。为了帮助在运行时使用设置,我试图保存这些设置(变异率、交叉机会、健身功能.)去磁盘。这将允许我修改文件,然后偶尔读取该文件,以便在运行时更新设置。从控制台获取输入会更容易,但是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.genetic_algorithm.genetic_algorithm2_2$eval776$fn__777$fn__778@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)只有在尝试保存/读取函数时才会出现此错误。我猜它不可能知道我要求它读取函数的内容,所以它会变胖。
有什么方法可以可靠地保存匿名函数吗?
是的,我知道read-string有潜在的危险。不过,我只是把它用于个人项目,所以我并不担心这个漏洞。
发布于 2016-10-29 00:16:48
如果您将代码改为生成函数,然后从命名空间提取函数以将其保存到文件中,则应该为设置生成表达式,然后立即将表达式保存到文件中。然后将加载该文件的结果作为新状态使用。
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]}当您定义要保存的新适应度函数时,将其生成为符号序列,并在编译成函数类之前保存该序列。让它编译的唯一时间是在加载时,这样您就知道它总是可以加载的。这会抓住虫子的。
如果您发现自己希望机械地生成这些组合,您可能需要考虑给它们命名一个只保存配置中的组合顺序的名称。
https://stackoverflow.com/questions/40305522
复制相似问题