Difference between revisions of "Calculate a derivative"

From CodeCodex

(Lisp)
Line 96: Line 96:
 
   ((eq (car e) '*) `(+ (* ,(cadr e) ,(d (caddr e) x))
 
   ((eq (car e) '*) `(+ (* ,(cadr e) ,(d (caddr e) x))
 
                         (* ,(caddr e) ,(d (cadr e) x))))))
 
                         (* ,(caddr e) ,(d (cadr e) x))))))
 +
 +
(defun string_of (e)
 +
  (cond
 +
  ((atom e) e (format nil "~A" e))
 +
  (t (concatenate 'string
 +
  "(" (string_of (cadr e))
 +
  (format nil "~A" (car e))
 +
  (string_of (caddr e)) ")"))))
  
 
(defvar e '(+ (+ (* a (* x x)) (* b x)) c))
 
(defvar e '(+ (+ (* a (* x x)) (* b x)) c))
  
(d e 'x)
+
(string_of (d e 'x))
 
</pre>
 
</pre>
  

Revision as of 18:48, 4 August 2006

Related content:

Compute and print the derivative of the symbolic expression a x^2 + b x + c.

C++

#include <iostream>

using namespace std;

class Var;

class Base {
public:
  virtual ~Base() {};
  virtual const Base *clone() = 0;
  virtual const Base *d(const string &v) const = 0;
  virtual ostream &print(ostream &o) const = 0;
};

ostream &operator<<(ostream &o, const Base &e) { e.print(o); return o; }

class Int : public Base {
  const int n;
public:
  Int(int m) : n(m) {}
  ~Int() {}
  const Base *clone() { return new Int(n); }
  const Base *d(const string &v) const { return new Int(0); }
  ostream &print(ostream &o) const { return o << n; }
};

class Var : public Base {
  const string var;
public:
  Var(string v) : var(v) {}
  ~Var() {}
  const Base *clone() { return new Var(var); }
  const Base *d(const string &v) const { return new Int(var == v ? 1 : 0); }
  ostream &print(ostream &o) const { return o << var; }
};

class Plus : public Base {
  const Base *e1, *e2;
public:
  Plus(const Base *a, const Base *b) : e1(a), e2(b) {}
  ~Plus() { delete e1; delete e2; }
  const Base *clone() { return new Plus(e1, e2); }
  const Base *d(const string &v) const { return new Plus(e1->d(v), e2->d(v)); }
  ostream &print(ostream &o) const
  { return o << "(" << *e1 << " + " << *e2 << ")"; }
};

class Times : public Base {
  const Base *e1, *e2;
public:
  Times(const Base *a, const Base *b) : e1(a), e2(b) {}
  ~Times() { delete e1; delete e2; }
  const Base *clone() { return new Times(e1, e2); }
  const Base *d(const string &v) const
  { return new Plus(new Times(e1, e2->d(v)), new Times(e1->d(v), e2)); }
  ostream &print(ostream &o) const { return o << "(" << *e1 << " * " << *e2 << ")"; }
};

class Expr {
public:
  Base *e;
  Expr(Base *a) : e(a) {}
};

const Expr operator+(const Expr e1, const Expr e2)
{ return Expr(new Plus(e1.e->clone(), e2.e->clone())); }
const Expr operator*(const Expr e1, const Expr e2)
{ return Expr(new Times(e1.e->clone(), e2.e->clone())); }

ostream &operator<<(ostream &o, const Expr e) { return o << e.e; }

int main() {
  Var vx("x"), va("a"), vb("b"), vc("c");
  Expr x(&vx), a(&va), b(&vb), c(&vc);
  Expr e = a*x*x + b*x + c;
  cout << "d(" << *(e.e) << ", x) = " << *(e.e->d("x")) << endl;
  return 0;
}

Lisp

Lisp benefits from the use of the built-in s-expression type:

(defun d (e x)
  (cond
   ((atom e) (if (eq e x) 1 0))
   ((eq (car e) '+) `(+ ,(d (cadr e) x) ,(d (caddr e) x)))
   ((eq (car e) '*) `(+ (* ,(cadr e) ,(d (caddr e) x))
                        (* ,(caddr e) ,(d (cadr e) x))))))

(defun string_of (e)
  (cond
   ((atom e) e (format nil "~A" e))
   (t (concatenate 'string
		   "(" (string_of (cadr e))
		   (format nil "~A" (car e))
		   (string_of (caddr e)) ")"))))

(defvar e '(+ (+ (* a (* x x)) (* b x)) c))

(string_of (d e 'x))

Note that this implementation doesn't include printing.

OCaml

Conventionally, the expr type would be declared as a variant type:

type expr =
    | Int of int
    | Plus of expr * expr
    | Times of expr * expr
    | Var of string

let rec d(e, x) = match e with
  | Int n -> Int 0
  | Plus(f, g) -> Plus(d(f, x), d(g, x))
  | Times(f, g) -> Plus(Times(f, d(g, x)), Times(g, d(f, x)))
  | Var v -> Int (if v=x then 1 else 0)

let rec string_of = function
  | Int n -> string_of_int n
  | Var v -> v
  | Plus(f, g) -> "("^string_of f^" + "^string_of g^")"
  | Times(f, g) -> "("^string_of f^" * "^string_of g^")"

let ( +: ) e1 e2 = Plus(e1, e2)
let ( *: ) e1 e2 = Times(e1, e2)

let x = Var "x" and a = Var "a" and b = Var "b" and c = Var "c"

let e = a *: x *: x +: b *: x +: c

let () = Printf.printf "d(%s, x) = %s\n" (string_of e) (string_of (d(e, "x")))

OCaml also allows the expr type to be inferred via the use of polymorphic variants:

let ( +: ) e1 e2 = `Plus(e1, e2)
let ( *: ) e1 e2 = `Times(e1, e2);;

let rec d(e, x) = match e with
  | `Int n -> `Int 0
  | `Plus(f, g) -> d(f, x) +: d(g, x)
  | `Times(f, g) -> f *: d(g, x) +: g *: d(f, x)
  | v -> `Int (if v=x then 1 else 0);;

let rec string_of = function
  | `Int n -> string_of_int n
  | `Plus(f, g) -> "("^string_of f^" + "^string_of g^")"
  | `Times(f, g) -> "("^string_of f^" * "^string_of g^")"
  | `x -> "x" | `a -> "a" | `b -> "b" | `c -> "c";;

let e = `a *: `x *: `x +: `b *: `x +: `c;;

let () = Printf.printf "d(%s, x) = %s\n" (string_of e) (string_of (d(e, `x)));;