close Warning: Can't synchronize with repository "(default)" (The repository directory has changed, you should resynchronize the repository with: trac-admin $ENV repository resync '(default)'). Look in the Trac log for more information.

source: branches/f4grobner/.junk/poly-eval.lisp@ 1060

Last change on this file since 1060 was 1060, checked in by Marek Rychlik, 9 years ago

* empty log message *

  • Property svn:mime-type set to application/x-elc
File size: 6.1 KB
Line 
1(defun alist-form (plist vars)
2 "Translates an expression PLIST, which should be a list of polynomials
3in variables VARS, to an alist representation of a polynomial.
4It returns the alist. See also PARSE-TO-ALIST."
5 (cond
6 ((endp plist) nil)
7 ((eql (first plist) '[)
8 (cons '[ (mapcar #'(lambda (x) (alist-form x vars)) (rest plist))))
9 (t
10 (assert (eql (car plist) '+))
11 (alist-form-1 (rest plist) vars))))
12
13(defun alist-form-1 (p vars
14 &aux (ht (make-hash-table
15 :test #'equal :size 16))
16 stack)
17 (dolist (term p)
18 (assert (eql (car term) '*))
19 (incf (gethash (powers (cddr term) vars) ht 0) (second term)))
20 (maphash #'(lambda (key value) (unless (zerop value)
21 (push (cons key value) stack))) ht)
22 stack)
23
24(defun powers (monom vars
25 &aux (tab (pairlis vars (make-list (length vars)
26 :initial-element 0))))
27 (dolist (e monom (mapcar #'(lambda (v) (cdr (assoc v tab))) vars))
28 (assert (equal (first e) '^))
29 (assert (integerp (third e)))
30 (assert (= (length e) 3))
31 (let ((x (assoc (second e) tab)))
32 (if (null x) (error "Variable ~a not in the list of variables."
33 (second e))
34 (incf (cdr x) (third e))))))
35
36
37
38(defun convert-number (number-or-poly n)
39 "Returns NUMBER-OR-POLY, if it is a polynomial. If it is a number,
40it converts it to the constant monomial in N variables. If the result
41is a number then convert it to a polynomial in N variables."
42 (if (numberp number-or-poly)
43 (make-poly-from-termlist (list (make-term (make-monom :dimension n) number-or-poly)))
44 number-or-poly))
45
46(defun $poly+ (ring-and-order p q n)
47 "Add two polynomials P and Q, where each polynomial is either a
48numeric constant or a polynomial in internal representation. If the
49result is a number then convert it to a polynomial in N variables."
50 (poly-add ring-and-order (convert-number p n) (convert-number q n)))
51
52(defun $poly- (ring-and-order p q n)
53 "Subtract two polynomials P and Q, where each polynomial is either a
54numeric constant or a polynomial in internal representation. If the
55result is a number then convert it to a polynomial in N variables."
56 (poly-sub ring-and-order (convert-number p n) (convert-number q n)))
57
58(defun $minus-poly (ring p n)
59 "Negation of P is a polynomial is either a numeric constant or a
60polynomial in internal representation. If the result is a number then
61convert it to a polynomial in N variables."
62 (poly-uminus ring (convert-number p n)))
63
64(defun $poly* (ring-and-order p q n)
65 "Multiply two polynomials P and Q, where each polynomial is either a
66numeric constant or a polynomial in internal representation. If the
67result is a number then convert it to a polynomial in N variables."
68 (poly-mul ring-and-order (convert-number p n) (convert-number q n)))
69
70(defun $poly/ (ring p q)
71 "Divide a polynomials P which is either a numeric constant or a
72polynomial in internal representation, by a number Q."
73 (if (numberp p)
74 (common-lisp:/ p q)
75 (scalar-times-poly ring (common-lisp:/ q) p)))
76
77(defun $poly-expt (ring-and-order p l n)
78 "Raise polynomial P, which is a polynomial in internal
79representation or a numeric constant, to power L. If P is a number,
80convert the result to a polynomial in N variables."
81 (poly-expt ring-and-order (convert-number p n) l))
82
83
84(defun variable-basis (ring n &aux (basis (make-list n)))
85 "Generate a list of polynomials X[i], i=0,1,...,N-1."
86 (dotimes (i n basis)
87 (setf (elt basis i) (make-variable ring n i))))
88
89
90(defun poly-eval-1 (expr vars &optional (ring *ring-of-integers*) (order #'lex>)
91 &aux
92 (ring-and-order (make-ring-and-order :ring ring :order order))
93 (n (length vars))
94 (basis (variable-basis ring (length vars))))
95 "Evaluate an expression EXPR as polynomial by substituting operators
96+ - * expt with corresponding polynomial operators and variables VARS
97with the corresponding polynomials in internal form. We use special
98versions of binary operators $poly+, $poly-, $minus-poly, $poly* and
99$poly-expt which work like the corresponding functions in the POLY
100package, but accept scalars as arguments as well. The result is a
101polynomial in internal form. This operation is somewhat similar to
102the function EXPAND in CAS."
103 (cond
104 ((numberp expr)
105 (cond
106 ((zerop expr) NIL)
107 (t (make-poly-from-termlist (list (make-term (make-monom :dimension n) expr))))))
108 ((symbolp expr)
109 (nth (position expr vars) basis))
110 ((consp expr)
111 (case (car expr)
112 (expt
113 (if (= (length expr) 3)
114 ($poly-expt ring-and-order
115 (poly-eval-1 (cadr expr) vars ring order)
116 (caddr expr)
117 n)
118 (error "Too many arguments to EXPT")))
119 (/
120 (if (and (= (length expr) 3)
121 (numberp (caddr expr)))
122 ($poly/ ring (cadr expr) (caddr expr))
123 (error "The second argument to / must be a number")))
124 (otherwise
125 (let ((r (mapcar
126 #'(lambda (e) (poly-eval-1 e vars ring order))
127 (cdr expr))))
128 (ecase (car expr)
129 (+ (reduce #'(lambda (p q) ($poly+ ring-and-order p q n)) r))
130 (-
131 (if (endp (cdr r))
132 ($minus-poly ring (car r) n)
133 ($poly- ring-and-order
134 (car r)
135 (reduce #'(lambda (p q) ($poly+ ring-and-order p q n)) (cdr r))
136 n)))
137 (*
138 (reduce #'(lambda (p q) ($poly* ring-and-order p q n)) r))
139 )))))))
140
141
142
143(defun poly-eval (expr vars &optional (order #'lex>) (ring *ring-of-integers*))
144 "Evaluate an expression EXPR, which should be a polynomial
145expression or a list of polynomial expressions (a list of expressions
146marked by prepending keyword :[ to it) given in Lisp prefix notation,
147in variables VARS, which should be a list of symbols. The result of
148the evaluation is a polynomial or a list of polynomials (marked by
149prepending symbol '[) in the internal alist form. This evaluator is
150used by the PARSE package to convert input from strings directly to
151internal form."
152 (cond
153 ((numberp expr)
154 (unless (zerop expr)
155 (make-poly-from-termlist
156 (list (make-term (make-monom :dimension (length vars)) expr)))))
157 ((or (symbolp expr) (not (eq (car expr) :[)))
158 (poly-eval-1 expr vars ring order))
159 (t (cons '[ (mapcar #'(lambda (p) (poly-eval-1 p vars ring order)) (rest expr))))))
160
161
Note: See TracBrowser for help on using the repository browser.