(save-buffer) (let ((org-confirm-babel-evaluate (lambda (lang body) (declare (ignorable lang body)) nil))) (org-latex-export-to-pdf))
(save-buffer) (let ((python-indent-offset 4)) (org-babel-tangle))
CLOSED: [2016-05-01 Sun 14:33]
As a part of my lisp-based Computer Algebra System, an algebraic manipulation toolkit is required. This will be used to simplify equations, or for that matter solve them. This creates this toolkit, but does not create a complete simplifier or solver. It does this by providing manipulators and automatic rewriters. These together will provide simplification and solving utilities.
[0/5]
<<classification-storage>> <<define-classification>> <<check-classification>> <<classify-expression>> <<possible-classifications>>
(defvar *classifications* '())
(defmacro define-classification (name &body body) `(progn (defun ,(symbolicate name '-classifier) (expression &aux (length (if (listp expression) (length expression) 1))) (declare (ignorable length)) ,@body) (pushnew '(,name . ,(symbolicate name '-classifier)) *classifications*) ',name))
(defun expression-type-p (expression type) (if (eq '* type) t (funcall (cdr (assoc type *classifications*)) expression)))
(defun classify (expression) (remove-if #'null (map 'list #'(lambda (name-and-checker) (let ((name (car name-and-checker)) (checker (cdr name-and-checker))) (if (funcall checker expression) name nil))) ,*classifications*)))
[0/12]
<<classify-numbers>> <<classify-variables>> <<classify-additives>> <<classify-subtractives>> <<classify-powers>> <<classify-exponentials>> <<classify-multiplicatives>> <<classify-logarithmics>> <<classify-rationals>> <<classify-polynomial-term>> <<classify-polynomials>> <<classify-trigonometrics>>
(define-classification numeric (numberp expression))
(define-classification variable (symbolp expression))
(define-classification additive (when (listp expression) (eq '+ (first expression))))
(define-classification subtractive (when (listp expression) (eq '- (first expression))))
(define-classification power (when (listp expression) (and (eq 'expt (first expression)) (expression-type-p (second expression) 'variable) (expression-type-p (third expression) 'numeric))))
(define-classification natural-exponential (when (listp expression) (and (= 2 length) (eq 'exp (first expression))))) (define-classification exponential (when (listp expression) (and (= 3 length) (eq 'expt (first expression)))))
(define-classification multiplicative (when (listp expression) (eq '* (first expression))))
(define-classification natural-logarithmic (when (listp expression) (and (= 2 length) (eq 'log (first expression))))) (define-classification logarithmic (when (listp expression) (and (= 3 length) (eq 'log (first expression)))))
(define-classification rational (when (listp expression) (and (= 3 length) (eq '/ (first expression)))))
(define-classification polynomial-term (or (expression-type-p expression 'numeric) (expression-type-p expression 'variable) (expression-type-p expression 'power) (and (expression-type-p expression 'multiplicative) (= (length (rest expression)) 2) (or (and (expression-type-p (second expression) 'numeric) (or (expression-type-p (third expression) 'power) (expression-type-p (third expression) 'variable))) (and (expression-type-p (third expression) 'numeric) (or (expression-type-p (second expression) 'power) (expression-type-p (second expression) 'variable)))))))
(define-classification polynomial (when (listp expression) (and (or (eq '- (first expression)) (eq '+ (first expression))) (reduce #'(lambda (a b) (and a b)) (map 'list #'(lambda (the-expression) (expression-type-p the-expression 'polynomial-term)) (rest expression))))))
(define-classification sin (when (listp expression) (eq 'sin (first expression)))) (define-classification cos (when (listp expression) (eq 'cos (first expression)))) (define-classification tan (when (listp expression) (eq 'tan (first expression)))) (define-classification csc (when (listp expression) (eq 'csc (first expression)))) (define-classification sec (when (listp expression) (eq 'sec (first expression)))) (define-classification cot (when (listp expression) (eq 'cot (first expression))))
Foo
(defun collect-terms (expression) (let ((terms (rest expression))) ))
(defun coefficient (term) (when (expression-type-p term 'polynomial-term) (cond ((expression-type-p term 'variable) 1) ((expression-type-p term 'power) 1) ((expression-type-p term 'multiplicative) (second term)) ((expression-type-p term 'numeric) term)))) (defun term-variable (term) (when (expression-type-p term 'polynomial-term) (cond ((expression-type-p term 'multiplicative) (second (third term))) ((expression-type-p term 'power) (second term)) (t nil)))) (defun get-power (term) (cond ((expression-type-p term 'power) (third term)) ((expression-type-p term 'polynomial-term) (third (third term))) (t 0))) (defun same-order-p (term-a term-b) (= (get-power term-a) (get-power term-b))) (defun same-variable-p (term-a term-b) (eq (term-variable term-a) (term-variable term-b))) (defun single-term-combinable-p (term-a term-b) (and (same-order-p term-a term-b) (same-variable-p term-a term-b)))
[0/8]
Foo
<<misc-manipulator-functions>> <<define-expression-manipulator>> <<external-manipulator>> <<addition-manipulator>> <<subtraction-manipulator>> <<multiplication-manipulators>>
(defvar *manipulator-map* '()) (defun gen-args-list (count) (let ((letters '(a b c d e f g h i j k l m n o p q r s t u v w x y z))) (loop for i from 1 to count collect (symbolicate 'expression- (nth (1- i) letters)))))
(defmacro define-operation (name arity short) (check-type name symbol) (check-type arity (integer 1 26)) (check-type short symbol) (let* ((args (gen-args-list arity)) (expression-types (map 'list #'(lambda (x) (symbolicate x '-type)) args)) (rules-name (symbolicate '*manipulators- name '*)) (base-manipulator-name (symbolicate name '-manipulator-)) (manipulator-define-name (symbolicate 'define- name '-manipulator)) (is-applicable-name (symbolicate name '-is-applicable-p)) (get-operations-name (symbolicate 'get- name '-manipulators)) (type-check-list (let ((i 0)) (loop for arg in args collect (prog1 `(expression-type-p ,arg (nth ,i types)) (incf i)))))) `(progn (push '(,short . ,name) *manipulator-map*) (defvar ,rules-name '()) (defun ,is-applicable-name (types ,@args) (and ,@type-check-list)) (defun ,get-operations-name (,@args) (remove-if #'null (map 'list #'(lambda (option) (let ((types (car option)) (name (cdr option))) (if (,is-applicable-name types ,@args) name))) ,rules-name))) (defun ,name (,@args) (funcall (first (,get-operations-name ,@args)) ,@args)) (defmacro ,manipulator-define-name ((,@expression-types) &body body) (let ((manipulator-name (symbolicate ',base-manipulator-name ,@expression-types))) `(progn (setf ,',rules-name (append ,',rules-name '(((,,@expression-types) . ,manipulator-name)))) (defun ,manipulator-name ,',args ,@body)))))))
;; (defun manipulate (action &rest expressions) ;; (case action ;; (+ ;; (reduce #'add expressions)) ;; (- ;; (reduce #'subtract expressions)) ;; (* ;; (reduce #'multiply expressions)) ;; (/ ;; (reduce #'divide expressions)) ;; (sin ;; (reduce #'manip-sin expressions)) ;; (cos ;; (reduce #'manip-cos expressions)) ;; (tan ;; (reduce #'manip-tan expressions)) ;; (expt ;; (reduce #'powers expressions))))
Foo
(define-operation add 2 +) (define-add-manipulator (numeric numeric) (+ expression-a expression-b)) (define-add-manipulator (numeric additive) (let ((total expression-a) (remainder (rest expression-b)) (non-numeric '())) (dolist (element remainder) (if (expression-type-p element 'numeric) (incf total element) (push element non-numeric))) (cond ((null non-numeric) total) ((= 0 total) `(+ ,@non-numeric)) (t `(+ ,total ,@non-numeric))))) (define-add-manipulator (additive additive) (let ((total 0) (elements (append (rest expression-a) (rest expression-b))) (non-numeric '())) (dolist (element elements) (if (expression-type-p element 'numeric) (incf total element) (push element non-numeric))) (cond ((null non-numeric) total) ((= 0 total) `(+ ,@non-numeric)) (t `(+ ,total ,@non-numeric))))) (define-add-manipulator (numeric subtractive) (let ((total expression-a) (the-other (rest expression-b)) (non-numeric '())) (dolist (element the-other) (if (expression-type-p element 'numeric) (decf total element) (push element non-numeric))) (cond ((null non-numeric) total) ((= 0 total) `(+ ,@non-numeric)) (t `(+ ,total (-,@non-numeric)))))) (define-add-manipulator (numeric polynomial-term) `(+ ,expression-a ,expression-b)) (define-add-manipulator (polynomial-term polynomial-term) (if (single-term-combinable-p expression-a expression-b) (let ((new-coefficient (+ (coefficient expression-a) (coefficient expression-b))) (variable (term-variable expression-a)) (power (get-power expression-a))) `(* ,new-coefficient (expt ,variable ,power))) `(+ ,expression-a ,expression-b))) (define-add-manipulator (* numeric) (add expression-b expression-a))
Foo
(define-operation subtract 2 -) (define-subtract-manipulator (numeric numeric) (- expression-a expression-b)) (define-subtract-manipulator (numeric subtractive) (let ((total expression-a) (elements (rest expression-b)) (non-numeric '())) (dolist (element elements) (if (expression-type-p element 'numeric) (decf total element) (push element non-numeric))) (cond ((null non-numeric) total) ((= 0 total) `(- ,@(reverse non-numeric))) (t `(- ,total ,@(reverse non-numeric)))))) (define-subtract-manipulator (* numeric) (subtract expression-b expression-a))
Foo
(define-operation multiply 2 *)
Foo
(define-operation division 2 /)
Foo
Foo
(defpackage #:manipulator (:use #:cl) (:import-from #:alexandria #:symbolicate) (:export #:manipulate)) (in-package #:manipulator) <<determine-expression-type>> <<polynomial-related-functions>> <<collect-terms>> <<expression-manipulation>>