Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active August 23, 2019 15:52

Revisions

  1. ericnormand revised this gist Aug 23, 2019. 2 changed files with 37 additions and 0 deletions.
    37 changes: 37 additions & 0 deletions Eric Normand.clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    (defn variable? [v]
    (symbol? v))

    (defn same-variable? [v1 v2]
    (and (variable? v1) (variable? v2) (= v1 v2)))

    (defn sum? [expr]
    (and (seq? expr)
    (= '+ (first expr))))

    (defn ->sum [u v]
    (list '+ u v))

    (defn prod? [expr]
    (and (seq? expr)
    (= '* (first expr))))

    (defn ->prod [u v]
    (list '* u v))

    (defn deriv [expr var]
    (cond
    (same-variable? expr var)
    1

    (or (variable? expr) (number? expr))
    0

    (sum? expr)
    (let [[_ u v] expr]
    (->sum (deriv u var) (deriv v var)))

    (prod? expr)
    (let [[_ u v] expr]
    (->sum
    (->prod u (deriv v var))
    (->prod v (deriv u var))))))
    File renamed without changes.
  2. ericnormand revised this gist Aug 18, 2019. 1 changed file with 29 additions and 0 deletions.
    29 changes: 29 additions & 0 deletions valerauko,clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    (defn sum? [exp]
    (= (first exp) '+))

    (defn product? [exp]
    (= (first exp) '*))

    (defn pred* [exp clauses]
    (when clauses
    (list 'if (list (first clauses) exp)
    (second clauses)
    (pred* exp (-> clauses next next)))))

    (defmacro pred [exp & clauses]
    (pred* exp clauses))

    (defn deriv [exp v]
    (pred exp
    number? 0
    symbol? (if (= exp v) 1 0)
    sum? (list '+
    (deriv (second exp) v)
    (deriv (last exp) v))
    product? (list '+
    (list '*
    (second exp)
    (deriv (last exp) v))
    (list '*
    (deriv (second exp) v)
    (last exp)))))
  3. ericnormand created this gist Aug 18, 2019.
    22 changes: 22 additions & 0 deletions 00 symbolic differentiation.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    *symbolic differentiation*

    I got excited last week by the numeric differentiator challenge. When I originally read that section of SICP so many years ago, I was elated. Do you know how hard that would be to do in Java?

    Now for something that's even harder to do in Java: symbolic differentiation.

    Here's the [relevant link into SICP](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.2), for reference.

    The challenge this week is to use four differentiation formulas to make a symbolic differentiator. It has been a while since I've done any calculus, so I had to look these up:

    1. `dc/dx = 0` (for a constant c, or variable c different from x)
    2. `dx/dx = 1`
    3. `d(u+v)/dx = du/dx + dv/dx` (addition rule)
    4. `d(uv)/dx = u(dv/dx) + v(du/dx)` (product rule)

    This won't differentiate every formula, but it will differentiate sums and products of variables and numbers. You should make a function that takes an expression and a variable to differentiate by, like so:

    ```clojure
    (deriv '(+ x 5) 'x) ;=> (+ 1 0)
    ```

    Don't worry about simplifying the final expression. Just make sure it's right.
    30 changes: 30 additions & 0 deletions Dan Dorman.clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    (ns symderiv.main)

    (defn deriv [expr v]
    (cond
    (list? expr) (let [[op a b] expr]
    (case op
    + (list '+ (deriv a v) (deriv b v))
    * (list '+ (list '* a (deriv b v)) (list '* b (deriv a v)))
    (throw (ex-info "Unrecognized operator" {:op op}))))
    (= expr v) 1
    (or (number? expr) (symbol? expr)) 0
    :else (throw (ex-info "Unrecognized expression" {:expr expr}))))

    (ns symderiv.main
    (:require [meander.strategy.delta :as r]))


    (defn deriv [expr var]
    (let [operations (r/rewrite
    ; addition
    (+ ?u ?v)
    (+ ~(deriv ?u var) ~(deriv ?v var))
    ; multiplication
    (* ?u ?v)
    (+ (* ?u ~(deriv ?v var)) (* ?v ~(deriv ?u var))))
    var' (r/pipe (r/pred #(= var %)) (r/build 1))
    constant' (r/pipe (r/pred number?) (r/build 0))
    other-var' (r/pipe (r/pred symbol?) (r/build 0))
    choice (r/choice operations var' other-var' constant')]
    (choice expr)))