(ns grad-descent.core)

(require '[clojure.math.numeric-tower :as math])
(require '[grad-descent.vec :as vmath])

(defn descent
  ; Function applies a gradient descent step to a vector of values, val.
  [val grad stepsize]
  (vmath/sub val (vmath/scale stepsize (grad val)))) ; implements v - step*grad(v)

; function to run the gradient descent algorithm with fixed step size
(defn gradient-descent
  ; This function takes a gradient function, gradfunc, and an initial condition, x0, to numerically 
  ; evaluate the minimum of a function. It will advance with stepsize and stop when the gradient
  ; has a manitude less than err.
  [gradfunc x0 stepsize err]      
  (loop [x x0]
    ;(prn x)
    (if (< (vmath/norm (gradfunc x)) err)
      x
      (recur (descent x gradfunc stepsize))
      )
    )
  )

; This function applies the gradient function used in the matlab files: f(x,y) = x^3+y^3
(defn example-grad
     [xs]
     (let [x (first xs)
           y (second xs)]
       [(* 3 (math/expt x 2)) (* 3 (math/expt y 2))]))
