2013-03-18 41 views
2

我开始学习Clojure,并试图实现一些基本的数值微分函数。我试图创建一个接受n变量函数的gradient函数以及评估它的点。为了以“功能性”的风格做到这一点,我想实现渐变作为单变量衍生物的mapClojure中部分输出变量函数中的第i个变量

1-可变衍生物的功能是简单的:

(defn derivative 
"Numerical derivative of a univariate function." 
[f x] 
    (let [eps 10e-6] ; Fix epsilon, just for starters. 
      ; Centered derivative is [f(x+e) - f(x-e)]/(2e) 
      (/ (- (f (+ x eps)) (f (- x eps))) (* 2 eps)))) 

我想设计沿着这些线的梯度:

(defn gradient 
"Numerical gradient of a multivariate function." 
[f & x] 
    (let [varity-index   (range (count x)) 
     univariate-in-i (fn [i] (_?_))] ; Creates a univariate fn 
             ; of x_i (other x's fixed) 
     ;; For each i = 0, ... n-1: 
     ;; (1) Get univariate function of x_i 
     ;; (2) Take derivative of that function 
     ;; Gradient is sequence of those univariate derivatives. 

     (map derivative (map univariate-in-i varity-index) x))) 

所以,gradient具有可变的元数(可以接受任何#的x's)以及x的计数顺序。函数univariate-in-i采用索引i = 0, 1, ... n-1,并通过将除x_i以外的所有变量进行部分分解来返回1变量函数。例如,你会得到:

#(f x_0 x_1 ... x_i-1 % x_i+1 ... x_n) 
        ^
        (x_i still variable) 

mapvarity-index -ping这个功能可以让你的1变量函数在每个x_i序列,然后map -ping derivative对这些让你衍生物的序列中的每个x_i这是我们想要的渐变。

我的问题是:我不确定实施univariate-in-i的好方法是什么。我基本上需要填写f中的x的值,除了某些特定的地方(即,放置上面的%),但是以编程方式。我对技术比解决方案更感兴趣(即我知道如何计算渐变,我试图学习函数式编程和惯用的Clojure)。因此,我想忠于将梯度视为一维导出函数的分布图的策略。但是如果有更好的“功能”方法,请告诉我。如果可能的话,我宁愿不求助于宏。

在此先感谢!

更新:

使用下面ANKUR的回答,梯度功能我得到的是:

(defn gradient 
"Numerical gradient of a multivariate function." 
[f & x] 
    (let [varity-index  (range (count x)) 
      x-vec   (vec x) 
      univariate-in-i 
      (fn [i] #(->> (assoc x-vec i %) (apply f)))] 

     (map derivative (map univariate-in-i varity-index) x))) 

这不正是我所希望的,而且似乎非常简洁和实用。

回答

2

您可以定义univariate-in-i,如下所示。 (假设所有其他位置值都是在某个var default中定义的,它是一个向量)

(fn [i] #(->> 
      (assoc default i %) 
      (apply f))) 
+0

'default'这里只是上面的'x' rest参数吧? – dfreeman 2013-03-18 17:21:52

+0

这很好用:'default'是'x',但是包裹在一个向量中对我来说完全理解有点微妙,但我会通过它来思考。我认为这是我正在寻找的答案。谢谢! – Carl 2013-03-18 17:39:37

+0

诀窍是向量实现'clojure.lang.Associative',这就是允许你在'i'处换掉元素的非应用参数:) – dfreeman 2013-03-18 17:50:48