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/grobner.lisp@ 126

Last change on this file since 126 was 126, checked in by Marek Rychlik, 10 years ago

* empty log message *

File size: 12.8 KB
RevLine 
[1]1;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*-
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3;;;
[72]4;;; Copyright (C) 1999, 2002, 2009, 2015 Marek Rychlik <rychlik@u.arizona.edu>
[1]5;;;
6;;; This program is free software; you can redistribute it and/or modify
7;;; it under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 2 of the License, or
9;;; (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19;;;
20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21
22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23;;
24;; Global switches
25;;
[94]26;; Can be used in Maxima just fine, as they observe the
[95]27;; Maxima naming convention, i.e. all names visible at the
[96]28;; Maxima toplevel begin with a '$'.
[94]29;;
[1]30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31
[97]32(defvar $poly_monomial_order '$lex
[1]33 "This switch controls which monomial order is used in polynomial
34and Grobner basis calculations. If not set, LEX will be used")
35
[97]36(defvar $poly_coefficient_ring '$expression_ring
[1]37 "This switch indicates the coefficient ring of the polynomials
38that will be used in grobner calculations. If not set, Maxima's
39general expression ring will be used. This variable may be set
40to RING_OF_INTEGERS if desired.")
41
[97]42(defvar $poly_primary_elimination_order nil
[1]43 "Name of the default order for eliminated variables in elimination-based functions.
44If not set, LEX will be used.")
45
[97]46(defvar $poly_secondary_elimination_order nil
[1]47 "Name of the default order for kept variables in elimination-based functions.
48If not set, LEX will be used.")
49
[97]50(defvar $poly_elimination_order nil
[1]51 "Name of the default elimination order used in elimination calculations.
52If set, it overrides the settings in variables POLY_PRIMARY_ELIMINATION_ORDER
53and SECONDARY_ELIMINATION_ORDER. The user must ensure that this is a true
54elimination order valid for the number of eliminated variables.")
55
[97]56(defvar $poly_return_term_list nil
[1]57 "If set to T, all functions in this package will return each polynomial as a
58list of terms in the current monomial order rather than a Maxima general expression.")
59
[97]60(defvar $poly_grobner_debug nil
[1]61 "If set to TRUE, produce debugging and tracing output.")
62
[97]63(defvar $poly_grobner_algorithm '$buchberger
[1]64 "The name of the algorithm used to find grobner bases.")
65
[97]66(defvar $poly_top_reduction_only nil
[1]67 "If not FALSE, use top reduction only whenever possible.
68Top reduction means that division algorithm stops after the first reduction.")
69
70
71
72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73;;
74;; Coefficient ring operations
75;;
76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
77;;
78;; These are ALL operations that are performed on the coefficients by
79;; the package, and thus the coefficient ring can be changed by merely
80;; redefining these operations.
81;;
82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
83
84(defstruct (ring)
85 (parse #'identity :type function)
86 (unit #'identity :type function)
87 (zerop #'identity :type function)
88 (add #'identity :type function)
89 (sub #'identity :type function)
90 (uminus #'identity :type function)
91 (mul #'identity :type function)
92 (div #'identity :type function)
93 (lcm #'identity :type function)
94 (ezgcd #'identity :type function)
95 (gcd #'identity :type function))
96
97(defparameter *ring-of-integers*
98 (make-ring
99 :parse #'identity
100 :unit #'(lambda () 1)
101 :zerop #'zerop
102 :add #'+
103 :sub #'-
104 :uminus #'-
105 :mul #'*
106 :div #'/
107 :lcm #'lcm
108 :ezgcd #'(lambda (x y &aux (c (gcd x y))) (values c (/ x c) (/ y c)))
109 :gcd #'gcd)
110 "The ring of integers.")
[126]111
[125]112(defvar *maxima-ring* *ring-of-integers*
113 "The ring of coefficients, over which all polynomials are assumed to
[124]114 be defined.")
115
[1]116
117
118
119;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120;;
121;; This is how we perform operations on coefficients
122;; using Maxima functions.
123;;
124;; Functions and macros dealing with internal representation structure
125;;
126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
127
128
129;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130;;
131;; Debugging/tracing
132;;
133;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
134(defmacro debug-cgb (&rest args)
135 `(when $poly_grobner_debug (format *terminal-io* ,@args)))
136
137
138
139;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
140;;
141;; These are provided mostly for debugging purposes To enable
142;; verification of grobner bases with BUCHBERGER-CRITERION, do
143;; (pushnew :grobner-check *features*) and compile/load this file.
144;; With this feature, the calculations will slow down CONSIDERABLY.
145;;
146;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147
148(defun grobner-test (ring g f)
149 "Test whether G is a Grobner basis and F is contained in G. Return T
150upon success and NIL otherwise."
151 (debug-cgb "~&GROBNER CHECK: ")
152 (let (($poly_grobner_debug nil)
153 (stat1 (buchberger-criterion ring g))
154 (stat2
155 (every #'poly-zerop
156 (makelist (normal-form ring (copy-tree (elt f i)) g nil)
157 (i 0 (1- (length f)))))))
158 (unless stat1 (error "~&Buchberger criterion failed."))
159 (unless stat2
160 (error "~&Original polys not in ideal spanned by Grobner.")))
161 (debug-cgb "~&GROBNER CHECK END")
162 t)
[66]163
164
165;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
166;;
167;; Selection of algorithm and pair heuristic
168;;
[1]169;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
170
171(defun find-grobner-function (algorithm)
172 "Return a function which calculates Grobner basis, based on its
173names. Names currently used are either Lisp symbols, Maxima symbols or
174keywords."
175 (ecase algorithm
176 ((buchberger :buchberger $buchberger) #'buchberger)
177 ((parallel-buchberger :parallel-buchberger $parallel_buchberger) #'parallel-buchberger)
178 ((gebauer-moeller :gebauer_moeller $gebauer_moeller) #'gebauer-moeller)))
179
180(defun grobner (ring f &optional (start 0) (top-reduction-only nil))
181 ;;(setf F (sort F #'< :key #'sugar))
182 (funcall
183 (find-grobner-function $poly_grobner_algorithm)
184 ring f start top-reduction-only))
185
186(defun reduced-grobner (ring f &optional (start 0) (top-reduction-only $poly_top_reduction_only))
187 (reduction ring (grobner ring f start top-reduction-only)))
188
189(defun set-pair-heuristic (method)
190 "Sets up variables *PAIR-KEY-FUNCTION* and *PAIR-ORDER* used
191to determine the priority of critical pairs in the priority queue."
192 (ecase method
193 ((sugar :sugar $sugar)
194 (setf *pair-key-function* #'sugar-pair-key
195 *pair-order* #'sugar-order))
196; ((minimal-mock-spoly :minimal-mock-spoly $minimal_mock_spoly)
197; (setf *pair-key-function* #'mock-spoly
198; *pair-order* #'mock-spoly-order))
199 ((minimal-lcm :minimal-lcm $minimal_lcm)
200 (setf *pair-key-function* #'(lambda (p q)
201 (monom-lcm (poly-lm p) (poly-lm q)))
202 *pair-order* #'reverse-monomial-order))
203 ((minimal-total-degree :minimal-total-degree $minimal_total_degree)
204 (setf *pair-key-function* #'(lambda (p q)
205 (monom-total-degree
206 (monom-lcm (poly-lm p) (poly-lm q))))
207 *pair-order* #'<))
208 ((minimal-length :minimal-length $minimal_length)
209 (setf *pair-key-function* #'(lambda (p q)
210 (+ (poly-length p) (poly-length q)))
211 *pair-order* #'<))))
212
213
214
215
216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217;;
218;; Conversion from internal to infix form
219;;
220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
221
222(defun coerce-to-infix (poly-type object vars)
223 (case poly-type
224 (:termlist
225 `(+ ,@(mapcar #'(lambda (term) (coerce-to-infix :term term vars)) object)))
226 (:polynomial
227 (coerce-to-infix :termlist (poly-termlist object) vars))
228 (:poly-list
229 `([ ,@(mapcar #'(lambda (p) (coerce-to-infix :polynomial p vars)) object)))
230 (:term
231 `(* ,(term-coeff object)
232 ,@(mapcar #'(lambda (var power) `(expt ,var ,power))
233 vars (monom-exponents (term-monom object)))))
234 (otherwise
235 object)))
236
237
238;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
239;;
240;; Order utilities
241;;
242;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
243(defun find-order (order)
244 "This function returns the order function bases on its name."
245 (cond
246 ((null order) nil)
247 ((symbolp order)
248 (case order
249 ((lex :lex $lex) #'lex>)
250 ((grlex :grlex $grlex) #'grlex>)
251 ((grevlex :grevlex $grevlex) #'grevlex>)
[120]252 ((invlex :invlex $invlex) #'invlex>)
[1]253 ((elimination-order-1 :elimination-order-1 elimination_order_1) #'elimination-order-1)
[120]254 (otherwise
[1]255 (warn "~%Warning: Order ~A not found. Using default.~%" order))))
256 (t
257 (warn "~%Order specification ~A is not recognized. Using default.~%" order)
258 nil)))
259
260(defun find-ring (ring)
261 "This function returns the ring structure bases on input symbol."
262 (cond
263 ((null ring) nil)
264 ((symbolp ring)
265 (case ring
[121]266 ((expression-ring :expression-ring $expression_ring) *expression-ring*)
[1]267 ((ring-of-integers :ring-of-integers $ring_of_integers) *ring-of-integers*)
[121]268 (otherwise
[1]269 (warn "~%Warning: Ring ~A not found. Using default.~%" ring))))
270 (t
271 (warn "~%Ring specification ~A is not recognized. Using default.~%" ring)
272 nil)))
273
274(defmacro with-monomial-order ((order) &body body)
275 "Evaluate BODY with monomial order set to ORDER."
276 `(let ((*monomial-order* (or (find-order ,order) *monomial-order*)))
277 . ,body))
278
279(defmacro with-coefficient-ring ((ring) &body body)
280 "Evaluate BODY with coefficient ring set to RING."
281 `(let ((*maxima-ring* (or (find-ring ,ring) *maxima-ring*)))
282 . ,body))
283
284(defmacro with-elimination-orders ((primary secondary elimination-order)
285 &body body)
286 "Evaluate BODY with primary and secondary elimination orders set to PRIMARY and SECONDARY."
287 `(let ((*primary-elimination-order* (or (find-order ,primary) *primary-elimination-order*))
288 (*secondary-elimination-order* (or (find-order ,secondary) *secondary-elimination-order*))
289 (*elimination-order* (or (find-order ,elimination-order) *elimination-order*)))
290 . ,body))
291
292
293
294;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
295;;
296;; Conversion from internal form to Maxima general form
297;;
298;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
299
300(defun maxima-head ()
301 (if $poly_return_term_list
[17]302 '(mlist)
303 '(mplus)))
304
305(defun coerce-to-maxima (poly-type object vars)
[19]306 (case poly-type
[17]307 (:polynomial
[20]308 `(,(maxima-head) ,@(mapcar #'(lambda (term) (coerce-to-maxima :term term vars)) (poly-termlist object))))
[17]309 (:poly-list
310 `((mlist) ,@(mapcar #'(lambda (p) ($ratdisrep (coerce-to-maxima :polynomial p vars))) object)))
[26]311 (:term
312 `((mtimes) ,($ratdisrep (term-coeff object))
[17]313 ,@(mapcar #'(lambda (var power) `((mexpt) ,var ,power))
314 vars (monom-exponents (term-monom object)))))
[1]315 ;; Assumes that Lisp and Maxima logicals coincide
316 (:logical object)
317 (otherwise
318 object)))
319
320
321
322;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
323;;
324;; Macro facility for writing Maxima-level wrappers for
325;; functions operating on internal representation
326;;
327;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
328
329(defmacro with-parsed-polynomials (((maxima-vars &optional (maxima-new-vars nil new-vars-supplied-p))
330 &key (polynomials nil)
331 (poly-lists nil)
332 (poly-list-lists nil)
333 (value-type nil))
334 &body body
335 &aux (vars (gensym))
336 (new-vars (gensym)))
337 `(let ((,vars (coerce-maxima-list ,maxima-vars))
338 ,@(when new-vars-supplied-p
339 (list `(,new-vars (coerce-maxima-list ,maxima-new-vars)))))
340 (coerce-to-maxima
341 ,value-type
342 (with-coefficient-ring ($poly_coefficient_ring)
343 (with-monomial-order ($poly_monomial_order)
344 (with-elimination-orders ($poly_primary_elimination_order
345 $poly_secondary_elimination_order
346 $poly_elimination_order)
347 (let ,(let ((args nil))
348 (dolist (p polynomials args)
349 (setf args (cons `(,p (parse-poly ,p ,vars)) args)))
350 (dolist (p poly-lists args)
351 (setf args (cons `(,p (parse-poly-list ,p ,vars)) args)))
352 (dolist (p poly-list-lists args)
353 (setf args (cons `(,p (parse-poly-list-list ,p ,vars)) args))))
354 . ,body))))
355 ,(if new-vars-supplied-p
356 `(append ,vars ,new-vars)
357 vars))))
358
359
Note: See TracBrowser for help on using the repository browser.