Writing the Lp norm function

331 Views Asked by At

I'm attempting to write the Lp norm function as to generalize the standard L2 norm (Euclidean distance) used. Here is what I have come up with so far, given how I had written the L2 norm:

(defn foo [a b p]
     (reduce + (map (comp (map #(power a %) p) -) a b)))

However I am getting the error ClassCastException whenever I try to implement this function. Part of the interim code is from a previously asked question Raising elements in a vector to a power where the following code was provided:

(defn compute [exp numbers]
     (map #(power exp %) numbers))
2

There are 2 best solutions below

0
On BEST ANSWER

Consider factoring your code.

First define the p-norm

(defn p-norm [p x] 
   (if (= p :infinity) 
     (apply max (for [xi x] (Math/abs xi)))
     (Math/pow 
       (reduce + (for [xi x] (Math/pow xi p))) 
       (/ 1 p))))

And then use the p-norm to define your p-metric

(defn p-metric [p x y] 
  (p-norm p (map - x y)))

Example

(p-metric 2 [0 0] [3 4])
;=> 5.0

(p-metric :infinity [0 0] [3 4])
;=> 4
0
On

Your inner (map):

(map #(power a %) p)

Returns a sequence and you can't feed that to (comp). 'comp' is for 'Function Composition'.

In the REPL:

(doc comp)
clojure.core/comp
([] [f] [f g] [f g h] [f1 f2 f3 & fs])
  Takes a set of functions and returns a fn that is the composition
  of those fns.  The returned fn takes a variable number of args,
  applies the rightmost of fns to the args, the next
  fn (right-to-left) to the result, etc.

Start breaking your code into smaller steps. (let) form is quite handy, don't be shy to use it.