Search code examples
clojuremaxima

How do I translate a complicated recurrence from clojure to maxima?


I think this little program:

(defn average [lst] (/ (reduce + lst) (count lst)))
(defn sqsum [lst] (reduce + (map #(* % %) lst)))


(defn tet [row col]
  (cond (= [row col] [0 0]) 0
        (= [row col] [1 0]) 1
        (< row (inc col)) 0
        (> row (inc col)) (average (for [i (range row)] (tet i col)))
        (= row (inc col)) (Math/sqrt (- 1 (sqsum (for [i (range col)] (tet row i)))))))

gives me the coordinates of the vertices of generalised tetrahedra / euclidean simplices in various dimensions.

Unfortunately clojure will express things like sqrt(3/4) in floating point, whereas I'd like the answers in symbolic form.

Maxima would be ideal for this sort of thing, but I don't know how to express this relation in maxima.

Alternatively, solutions involving adding symbolic square roots to clojure would also be nice.


Solution

  • In Maxima, a memoizing function is defined by f[x, y] := ..., that is, with square brackets instead of parentheses for the arguments.

    From what I can tell, this is a translation of the Clojure function:

    average (lst) := apply ("+", lst) / length (lst);
    sqsum (lst) := apply ("+", map (lambda ([x], x^2), lst));
    
    tet [row, col] :=
      if row < col + 1 then 0
      else if row > col + 1 then average (makelist (tet [i, col], i, 0, row - 1))
      else if row = col + 1 then sqrt (1 - sqsum (makelist (tet [row, i], i, 0, col - 1)));
    
    tet [0, 0] : 0;
    tet [1, 0] : 1;
    

    E.g.:

    radcan (tet[4, 3]);
     => sqrt(5)/2^(3/2)
    
    radcan (tet[7, 6]);
     => 2/sqrt(7)
    

    First one agrees with a[4, 3] above. Dunno about the second.