In documentation for lreduce and rreduce, supply second argument as an explicit list
[maxima.git] / share / affine / polya.lisp
blob41a3a13a48a837ea7995a431ddff06fef76bf044
1 ;;; -*- Mode:Lisp; Package:CL-MAXIMA; Syntax:COMMON-LISP; Base:10 -*-;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; ;;;;;
4 ;;; Copyright (c) 1984 by William Schelter,University of Texas ;;;;;
5 ;;; All rights reserved ;;;;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 (in-package :maxima)
10 ; (:init-keywords :the-sparse-matrix :table :array-of-tables
11 ; :array-of-polynomials :type-of-entries :constants-column-number
12 ; :solution-in-macsyma-format :relations :variables :rows)
14 ; (:settable-instance-variables verify-conversion)
15 ; :gettable-instance-variables)
17 ; rows
18 ; length-of-array-of-tables
19 ; array-of-tables
20 ; type-of-polynomials
21 ; table
22 ; array-of-tables
23 ; last-column-number
24 ; number-of-independent-terms ;;never occurs
25 ; array-of-polynomials
26 ; type-of-entries
27 ; verify-conversion
28 ; constants-column-number
29 ; the-sparse-matrix
30 ; solution-in-macsyma-format
31 ; relations
32 ; variables
34 ;;The idea will be to take a list of vectors containing polynomials so
35 ;;why not an array such that the rows will represent the rows of the
36 ;;eventual sparse matrix to be created. The columns (there may be only
37 ;;one) will correspond to possibly different slots of some matrix. Thus
38 ;;if we have 20 2 by 2 matrices with polynomial entries, we shall
39 ;;consider an array 20 by 4. Or better yet why not 20 by 2 by 2. We
40 ;;wish do go through and create a table for each slot of the 2 by 2
41 ;;which lists the terms occurring somewhere in that slot. Then we will
42 ;;go through the polynomials and associate 20 sparse-matrix type rows
43 ;;whose entries will be the coefficients obtained from looking in the
44 ;;hash table.
46 ;;Alternateley it is probably better to store the polynomial vectors as
47 ;;elements of a 1 dimensional art-q array. Thus each slot would contain
48 ;;a 2 by 2 art q array its entries being the appropriate polynomial.
50 (defvar $current_variables nil)
51 (defvar $current_monomials nil)
52 (defvar $fast_dotsimp t "will use rat-ncmul")
53 (defvar $order_function '$monomial_alphalessp
54 "Order used for dot monomials. Tail-alphalessp is another reasonable value.")
55 (defvar $aaaa nil "Should contain a list of scalar coefficients $aa1 etc.")
56 (defvar $dot_simplifications nil "Macsyma list of pattern ,replacements")
58 (setq $dotdistrib t)
60 (defmacro get-rid-of-array (ar)
61 `(return-array (prog1 ,ar (setq ,ar nil))))
63 ;(defmethod (polynomial-vectors :fasd-form) ()
64 ; (let ((options-present
65 ; (loop for u in (list :the-sparse-matrix :table :array-of-tables
66 ; :array-of-polynomials :type-of-entries :constants-column-number
67 ; :solution-in-macsyma-format :relations :variables :rows)
68 ; when (catch-error (send self u) nil)
69 ; appending (list u (send self u)))))
70 ; (setq options-present (cons nil options-present))
71 ; `(instantiate-flavor 'polynomial-vectors ',options-present t)))
72 ;(defmethod (polynomial-vectors :init) (plist &aux value )
73 ; (loop for value-name in (list :the-sparse-matrix :table :array-of-tables
74 ; :array-of-polynomials :type-of-entries :constants-column-number
75 ; :solution-in-macsyma-format :relations :variables :rows)
76 ; when (setq value (get plist value-name))
77 ; do (send self :eval-inside-yourself
78 ; `(setq ,
79 ; (INTERN (string-trim ":"
80 ; (string value-name)) 'MACSYMA ) VALUE)) ))
82 (defun macsyma-display (form)
83 "Takes a macsyma form and displays it"
84 (displa `((mlabel) 1 ,form)))
86 (defun gt (form)
87 (grind-top-level form))
89 (defun list-terms (poly &aux terms)
90 (cond ((eql poly 0) nil)
91 ((atom poly) (setq terms (list poly)))
93 (setq terms
94 (case (caar poly)
95 (mplus (cdr poly))
96 (mtimes (list poly))
97 (mexpt (list poly))
98 (mnctimes (list poly))
99 (mncexpt (list poly))
100 (otherwise (error "~A is not a polynomial" poly))))))
101 terms)
102 ; (cond ((user:appears-in terms 'mplus)
103 ; (format t "~%~A was not fully expanded, so using its expansion" poly)
104 ; (list-terms ($expand poly)))
105 ; (t terms)))
106 (defmacro remove-second (a-list)
107 `(rplaca (cdr ,a-list) (car ,a-list)))
109 (defun numerical-coefficient-and-monomial (term &aux (answer 1) (monomial 1))
110 "returns two values the numerical coefficient and either 1 or
111 an atomic variable or a power eg ((mexpt simp) $x 2) or a list l
112 which whose elements would be multiplied ( by doing (cons '(mtimes simp) l) )
113 to obtain the appropriate monomial. This does work."
115 (cond ((numberp term) (setq answer term))
116 ((atom term) (setq monomial term))
118 (case (caar term)
119 (mtimes (cond (($numberp (second term)) (setq answer (second term))
120 (setq monomial (cddr term)))
121 (t (setq monomial (cdr term))))
122 (cond ((atom (car monomial))nil)
123 ((appears-in (caar monomial) 'mplus)
124 (error "Some monomial with a sum in it"))))
125 (mexpt (setq monomial term))
126 (mnctimes (setq monomial term))
127 (mncexpt (setq monomial term))
128 (otherwise (error "~A is not a term." term)))
129 (cond ((eql 1 (length monomial)) (setq monomial (car monomial))))))
130 (values answer monomial)) ;;Note this a monomial less the '(mtimes simp)!!!
132 ;;definition: A monomial is 1, or a symbol, or ((mexpt simp) var
133 ;;number) or ((mncexpt simp) var number) or ?((mnctimes simp) var number)?
134 ;;or ((mtimes simp) a1 a2 ... an) where a1, a2, ... an are in the above
135 ;;list( but not 1). Here var stands for a symbol and number stands for
136 ;;an integer bigger than 1.
138 ;;definition: A term is a number, or a monomial, or ((mtimes simp)
139 ;;number monomial)
141 ;;definition: A polynomial is either a term or ((mplus simp) t1 t2 ...
142 ;;tn) where the t1,.. tn are terms.
144 ;;definition: A premonomial is a monomial with the (mtimes simp)
145 ;;deleted.
147 ;;The keys in our hash table will be premonomials. The reason is it is
148 ;;simpler to just remove the ((mtimes simp) number at beginning of a
149 ;;list rather than keeping it. It will also make the hashing slightly
150 ;;better.
152 (defun make-monomial ( premonomial)
153 "Returns a monomial given a premonomial"
154 (cond ((atom premonomial) premonomial)
155 ((atom (car premonomial)) (cons '(mtimes simp) premonomial))
156 ; ((eq (caar premonomial) 'mexpt) premonomial)
157 ; (t (cons '(mtimes simp) premonomial))))
158 (t (case (caar premonomial)
159 (mexpt premonomial)
160 (mnctimes premonomial)
161 (mncexpt premonomial)
162 (otherwise (cons '(mtimes simp) premonomial))))))
164 (defun make-premonomial (monomial)
165 (cond ((atom monomial) monomial)
167 (delete '(mtimes simp) monomial :test #'equal))))
168 (defun macsyma-list (&rest l)
169 (cons '(mlist simp) (copy-list l)))
171 (defun show-coeff (poly )
172 (loop for u in (list-terms poly)
173 do (multiple-value-bind (coefficient guts-monomial)
174 (numerical-coefficient-and-monomial u)
175 (format t "~%~A has coefficient ~D and monomial ~A" u coefficient
176 (make-monomial guts-monomial))
177 (displa (macsyma-list u coefficient (make-monomial guts-monomial))))))
179 ;(setf (function $tee) (function convert-polynomial-to-vector))
181 (defvar *one-dimensional-array* (make-array 100 :fill-pointer 0 :adjustable t) "A temporary one dimensional array")
183 (defun convert-polynomial-to-vector (polynomial hash-table &optional last-column-number parts-of-monomial)
184 "Returns the row corresponding to the polynomial and the new last-column-number.
185 The first argument is a regular macsyma polynomial in expanded form as returned
186 by Expand(polynomial);. The second argument is the hash-table, and the last is the
187 number of entries in the hash table."
188 (let* ((terms (list-terms polynomial))
189 answer
190 ; (last-column-number (send hash-table :filled-elements))
191 (a-table hash-table)
192 col)
193 (setq answer (make-array (* 2 (length terms)) :fill-pointer 0 :adjustable t))
194 (cond ((null last-column-number)
195 (setq last-column-number
196 (hash-table-count hash-table))))
197 (cond ((null parts-of-monomial) (setq parts-of-monomial
198 'numerical-coefficient-and-monomial)))
199 (loop for u in terms
200 do (multiple-value-bind (coeff mon)
201 (funcall parts-of-monomial u)
202 (cond ((setq col (gethash mon a-table )))
203 (t (setq col (1+ last-column-number))
204 (setq last-column-number col)
205 (setf (gethash mon a-table) col)))
206 (vector-push-extend col answer)
207 (vector-push-extend coeff answer)))
209 (collect-coefficients answer)
210 (maybe-move-back-fill-pointer answer)
211 (values answer last-column-number)))
213 (defmacro reverse-two-values (form)
214 `(multiple-value-bind (.first. .second.),form
215 (values .second. .first.)))
217 (defun mac-add* (&rest l &aux tem)
218 (setq tem (apply #'add* l))
219 (cond (($zerop tem) 0)
220 (t tem)))
222 (defun collect-coefficients ( a-row &aux col sum)
223 (loop for i below (length (the cl:array a-row)) by 2
224 when (setq col (aref a-row i))
227 (setq sum (aref a-row (1+ i)))
228 (loop for ii from (+ i 2) below (length (the cl:array a-row)) by 2
229 when (equal col (aref a-row ii))
232 (setq sum (mac-add* sum (aref a-row (1+ ii))))
233 (setf (aref a-row ii) nil)
234 (setf (aref a-row (1+ i)) sum))))
236 (defun sc_and_nc_parts (monomial)
237 (reverse-two-values (extract_nc_and_sc_parts monomial)))
239 (defun $list_terms (f)
240 (macsyma-list (list-terms f)))
243 (defun get-key (table value)
244 (loop for ke being the hash-keys in table using (hash-value val)
245 when (equal val value)
246 do (return ke)))
248 ;; (defun convert-polynomial-row (row hash-table &aux terms cof col mon)
249 ;; "This should actually return something equal to the original polynomial
250 ;; which was fed into convert-polynomial-to-vector"
251 ;; (setq terms
252 ;; (loop for ii below (length (the cl:array row)) by 2
253 ;; when (setq col (aref row ii ))
254 ;; do
255 ;; (setq mon (get-key hash-table col))
256 ;; (setq cof (aref row (1+ ii )))
257 ;; collecting
258 ;; (mul* cof (make-monomial mon))))
259 ;; ; (cond ((atom mon)(list '(mtimes simp) cof mon))
260 ;; ; ((eq (car mon) 'mexpt) (list '(mtimes simp) cof mon))
261 ;; ; (t (append (list '(mtimes simp) cof) mon)))))
262 ;; (append '((mplus simp)) terms))
264 (defun convert-polynomial-row (row hash-table &aux terms cof col mon)
265 "This should actually return something equal to the original polynomial
266 which was fed into convert-polynomial-to-vector"
267 (setq terms
268 (loop for ii below (length (the cl:array row)) by 2
269 when (setq col (aref row ii ))
271 (setq mon (get-key hash-table col))
272 (setq cof (aref row (1+ ii )))
274 collecting
275 (mul* cof (make-monomial mon))))
276 (apply #'add* terms))
278 (defun make-one-dimensional (an-array)
279 (if (= (array-rank an-array) 1)
280 an-array
281 (make-array (apply #'* (array-dimensions an-array)) :adjustable t :displaced-to an-array)))
283 (defun total-dimension (an-array)
284 (apply #'* (array-dimensions an-array)))
286 (defmacro equation-length (eqn)
287 `(cond ((atom ,eqn) 1)
288 (($plusp ,eqn) (1- (length ,eqn)))
289 (t 1)))
291 (defun pv-get-rows-from-macsyma-equations
292 (self equations ; &optional variables
293 &aux tem temp-array ) ; corresponding-variables-column)
294 (check-arg equations $listp "Macsyma list")
295 (setq temp-array (make-array (length equations) :fill-pointer 0 :adjustable t))
296 (loop for u in (cdr equations)
298 (setq tem (bring-to-left-side u))
299 ;(print tem)
300 (cond ((numberp tem)
301 (cond ((zerop tem)(format t "~%Eliminate Trivial equation"))
302 (t (format t "~%Warning: Inconsistent equation ~A = 0" tem))))
303 (t (vector-push-extend tem temp-array))))
306 ( pv-get-rows-from-array-of-polynomials self temp-array)
307 (setf (pv-constants-column-number self) (gethash 1 (pv-table self) ))
308 ( pv-set-up-sparse-matrix-from-rows self ))
309 (defun pv-set-up-sparse-matrix-from-rows (self)
310 (cond ( (pv-the-sparse-matrix self) nil)
311 (t (setf (pv-the-sparse-matrix self) (make-sparse-matrix))))
312 ( sp-set-rows (pv-the-sparse-matrix self) (pv-rows self))
313 ( sp-set-type-of-entries (pv-the-sparse-matrix self)
314 (pv-type-of-entries self))
315 (cond ((pv-constants-column-number self)
316 ( sp-set-constants-column
317 (pv-the-sparse-matrix self)
318 (pv-constants-column-number self)))
319 (t (setf (sp-constants-column
320 (pv-the-sparse-matrix self)) nil))))
322 (defun pv-reduce (self)
323 ( pv-set-up-sparse-matrix-from-rows self )
324 ( sp-reduce (pv-the-sparse-matrix self))
325 (format t "~%The rank is ~D"
326 ( sp-number-of-pivots (pv-the-sparse-matrix self))))
328 (defmacro solution-corresponds-to-column (a-solution)
329 ; `(array-leader ,a-solution 1))
330 `(getf (pv-solution-plist self) ,a-solution))
332 (defvar *show-solve* t)
333 (defvar $solution_parameter '$par "The prefix for the parameters in solve-suitable-to-sublis,
334 a value of nil uses the values in table instead.")
336 (defun poly-identity (x)
337 (cond ((null x) 0)
338 (t x)))
340 (defun pv-solve-suitable-to-sublis
341 (self &aux the-solutions the-special-solution dim tem col-list no-pivot
342 answer final-answer this-row (val 0) parameter
343 special-contribution corresponding-variables-column
344 columns-used-to-pivot )
345 (cond (*show-solve*
346 (format t "~%Starting to solve. There are ~D equations with ~D unknowns occurring."
347 ( sp-number-of-rows (pv-the-sparse-matrix self))
348 (length ( sp-list-of-all-columns-occurring (pv-the-sparse-matrix self))))))
350 ( sp-solve (pv-the-sparse-matrix self) :reduce t)
351 (setf col-list ( sp-list-of-all-columns-occurring (pv-the-sparse-matrix self)))
352 (setq the-solutions ( sp-rows ( sp-solutions (pv-the-sparse-matrix self))))
353 (setq the-special-solution
354 ( sp-special-solution
355 ( sp-solutions (pv-the-sparse-matrix self))))
356 (setq dim (array-total-size the-solutions))
357 (setq no-pivot (sp-columns-with-no-pivot(pv-the-sparse-matrix self)))
358 (cond (the-special-solution
359 (setq columns-used-to-pivot
360 (sp-columns-used-to-pivot(pv-the-sparse-matrix self) ))))
361 (cond (*show-solve* (format t "~%The dimension of the solution space is ~D" dim)))
362 (setq
363 final-answer
364 (loop for i in col-list
366 (setq answer 0)
367 (setq special-contribution 0)
368 (loop for ii below (length (the cl:array the-solutions))
370 (setq this-row (aref the-solutions ii))
371 (setq corresponding-variables-column
372 (solution-corresponds-to-column this-row))
373 (setq tem (row-entry this-row i))
374 ;;;corresponding-variables-column
375 when tem
377 (cond ($solution_parameter (setq parameter (intern (format nil "~a~d" $solution_parameter ii))))
379 (error "unexpected case")
380 (setq parameter
381 (get-key (pv-table self)
382 corresponding-variables-column))))
383 (setq val (sp-mul* tem
384 parameter))
385 (setq answer (sp-add* answer val)))
386 (cond (the-special-solution
387 (setq special-contribution
388 (poly-identity (row-entry the-special-solution i)))))
389 (setq answer (sp-add* answer special-contribution))
390 collecting
391 (list '(mequal simp)
392 (get-key (pv-table self) i)
393 (new-disrep answer))))
394 (setf (pv-solution-in-macsyma-format self) (cons '(mlist) final-answer)))
397 (defun pv-get-rows-from-list-of-polynomials
398 (self mac-list &optional parts-of-monomial &aux ar)
399 (setq ar (make-array (length (cdr mac-list)) :adjustable t))
400 (fillarray ar (cdr mac-list))
401 ( pv-get-rows-from-array-of-polynomials self ar parts-of-monomial))
403 (defun $find_rank_of_list_of_polynomials (a-list &aux cols)
404 (declare (special $poly_vector))
405 ( pv-get-rows-from-list-of-polynomials $poly_vector a-list)
406 ( pv-set-up-sparse-matrix-from-rows $poly_vector )
407 (let ((sp ( pv-the-sparse-matrix $poly_vector )))
408 ( sp-reduce sp)
409 (setq cols ( sp-column-used-in-row sp))
410 (loop for i below (length (the cl:array cols))
411 when (aref cols i)
412 count i into rank
413 finally (return rank))))
415 (defun pv-get-rows-from-array-of-polynomials
416 (self an-array &optional parts-of-monomial last-column-number)
417 "Takes AN-ARRAY whose entries are polynomials or Art-q-n arrays of polynomials.
418 It uses the parts-of-monomial if supplied to get the coefficients"
419 (let* ((number-of-rows (length (the cl:array an-array)))
420 first-element a-row poly partial-row)
421 (cond ((> 0 number-of-rows )(setq first-element (aref an-array 0))))
422 (cond ((arrayp first-element)
423 (setf (pv-length-of-array-of-tables self) (total-dimension first-element))
424 (setf (pv-type-of-polynomials self) :polynomial-vectors)
425 (cond ( (pv-array-of-tables self) nil)
426 (t ( pv-set-up-hash-tables self ))))
427 (t (setf (pv-type-of-polynomials self) :polynomial)
428 (cond (( pv-table self) (clrhash (pv-table self) ))
429 (t ( pv-set-up-hash-tables self )))))
430 (setf (pv-rows self) (make-array number-of-rows :adjustable t))
432 (setf (pv-array-of-polynomials self) an-array)
433 (case
434 (pv-type-of-polynomials self)
435 (:polynomial
436 (loop for i below number-of-rows
438 (setq poly (aref an-array i))
439 (setq a-row (convert-polynomial-to-vector
440 poly (pv-table self) nil parts-of-monomial))
441 (setf (aref (pv-rows self) i) a-row)
443 (cond ((pv-verify-conversion self)
444 (check-conversion poly a-row (pv-table self))))))
445 (:polynomial-vectors
446 (let (poly-vector)
447 (loop for i below number-of-rows
449 (setq poly-vector (make-one-dimensional
450 (aref (pv-array-of-polynomials self) i)))
451 (setf (aref (pv-array-of-polynomials self) i) poly-vector)
452 (setq a-row (make-array (length poly-vector) :fill-pointer 0 :adjustable t))
453 (setf (aref (pv-rows self) i) a-row)
454 (loop for ii below (array-total-size poly-vector)
456 (setq poly (aref poly-vector ii))
457 (multiple-value (partial-row last-column-number )
458 (convert-polynomial-to-vector
459 poly
460 (aref (pv-array-of-tables self) i)
461 (pv-last-column-number self) parts-of-monomial))
462 (setf (pv-last-column-number self) last-column-number)
463 (cond ((pv-verify-conversion self)
464 (check-conversion poly partial-row
465 (aref (pv-array-of-tables self) i))))
466 (loop for k below (length (the cl:array partial-row))
467 do (vector-push-extend (aref partial-row k) a-row))
468 ;;; (get-rid-of-array partial-row)
469 ))))))
470 ( pv-check-type-of-entries self ))
472 (defun check-conversion (polynomial row table &aux poly)
473 (cond ((equal (setq poly (convert-polynomial-row row table)) polynomial)
474 (format t "~%Checking polynomial ~A and table ~A. Conversion OK." row table))
475 (t (format t
476 "~%The converted row ~A and the polynomial ~A with translation table
477 ~A do not agree. They differ by " row polynomial table)
478 (displa (mul* poly (add* -1 polynomial))))))
480 (defun pv-check-type-of-entries (self &aux a-row)
481 (setf (pv-type-of-entries self) (or modulus :rational))
482 (catch 'done
483 (loop for ii below (length (the cl:array (pv-rows self)))
485 (setq a-row (aref (pv-rows self) ii))
486 (loop for i below (length (the cl:array a-row)) by 2
487 when (and (aref a-row i) (not (numberp (aref a-row (1+ i)))))
488 do (setf (pv-type-of-entries self) ':any-macsyma)
489 (throw 'done 'done))))
490 (format t "~%Using entry type ~A." (pv-type-of-entries self)))
492 (defun pv-set-up-hash-tables (self)
493 (case (pv-type-of-polynomials self)
494 (:polynomial (setf (pv-table self) (make-hash-table :test 'equal)))
495 (:polynomial-vectors
496 (setf (pv-last-column-number self) 0)
497 (setf (pv-array-of-tables self)
498 (make-array (pv-length-of-array-of-tables self) :fill-pointer 0 :adjustable t))
499 (loop for i below (pv-length-of-array-of-tables self)
501 (vector-push (make-hash-table :test 'equal) (pv-array-of-tables self))))))
504 (defun $my_sum (quote-form quote-index start &optional end &aux answer)
505 (setq quote-form (subst 'ind quote-index quote-form))
506 (setq start (meval start))
507 (setq end (meval end))
508 (setq answer
509 (cond (end
510 (loop for ind from start to end
511 collecting
512 (meval quote-form)))
514 (loop for ind in (cdr start)
515 collecting
516 (meval quote-form)))))
517 (setq answer (meval* (cons '(mplus) answer)))
518 answer)
520 (defun $list_dot (l ll)
521 (apply #'add* (loop for u in (cdr l) for v in (cdr ll)
522 collecting (mul* u v))))
524 (defun permutations (a-list &optional (size (length a-list)) &aux answer )
525 (setq answer (loop for u in a-list collecting (list u)))
526 (loop for i below (1- size)
528 (setq answer
529 (loop for v in a-list
530 appending
531 (loop for perm in answer
532 when (not (member v perm :test #'equal))
533 collecting (cons v perm)))))
535 answer)
537 (defun sign-of-permutation (perm-of-first-n-non-negative-integers)
538 "Will return the proper sign of a permutation of the first n non-negative integers"
539 (nsign-of-permutation (copy-list perm-of-first-n-non-negative-integers)))
541 (defun nsign-of-permutation (perm &aux tem)
542 (let ((sub1-leng (1- (length perm))))
543 (cond ((zerop sub1-leng) 1)
544 ((eq (setq tem (car (last perm))) sub1-leng)
545 (nsign-of-permutation (nbutlast perm)))
546 (t (nsubst tem sub1-leng perm)
547 (- (nsign-of-permutation (nbutlast perm)))))))
549 (defun $make_art_q (&rest indices)
550 (make-array indices :adjustable t))
552 (defun $first_variable (monomial )
553 (cond ((numberp monomial) nil)
554 ((atom monomial) monomial)
555 (t (loop for u in monomial do (print u)
556 (cond ((numberp u) nil)
557 ((atom u) (return u))
558 ((member u '((mtimes simp) (mtimes)
559 (mexpt simp) (mncexpt simp) (mncexpt)
560 (mnctimes simp)(mnctimes)) :test #'equal) nil)
561 ((member (car u)'((mtimes simp) (mtimes)
562 (mnctimes simp)(mnctimes)) :test #'equal)
563 (return ($first_variable (cdr u))))
564 (t (return (second u))))))))
567 (defun m. (&rest l)
568 (simplifya (cons '(mnctimes) (copy-list l)) nil))
571 (defun $convert_right_to_left (a b)
572 (let* ((f ($expand (add* (m. a '$x) (m. b '$y))))
573 (terms (list-terms f)) x-terms y-terms)
574 (loop for u in terms do
575 (format t "~%For term ~A" u)
576 (cond ((equal ($first_variable u) '$x) (setq x-terms (cons u x-terms)))
577 ((equal ($first_variable u) '$y) (setq y-terms (cons u y-terms)))
578 (t (error "~A has first variable not x or y" u))))
580 (macsyma-list (apply 'add* x-terms) (apply 'add* y-terms))))
582 (defun $split_into_x_and_y (f)
583 (let ((terms (list-terms f)) x-terms y-terms)
584 (loop for u in terms do
585 (format t "~%For term ~A" u)
586 (cond ((equal ($first_variable u) '$x) (setq x-terms (cons u x-terms)))
587 ((equal ($first_variable u) '$y) (setq y-terms (cons u y-terms)))
588 (t (error "~A has first variable not x or y" u))))
590 (macsyma-list (apply 'add* x-terms) (apply 'add* y-terms))))
592 (defun $matrix_entry(x i j) (nth i (nth j x)))
594 (defun initial-equal (list-a list-b)
595 (not (loop for u in list-a for v in list-b
596 when (not (eql u v))
597 do (return t))))
599 (defun initial-sublist (lista biglist)
600 (cond ((< (length biglist) (length lista)) nil)
601 (t (initial-equal lista biglist))))
604 ;;faster version
605 (defun $replace_the_pattern (adp pattern replacement &aux tem)
606 "replaces the pattern in ADP (a dot product) by replacement. When
607 inserted in the simplifier simpmnct it does the replacement whenever
608 called."
609 (cond ((atom adp) adp)
610 ((equal (caar adp) 'mnctimes)
611 (cond ((setq tem (ordered-sublist (cdr pattern ) (cdr adp)))
612 (ncmul* (ncmuln (car tem) t ) replacement (ncmuln (cadr tem)t)))
613 (t adp)))
614 (t adp)))
615 (defvar $free_dot t
617 "If nil the simplifier will use $dot_simplifications to reduce
618 dot_products, much the same as can be obtained by doing $dotsimp")
620 (defun dotsimp-one-term (monom coeff ignor) ignor
621 (mul* coeff ($expand ($dot_simp_monomial monom))))
623 (defun dotsimp-atom (expr)
624 (loop for u in (cdr $dot_simplifications)
625 for i from 1
626 when (and (oddp i)(eq u expr))
627 do (return (nth (1+ i) $dot_simplifications))
628 finally (return expr)))
629 (defvar *troublesome-variables* nil)
630 (defun check-rat-order (expr &optional (variables *troublesome-variables*)
631 &aux maybe-out-of-order nc-product-appeared)
632 (cond ((and (consp expr)($ratp expr))
633 (loop for v in (third (car expr))
634 when (not (fast-scalarp v))
635 do (setq nc-product-appeared t)
636 when (and (member v variables :test #'eq) nc-product-appeared)
637 do (setq maybe-out-of-order t))))
638 (cond (maybe-out-of-order
639 (setq nc-product-appeared nil)
640 (setq maybe-out-of-order nil)
641 (loop for v in (third (car expr))
642 for w in (fourth (car expr))
643 when (and (not (atom v))(eq (caar v) 'mnctimes))
644 do (setq nc-product-appeared t)
645 when (and (member v variables :test #'eq) nc-product-appeared
646 (appears-in (cdr expr) w))
648 (setq maybe-out-of-order t)))
649 (t nil))
650 (cond (maybe-out-of-order
651 (setq nc-product-appeared nil)
652 (cond ((loop for v in (third (car expr))
653 for w in (fourth (car expr))
654 when (and (not (atom v)) (eq (caar v) 'mnctimes)
655 (appears-in (cdr expr) w))
656 do (setq nc-product-appeared t)
657 when (and (member v variables :test #'eq) nc-product-appeared
658 (appears-in (cdr expr) w))
659 do (return t))
660 (format t "~%~%~%*************Changing rat order")
661 (beep)(break 'change)
662 (setq expr ($nc_rat expr))))))
663 expr)
664 (defun get-varlist (expr)
665 (cond (($ratp expr)(third (car expr)))
666 (t nil)))
667 ;(defun minimize-varlist-and-genvar (expr)
668 ; (cond (($ratp expr)
669 ; (let ((var-list (third (car expr)))
670 ; (gen-var (fourth (car expr))))
672 ; (loop for v in var-list
673 ; for w in gen-var
674 ; when (user:appears-in (cdr expr) w)
675 ; collecting v into new-varlist
676 ; and
677 ; collecting w into new-genvar
678 ; finally (setf (third (car expr)) new-varlist)
679 ; (setf (fourth (car expr)) new-genvar)))))
680 ; expr)
681 (defmacro check-nc-rat-order (expr)
682 ` (progn (format t "~%checking order for ~A" ',expr)
683 (setq ,expr (check-rat-order ,expr))))
684 (defun varlist (expr)
685 (third (car expr)))
686 (defun genvar (expr)
687 (fourth (car expr)))
688 (defmacro show-varlist (expr)
689 `(progn (format t "~%The varlist for ~A is"',expr)
690 (gt (varlist ,expr))))
693 (defvar $radical nil)
694 (defvar $radical_nilpotent_of_order 0)
695 (defun nil-radicalp (monom )
696 "gives nil if monom not in radical otherwise gives the power it is in"
697 (cond ((atom monom) (setq monom (list nil monom))))
698 (cond ($radical
699 (let ((answer 0))
700 (loop for v in (cdr $radical)
702 (loop for w in (cdr monom)
703 when (eq w v) do (setq answer (1+ answer))))
704 (cond ((zerop answer) nil)
705 (t answer))))))
706 (defun in-nth-power-radical (monom n &aux tem)
707 (cond ((setq tem (nil-radicalp monom))(> tem (1- n)))))
712 ;;;newest version with saving possible reset inside
713 (defun dot-show (nc-list)
714 (cond ((atom nc-list) (princ nc-list))
715 (t(format t "~A" (string-trim "$" (string (second nc-list))))
716 (loop for v in (cddr nc-list) do
717 (format t ".~A" (string-trim "$" (string v)))))))
719 (defun new-rat-dotsimp (expr &aux (answer 0) repl the-num the-denom the-rest tem)
720 (format t "~%Beginnning to new-rat-dotsimp ")
721 (cond (($must_replacep expr)
722 (loop while(not ($zerop expr))
724 (show answer)
725 (setq tem nil)
726 (cond (($must_replacep expr))
727 (t (return (header-poly (n+ answer expr)))))
728 (setq-num-den the-num the-denom expr)
729 (show the-num)
730 ; (cond ((affine-polynomialp expr) (setq the-num expr the-denom 1))
731 ; ((rational-functionp expr) (setq the-num (num expr) the-denom (denom expr)))
732 ; (t (fsignal "expr is supposed to be poly or rational-functionp")))
733 ; (cond ((numberp the-num)(setq answer (n+ answer expr))
734 (cond ((poly-scalarp the-num)(setq answer (n+ answer expr))
735 (return (header-poly answer))))
736 (setq tem (get (car the-num) 'disrep))
737 when
738 (contains-a-zero-replacement tem)
740 (format t "~%Simplifying the worst monomial: ")(dot-show tem)
741 (cond ((setq expr (fifth the-num)))
742 (t (setq expr 0)))
743 else
744 when ($must_replacep tem) ;; (setq tem (get (car the-num) 'disrep)))
746 (format t "~%Simplifying the worst monomial: ")(dot-show tem)
747 (setq repl (n* (third the-num) ($dot_simp_monomial tem)))
748 (cond ((setq the-rest (fifth the-num))
749 (show the-rest repl)
750 (setq expr (n+ the-rest repl))
751 (show expr)
752 (setq expr (nred expr the-denom)))
753 (t (setq expr (nred repl the-denom))))
754 else
756 (format t "~%Simplifying the worst monomial: ")(dot-show tem)
757 (format t "adding it to answer")
758 (cond ((fifth the-num)(setq expr (nred (fifth the-num) the-denom))) ;cons?
759 (t (setq expr 0)))
760 (setq answer (n+ answer (nred (subseq the-num 0 3) the-denom)))
762 (setq repl nil)
763 (setq tem nil the-num nil the-denom nil )
764 finally (return (header-poly answer))))
765 (t (header-poly expr))))
767 (defun rat-dotsimp (expr &aux (answer 0) repl monom term cof tem simped-monom )
768 (format t "~%Beginning to rat-dotsimp..")
769 (setq expr (minimize-varlist expr))
770 ; (setq upper-bound-for-gen-var (expt (length (cdr $current_variables))
771 ; ($nc_degree expr)))
772 ; (cond (*genvar* nil)
773 ; (t (setq *genvar* (copy-list genvar))))
774 ; (setq the-dif (max 0 (- (length *genvar*) upper-bound-for-gen-var (length (varlist expr))))
775 ; (setq gen-vars (nthcdr the-dif *genvar*))
776 ; (let ((genvar gen-vars))
777 ; (displa expr)
778 (loop while (and (not ($zerop expr))($must_replacep expr))
780 (multiple-value (monom cof) (find-worst-nc-monomial expr))
781 ; (check-nc-rat-order expr)))
782 (cond (($must_replacep monom)
783 (setq expr (vsub* expr (vmul* cof monom)))
784 ; (check-nc-rat-order expr)
785 (setq simped-monom ($dot_simp_monomial monom))
786 (setq repl (vmul* cof simped-monom))
787 ; (check-nc-rat-order expr)
788 ; (check-nc-rat-order repl)
789 (cond (($must_replacep repl)
790 (setq tem (vadd* repl expr))
791 (setq expr tem))
792 (t (setq answer (vadd* repl answer)))))
793 (t (setq expr (vsub* expr (setq term (vmul* cof monom))))
794 (setq answer (vadd* term answer))))
795 finally
796 ; (setq *genvar* (copy-list genvar))
797 (return (minimize-varlist (vadd* expr answer)))))
801 (defun $dotsimp (expr &aux (answer 0) term cof varlist monom repl (prev-monom 'zzzzz))
802 (cond ((and $fast_dotsimp (not(or (mbagp expr) ($ratp expr))))
803 (cond ($new_fast_dotsimp (setq expr ($new_rat expr)))
804 (t (setq expr ($vrat expr))))))
805 (cond ((not (or (atom expr)$fast_dotsimp ($ratp expr)))
806 (setq expr ($multthru ($ratsimp ($expand expr))))))
807 (cond
808 ((atom expr)(setq answer (dotsimp-atom expr)))
809 (($ratp expr)
810 (cond ($new_fast_dotsimp (setq answer (new-rat-dotsimp (cdr expr))))
811 (t (setq answer (rat-dotsimp expr)))))
812 ((mbagp expr)(setq answer (cons (car expr) (mapcar #'$dotsimp (cdr expr)))))
813 ((member (caar expr) '(mtimes mnctimes) :test #'equal)
814 (setq answer(apply 'dotsimp-one-term
815 (multiple-value-list (find-worst-nc-monomial expr))))
816 (cond (($must_replacep answer)
817 (setq answer ($dotsimp answer)))
818 (t answer)))
819 ((equal (caar expr) 'mplus)
820 (loop while (not (and (numberp expr) (zerop expr)))
821 count t into the-count
823 (cond ((not(atom expr))
824 (show (length expr))))
825 (multiple-value (monom cof term)(find-worst-nc-monomial expr))
826 (cond ((not (funcall $order_function monom prev-monom))
827 (show prev-monom monom)
828 (format t "****** out of order ****")
829 (beep)))
830 (setq prev-monom monom)
831 (cond (($must_replacep monom)
832 ;;the following expand may be unnecessary with dotdistrib at true.
834 (setq repl ($multthru (mul* cof ($expand ($dot_simp_monomial monom)))))
835 (cond ((loop for v in *troublesome-variables*
836 when
837 (appears-in repl v )
838 do (return t))
839 (format t "~%Ratsimping repl")
840 (setq repl ($multthru ($ratsimp repl)))))
841 (setq expr (sub* expr term ))
842 (setq expr (add* repl expr)))
844 (cond ((fast-scalarp term)(setq expr ($multthru ($ratsimp expr)))))
845 (setq expr (sub* expr term))(setq answer (add* answer term))))
846 finally (show the-count))))
847 answer)
851 ;(defun $tes (expr &aux tem1 tem2 tem3)
852 ; (let (( $free_dot t))
853 ; (setq tem1 ($dotsimp expr))
854 ; (setq $free_dot nil)
855 ; (setq tem3 expr)
856 ; (setq tem2 nil)
857 ; (setq tem2 (loop until (equal tem2 tem3)do
858 ; (setq tem2 tem3)
859 ; (displa tem2)
860 ; (setq tem3 (meval* ($expand (meval* tem3)))) ;(displa tem3)
861 ; finally (return tem3)))
862 ; ($ratsimp (sub* tem1 tem2))))
864 (defun remove_nth (n a-list)
865 (cond ((zerop n)(rplaca a-list (cadr a-list))(rplacd a-list (cddr a-list)) a-list)
866 ((< n (length a-list))
867 (rplacd (nthcdr (1- n) a-list) (nthcdr (1+ n) a-list))
868 a-list)
869 (t a-list)))
871 (defun $simp_ncmuln (a-list flag)
872 (cond ((and $free_dot $dot_simplifications)
873 ($dotsimp (ncmuln a-list flag) ))
874 (t (ncmuln a-list flag))))
875 (defun $simp_ncmul (&rest a-list)
876 ($simp_ncmuln (copy-list a-list) nil))
878 ;(defun rat-ncmul (&rest a-list)
879 ; (cond ((and $free_dot $dot_simplifications)
880 ; ($dotsimp ($nc_rat (ncmuln a-list nil) )))
881 ; (t ($nc_rat (ncmuln (copy-list a-list) nil)))))
883 (defun $dncmul(f g)
884 (cond (($plusp f)
885 (loop for v in (cdr f)
886 collecting ($dncmul v g) into vtemp
887 finally (return (apply 'add vtemp))))
889 (t (cond (($plusp g)
890 (loop for u in (cdr g)
891 collecting (ncmul f u) into tem
892 finally (return (apply 'add tem))))
893 (t (ncmul f g))))))
895 (defun dotsimp2 (expression )
896 (cond ((atom expression) nil)
897 ((equal (caar expression) 'mnctimes)(setq expression ($dot_simp_monomial expression)))
898 (t (dotsimp1 expression)))
899 expression)
901 (defun dotsimp1 (expression )
902 (cond ((atom expression) expression)
903 (t (rplaca expression ($dot_simp_monomial (car expression)))
904 (dotsimp1 (car expression))
905 (dotsimp1 (cdr expression)))))
907 (defvar *nonsense* (list 'nonsense))
909 (defun $dot_simp_monomial (monom &aux answer tem (init-monom monom))
910 (cond ((atom monom)
911 (dotsimp-atom monom))
912 ((atom (car monom))
913 monom)
914 ((equal (caar monom) 'mnctimes)
915 (cond ($dot_simplifications
916 (setq answer
917 (catch 'found-replace
918 (let (pattern replacement tema)
919 (loop while monom
921 (setq tem (cdr $dot_simplifications))
922 (setq monom (cdr monom))
923 (loop while tem
924 when (and $new_fast_dotsimp
925 (or (eql 0 (second tem))
926 (eq (rzero) (cdr (second tem)))))
927 ; ($zerop (second tem)))
928 do (setq tem (cddr tem))
929 else
931 (cond ((atom (setq pattern (car tem)))
932 (cond ((member pattern monom :test #'equal)
933 ;;we have to handle
934 ;;the case of an atomic pattern by making
935 ;;it a standard list '(nonsense)
936 (setq pattern (list pattern)))
937 (t (setq pattern *nonsense*))))
938 (t (setq pattern (cdr pattern))))
939 (setq tem (cdr tem))
940 (setq replacement (car tem) tem (cdr tem))
942 when
943 (initial-sublist pattern monom)
945 (setq tema (subseq (cdr init-monom) 0 (- (length init-monom) (length monom) 1)))
946 (cond ($new_fast_dotsimp
947 (setq answer
948 (new-rat-ncmul1 (ncmuln tema t)
949 replacement
950 (ncmuln (nthcdr (length pattern) monom) t))))
952 (setq answer
953 (rat-ncmul (ncmuln tema t)
954 replacement
955 (ncmuln (nthcdr (length pattern) monom) t)))))
956 (throw 'found-replace answer))))))
957 (if answer answer init-monom))
958 (t init-monom)))
959 (t monom)))
961 (defmacro $declare_order_weights (&rest l)
962 (loop for i below (length l) by 2
964 (putprop (nth i l) (nth (1+ i) l) :order-weight)))
966 (defmacro $declare_weights (&rest l)
967 (loop for i below (length l) by 2
969 (putprop (nth i l) (nth (1+ i) l) :weight)))
971 (defun $dot_productp (x)
972 (cond ((atom x) nil)
973 ((atom (car x)) nil)
974 ((equal (caar x) 'mnctimes))))
976 ;could add to end of simpnct to change the simplifier.
977 ;;;The next part uses the $dot_simplifications to change the result, by doing replacement
978 ;;;For example Dot_simplifications:[y.x.x,-x.x.y,w.v,v.w] will do y.x.x-->-x.x.y and w.v-->v.w
979 ;;;Be careful that dot simplifications in effect will affect the attempt to define
980 ;;;new dot_simplifications. It might be better to set it to false first and then redefine it.
982 ; (cond (dot-simps (setq dot-simps (cdr dot-simps))
983 ; (loop while dot-simps
984 ; do
985 ; (setq answer ($replace_the_pattern answer (car dot-simps)
986 ; (second dot-simps)))
987 ; (setq dot-simps (cddr dot-simps))
988 ; finally (return answer)))
989 ; (t answer))))
990 (defun $dot (l)
991 (apply 'm. l))
992 (defun $my_coeff (f x)
993 "like $coeff except it always works on general rep, and if x is 1 it picks the scalar part"
994 (cond (($ratp f)(setq f ($ratsimp f))))
995 (cond ((atom f)(cond ((equal f x) 1)
996 (t 0)))
997 ((equal f x) 1)
998 ((eq (caar f) 'mtimes)(cond ((member x f :test #'equal)
999 (delete x (copy-list f) :test #'equal))
1000 ((and (equal x 1) ($scalarp f)) f)
1001 (t 0)))
1002 ((member (caar f) '(mplus mlist mequal) :test #'eq)
1003 (simplifya (cons (list (caar f))
1004 (mapcar #'(lambda (y)
1005 ( $my_coeff y x)) (cdr f))) nil))))
1007 (defun $ncoeff (f x &optional (exponent 1))
1008 (cond ((eql x 1) ($my_coeff f x))
1009 ((equal exponent 1)($coeff f x))
1010 (t ($coeff f x exponent))))
1013 ;(defun $extract_linear_equations (equations independent-monomials &aux ($expop 100)
1014 ; answer tem ttemp)
1016 ; "Equations is a list of equations or expressions. Matrix
1017 ; equations could have been treated by subtracting the right side from
1018 ; the left side and then adding the list of entries to those in
1019 ; equations."
1021 ; (check-arg equations $listp "A Macsyma List")
1022 ; (check-arg independent-monomials $listp "A Macsyma List")
1023 ; (setq answer (loop for u in (cdr independent-monomials)
1024 ; appending
1025 ; (loop for eqn in (cdr equations)
1026 ; when (atom eqn)
1027 ; collecting ($nc_coeff eqn u )
1028 ; when (appears-in eqn '$matrix)
1029 ; appending
1030 ; (cond ((eq (caar eqn) 'mequal)
1031 ; (setq tem (sub (second eqn) (third eqn))))
1032 ; (t (setq tem eqn)))
1033 ; (loop for row in (cdr tem)
1034 ; appending
1035 ; (loop for element in (cdr row)
1036 ; when (not ($zerop (setq ttemp ($nc_coeff element u))))
1037 ; collecting ttemp))
1038 ; else
1039 ; collecting ($nc_coeff eqn u ))))
1040 ; (cons '(mlist simp) (union answer)))
1043 (defun $matrix_equationp (expr)
1044 (or ($matrixp expr) (and (null (atom expr))(eq (caar expr) 'mequal)
1045 (null (atom (second expr)))($matrixp (second expr)))))
1048 (defvar $last_monomials '((mlist)))
1050 (defun $extract_linear_equations (equations &optional (independent-monomials
1051 ($list_nc_monomials equations)))
1052 (check-arg equations $listp "A Macsyma List")
1053 (loop for v in (cdr equations)
1054 do (assert (or (atom v) (not (equal(caar v) 'mequal)))))
1055 (cons '(mlist) (mapcar 'new-disrep
1056 (extract-linear-equations (st-rat equations)
1057 (st-rat independent-monomials)))))
1059 ;(defun $extract_linear_equations (equations &optional (independent-monomials ($list_nc_monomials equations))&aux ($expop 100)
1060 ; answer tem ttemp)
1062 ; "Equations is a list of equations or expressions. Matrix
1063 ; equations could have been treated by subtracting the right side from
1064 ; the left side and then adding the list of entries to those in
1065 ; equations."
1067 ; (check-arg equations $listp "A Macsyma List")
1068 ; (setq $last_monomials independent-monomials)
1069 ; (check-arg independent-monomials $listp "A Macsyma List")
1070 ; (setq answer (loop for u in (cdr independent-monomials)
1071 ; appending
1072 ; (loop for eqn in (cdr equations)
1073 ; when (atom eqn)
1074 ; collecting ($nc_coeff eqn u )
1075 ; when ($matrix_equationp eqn)
1076 ; appending
1077 ; (progn
1078 ; (cond ((eq (caar eqn) 'mequal)
1079 ; (setq tem (sub (second eqn) (third eqn))))
1080 ; (t (setq tem eqn)))
1081 ; (loop for row in (cdr tem)
1082 ; appending
1083 ; (loop for element in (cdr row)
1084 ; when (not ($zerop (setq ttemp ($nc_coeff element u))))
1085 ; collecting ttemp)))
1086 ; else
1087 ; collecting ($nc_coeff eqn u ))))
1088 ; (cons '(mlist simp) (zl-UNION answer)))
1091 (defun extract-linear-equations (list-eqns &optional tem all-ind-mons)
1092 (loop for v in list-eqns
1093 with varl with ind-mons = all-ind-mons
1094 do(cond ((affine-polynomialp v) nil)
1095 ((rational-functionp v)
1096 (setq v (function-numerator v)))
1097 (t (fsignal
1098 "list-eqns should be a list of polynomials or rational functions")))
1099 (cond ((null all-ind-mons)
1100 (setq varl (list-variables list-eqns))
1101 (setq ind-mons (loop for vv in varl with mon = (list nil 1 1)
1102 do (setf (car mon) vv)
1103 when (not (poly-scalarp mon))
1104 collecting vv))))
1106 appending
1107 (loop for va in ind-mons
1108 when (not (pzerop (setq tem (pcoeff v (list va 1 1)))))
1109 collecting tem)))
1112 (defun member-even (item a-list &aux lis answer)
1113 (cond ((evenp (length a-list)) (setq lis a-list))
1114 (t (setq lis (butlast a-list)) (cond ((equal (car (last a-list)) item)
1115 (setq answer item)))))
1116 (cond ((null answer)
1117 (loop while lis
1119 (cond ((equal item (car lis)) (return item)))
1120 (setq lis (cddr lis))))
1121 (t answer)))
1123 (defun initial-segment-is-replaced (a-list)
1124 (cond ((atom a-list) (member-even a-list (cdr $dot_simplifications)))
1126 (loop for i from 1 to (length a-list)
1128 (cond ((member-even (subseq a-list 0 i) (cdr $dot_simplifications)) (return t)))))))
1130 ;(defun $mono (a-list n &optional $sort &aux answer tem ans1 sorted-cdr-list)
1131 ; "Returns the dot-monomials which will not be replaced by $dot_simplifications
1132 ; They are tail sorted if the optional third argument is given"
1133 ; (check-arg a-list $listp "a Macsyma list")
1134 ; (cond ((eql n 0) (cons '(mlist simp) '(1)))
1135 ; ((eql n 1) (setq answer (copy-list a-list))
1136 ; (loop for v in (cdr answer)
1137 ; when (member-even v $dot_simplifications)
1138 ; do (setq answer (delete v answer)))
1139 ; answer)
1140 ; (t
1141 ; (setq sorted-cdr-list (sort (cdr a-list) '(lambda (x y) (alphalessp y x))))
1142 ; (setq answer (loop for u in sorted-cdr-list collecting (cons '(mnctimes simp) (list u))))
1143 ; (loop for i from 1 below n
1144 ; do
1145 ; (loop for u in sorted-cdr-list
1146 ; do
1147 ; (loop for v in answer
1148 ; do
1149 ; (setq tem (cons u (cdr v)))
1150 ; (setq tem (cons '(mnctimes simp) tem))
1151 ; (cond ((initial-segment-is-replaced tem) nil)
1152 ; (t (setq answer1 (cons tem answer1 ))))))
1153 ; (setq answer answer1)
1154 ; (setq answer1 nil))
1155 ; (cond ($sort (setq answer (sort answer 'tail-alphalessp))))
1156 ; (cons '(mlist simp) answer)) ))
1157 ;;a*x.y^^2.z*b*c we want to extract x.y^^2.z
1158 (defun $extract_nc_part(monomial &aux sc-part nc-part)
1159 "Returns first value nc-part of monomial and second value the sc-part if
1160 that can be obtained without consing, nil otherwise. It uses the scalar property
1161 to check if a single atom is scalar or not, with things like ((mexpt simp) z 2) always
1162 assumed scalar. If there are two non-scalars * together it only takes the first one.
1163 If there are two ((mnctimes ..) ) It only takes the first one. "
1164 ;(setq monomial (simplifya monomial nil))
1165 (cond
1166 ((atom monomial) (cond (($scalarp monomial) (setq nc-part 1 sc-part monomial))
1167 (t (setq nc-part monomial) (setq sc-part 1))))
1168 (t (case (caar monomial)
1169 (mtimes
1170 (loop for u in (cdr monomial)
1172 (cond
1173 ((and (not (atom u)) (eq (caar u) 'mnctimes))
1174 (setq nc-part u)
1175 (cond ((eql (length monomial) 3)
1176 (cond ((eq (second monomial) u)
1177 (setq sc-part (third monomial)))
1178 (t (setq sc-part
1179 (second monomial))))))
1180 (return 'done))))
1181 (cond ((null nc-part)
1182 (loop for u in (cdr monomial)
1183 when (and (atom u) (not ($scalarp u)))
1184 do (setq nc-part u )
1185 (cond ((eql (length monomial) 3)
1186 (cond ((eq (second monomial) u)
1187 (setq sc-part (third monomial)))
1188 (t (setq sc-part
1189 (second monomial))))))
1190 (return 'done))))
1191 (cond ((null nc-part) (setq nc-part 1 sc-part monomial))))
1192 (mnctimes (setq nc-part monomial sc-part 1))
1193 (mexpt (setq nc-part 1 sc-part monomial)) ;
1194 (otherwise (error "~A is not a product" monomial)))))
1195 (values nc-part sc-part))
1197 (defun extract_nc_and_sc_parts (monomial )
1198 (multiple-value-bind (nc-part sc-part) ($extract_nc_part monomial)
1199 (cond ((null sc-part) (setq sc-part (loop for u in monomial
1200 when (not(eq u nc-part))
1201 collecting u))
1202 (cond ((eql (length sc-part) 2) (setq sc-part (cadr sc-part))))))
1205 (values nc-part sc-part)))
1206 (defun $extract_nc_and_sc_parts (monomial )
1207 (multiple-value-bind (nc-part sc-part) (extract_nc_and_sc_parts monomial)
1209 (cons '(mlist simp) (list nc-part sc-part))))
1211 ;;fast_linsolve should be like linsolve but should convert the system
1212 ;;to a sparse matrix and then solve it. It should return the answer as a list
1213 ;;of solutions suitable for sublis if a certain flag is on. Otherwise
1214 ;;it would leave them as the sparse-matrix.
1216 ;;Polynomial_linsolve should extract the equations from some equations using
1217 ;;certain independent monomials occurring. It should then solve the system,
1218 ;;and if a flag is on return the list of solutions suitable for sublis.
1219 ;;a slow version could be:
1220 (defvar $fast_solve t "Generally used to decide whether to call $linsolve or $fast_linsolve.
1221 The latter works only for number coefficients, while the former works using rattimes, etc.")
1223 (defun $setfy (a-list)
1224 (loop for v in a-list
1225 when (not (member v tem :test #'equal))
1226 collecting v into tem
1227 finally (return tem)))
1229 (defun $list_nc_monomials (expr &aux answer )
1230 (cond ((atom expr) '((mlist simp)))
1231 ((eq (caar expr) 'mnctimes)`((mlist simp) ,expr))
1232 ((member (caar expr) '(mlist mequal $matrix) :test #'eq)
1233 (loop for u in (cdr expr)
1234 appending (cdr ($list_nc_monomials u)) into a-list
1235 finally (return (cons '(mlist simp) ($setfy a-list)))))
1236 (t (setq expr ($expand expr))
1237 (cond ((eq (caar expr) 'mplus)
1238 (loop for u in (cdr expr)
1239 when (not (member (setq answer (extract_nc_and_sc_parts u))
1240 a-list :test #'equal))
1241 collecting answer into a-list
1242 finally (return (cons '(mlist simp) a-list))))
1243 ((eq (caar expr) 'mtimes)
1244 (cons '(mlist simp)
1245 (list (extract_nc_and_sc_parts expr))))
1246 (t '((mlist simp)))))))
1247 (defun $reverse_equation (eqn)
1248 (cond ((atom eqn) eqn)
1249 ((eq (caar eqn) 'mequal)(list (car eqn) (third eqn) (second eqn)))
1250 (t eqn)))
1252 (defvar *monomial-table* (make-hash-table :test 'equal))
1254 (defun nc-monomial-table (monom &aux repl)
1255 (cond ((atom monom) monom)
1256 ((atom (car monom)) monom)
1257 (t (cond ((eq (caar monom) 'mnctimes)
1259 (setq repl (gethash monom *monomial-table* ))
1260 (cond (repl (copy-tree repl))
1261 (t (setq repl ($rat monom monom))
1262 (setf (gethash monom *monomial-table*) repl)
1263 (copy-tree repl))))
1264 (t monom)))))
1266 (defun new-rat-ncmul (&rest list-of-terms &aux (denom 1))
1267 (setq list-of-terms (copy-list list-of-terms))
1268 (loop for v in list-of-terms
1269 for i from 0
1270 when (and (not (numberp v))
1271 (or (affine-polynomialp v)
1272 (rational-functionp v)))
1274 (cond ((rational-functionp v)(setq denom (denom v))))
1275 (return (cons (poly-ncmul1 (ncmuln (subseq list-of-terms 0 i) nil)
1276 (num v)
1277 (ncmuln (nthcdr (1+ i) list-of-terms) nil)) denom))
1278 finally (return (ncmuln list-of-terms nil))))
1280 (defun rat-ncmul (&rest list-of-terms)
1281 (setq list-of-terms (copy-list list-of-terms))
1282 (loop for v in list-of-terms
1283 for i from 0
1284 when ($ratp v)
1286 (return (ncmul1 (ncmuln (subseq list-of-terms 0 i) nil)
1288 (ncmuln (nthcdr (1+ i) list-of-terms) nil)))
1289 finally (return (ncmuln list-of-terms nil))))
1291 (defun ncmul1 (mon expr mon1)
1292 (setq expr (minimize-varlist expr))
1293 (loop for v in (third (car expr))
1294 when (not (fast-scalarp v))
1295 collecting (ncmul* mon v mon1) into tem
1296 else collecting v into tem
1297 finally (return (cons (list 'mrat 'simp tem (fourth (car expr)))
1298 (cdr expr)))))
1300 (defun mysub (expr replacement-function)
1301 (mysub1 (copy-tree expr) replacement-function))
1302 (defun mysub1 (vv h)
1303 (cond ((atom vv) (funcall h vv))
1304 (t (rplaca vv (funcall h (car vv)))
1305 (rplacd vv (funcall h (cdr vv)))))
1306 (cond ((atom vv) vv)
1307 (t (rplaca vv (mysub1 (car vv) h))
1308 (cond ((not (eq (car vv) 'mrat)) ( rplacd vv (mysub1 (cdr vv) h)))
1309 (t vv)))))
1311 (defun max-for-pred (a-list pred)
1312 (let ((w (car a-list)))
1313 (loop for v in a-list
1314 when (funcall pred v w)
1315 do (setq w v)
1316 finally (return w))))
1319 ;(defun find-worst-nc-monomial (expr &aux answer ans1 tem1
1320 ; cof coefficient answeru repeat-flag)
1321 ; "expr should be somewhat expanded. The result of ($multthru expr) is ok."
1322 ; (cond ((and (not ($plusp expr))
1323 ; (user:appears-in expr 'mplus))(setq expr ($multthru ($ratsimp ($expand expr))))
1324 ; (format t "~%find-worst-nc-monomial was applied to a non sum. Expanding and continuing with " )(displa expr)))
1325 ; (cond ((atom expr) (setq answer expr coefficient 1 answeru expr))
1326 ; ((eq (caar expr) 'mnctimes)(setq answer expr coefficient 1 answeru expr))
1327 ;; ((member (caar expr) '(mlist mequal) :test #'eq) (loop for u in (cdr expr)
1328 ;; appending (cdr ($list_nc_monomials u)) into a-list
1329 ;; finally (return (cons '(mlist simp) ($setfy a-list)))))
1330 ; ((eq (caar expr) 'mplus) (loop for u in (cdr expr)
1331 ; when (null answer)do (setq answeru u)
1332 ; (multiple-value ( answer coefficient)
1333 ; (extract_nc_and_sc_parts u))
1334 ; else when
1335 ; (funcall $order_function answer
1336 ; (progn (multiple-value (ans1 cof)
1337 ; (extract_nc_and_sc_parts u))
1338 ; ans1))
1339 ; do (setq answer ans1 coefficient cof answeru u)
1340 ; else when (equal ans1 answer)
1341 ; do (setq repeat-flag answer) ;(show repeat-flag)
1342 ; finally (return answer)))
1343 ; ((eq (caar expr) 'mtimes)(multiple-value (answer coefficient
1344 ; (extract_nc_and_sc_parts expr))
1345 ; (setq answeru expr)))
1346 ; (cond ((equal repeat-flag answer)(setq coefficient ($my_nc_coef expr answer))
1347 ; (setq answeru (mul* coefficient answer))
1348 ; (cond (($zerop coefficient)
1349 ; (format t "~%Having to ratsimp expression of length ~A"(length expr))
1350 ; (setq tem1 ($multthru ($ratsimp expr)))
1351 ; (cond ((fast-scalarp tem1)(setq coefficient tem1)
1352 ; (setq answeru tem1) (setq answer 1)(format t "...it was scalar"))
1353 ; (t
1354 ; (format t "...starting to look for worst monomial again")
1355 ; (multiple-value (answer coefficient answeru)
1356 ; (find-worst-nc-monomial tem1))))))))
1357 ; (show answer)
1358 ; (values answer coefficient answeru)))
1360 (defun $nc_rat (expr &aux monoms)
1361 (setq monoms (cdr ($list_nc_monomials expr)))
1362 (apply '$rat (cons expr monoms)))
1364 (defun $re_rat_the_dot_simplifications ()
1365 (loop for v in (cdr $dot_simplifications)
1366 for i from 1
1367 when (and (evenp i) )
1368 collecting (minimize-varlist ($new_rat (new-disrep (cdr v)))) into tem
1369 else collecting v into tem
1370 finally (return (cons '(mlist simp) tem))))
1372 ;(defun $rat_the_dot_simplifications ()
1373 ; (loop for v in (cdr $dot_simplifications)
1374 ; for i from 1
1375 ; when (and (evenp i) (not ($ratp v)))
1376 ; collecting (minimize-varlist ($new_rat v)) into tem
1377 ; else collecting v into tem
1378 ; finally (return (cons '(mlist simp) tem))))
1380 (defun show-genvar (&optional(a-list genvar))
1381 (loop for v in a-list
1383 (format t "~%~A disreps ~A value ~A" v (get v 'disrep) (symbol-value v))))
1385 (defun find-worst-nc-monomial (expr &aux answer ans1 tem1 cof coefficient answeru the-worst repeat-flag)
1386 "expr should be somewhat expanded. The result of ($multthru expr) is ok."
1387 (cond (($ratp expr)
1388 (loop for v in (third (car expr))
1389 for gen-var in (fourth (car expr))
1390 when (and (not ($scalarp v))
1391 (appears-in (cdr expr) gen-var)
1392 (or (null the-worst)(funcall $order_function
1393 the-worst v)))
1395 (setq the-worst v)
1396 finally (setq answer the-worst))
1397 (setq coefficient ($nc_coeff expr answer)))
1398 ((and (not ($plusp expr))
1399 (appears-in expr 'mplus))
1400 (setq expr ($multthru ($ratsimp ($expand expr))))
1401 (format t "~%find-worst-nc-monomial was applied to a non sum. Expanding and continuing with " )(displa expr)))
1402 (cond (($ratp expr) nil)
1403 ((atom expr) (setq answer expr coefficient 1 answeru expr))
1404 ((eq (caar expr) 'mnctimes)(setq answer expr coefficient 1 answeru expr))
1405 ((eq (caar expr) 'mplus) (loop for u in (cdr expr)
1406 when (null answer)
1407 do (setq answeru u)
1408 (multiple-value ( answer coefficient)
1409 (extract_nc_and_sc_parts u))
1410 else when
1411 (funcall $order_function
1412 answer
1413 (progn (multiple-value
1414 (ans1 cof)
1415 (extract_nc_and_sc_parts u))
1416 ans1))
1417 do (setq answer ans1 coefficient cof answeru u)
1418 else when (equal ans1 answer)
1419 do (setq repeat-flag answer) ;(show repeat-flag)
1420 finally (return answer)))
1421 ((eq (caar expr) 'mtimes)(multiple-value (answer coefficient)
1422 (extract_nc_and_sc_parts expr))
1423 (setq answeru expr)))
1424 (cond ((equal repeat-flag answer)(setq coefficient ($nc_coeff expr answer))
1425 (setq answeru (mul* coefficient answer))
1426 (cond (($zerop coefficient)
1427 (format t "~%Having to ratsimp expression of length ~A"(length expr))
1428 (setq tem1 ($multthru ($ratsimp expr)))
1429 (cond ((fast-scalarp tem1)(setq coefficient tem1)
1430 (setq answeru tem1) (setq answer 1)
1431 (format t "...it was scalar"))
1433 (format t "...starting to look for worst monomial again")
1434 (multiple-value (answer coefficient answeru)
1435 (find-worst-nc-monomial tem1))))))))
1436 (show answer)
1437 (values answer coefficient answeru))
1439 (defun $my_nc_coef (expr var &aux answer coeff)
1440 (check-arg expr '$plusp "macsyma sum")
1441 (loop for v in (cdr expr)
1442 when (equal var (progn
1443 (multiple-value ( answer coeff) (extract_nc_and_sc_parts v))
1444 answer))
1445 collecting coeff into the-coeff
1446 finally (return ($ratsimp (cons '(mplus) the-coeff)))))
1448 ;;note that in cre form the noncommutative monomials seem to always come
1449 ;;after the atomic variables in the genvar list ( use (mapcar 'describe genvar) to see this).
1450 ;;This means the my-ratcoeff is justified since it assumes the noncommutative variables
1451 ;;are more main, ie come later in the list.
1453 (defun $sump (x)
1454 (and (consp x) (eq (caar x) 'mplus)))
1456 (defun $nc_coeff (expr monom &optional (deg 1) &aux tem1 answer)
1457 (setq answer (cond ((atom expr)
1458 (if (eq monom expr) 1 0))
1460 (case (caar expr)
1461 (mtimes (cond ((appears-in expr monom)
1462 (loop for v in (cdr expr)
1463 when (appears-in v monom)
1464 do (setq tem1 v)
1465 else
1466 collecting v into the-rest
1467 finally (return (mul* (apply #'mul* the-rest) ($nc_coeff tem1 monom)))))
1468 (t 0)))
1469 (mplus (loop named sue for v in (cdr expr)
1470 when (appears-in v monom)
1471 collecting v into tem1
1472 finally
1473 (if tem1
1474 (loop for w in tem1
1475 collecting ($nc_coeff w monom) into the-cof
1476 finally (return-from sue (apply #'add* the-cof)))
1477 (return-from sue 0))))
1478 (mexpt 0)
1479 (rat (cond ((appears-in (cdr expr) monom)
1480 (div* ($nc_coeff (second expr) monom) (third expr)))))
1482 (mnctimes (cond ((equal (cdr monom) (cdr expr)) 1)))
1483 (mrat (my-ratcoeff expr monom deg))
1484 (otherwise (error "invalid expression~A" expr))))))
1485 (if answer answer 0))
1487 (defun number-and-zerop (x)
1488 (and (numberp x) (zerop x)))
1490 ;;this version may not work if the expr is not expanded
1491 ;; (defun $nc_coeff (expr monom &optional (deg 1) &aux tem1 answer)
1492 ;; "This will probably work only on forms that are in expanded form"
1493 ;; (setq answer (cond ((atom expr)
1494 ;; (if (eq monom expr) 1 0))
1495 ;; (t
1496 ;; (case (caar expr)
1497 ;; (mtimes (loop for u in (cdr expr)
1498 ;; when (equal u monom)
1499 ;; do
1500 ;; (return
1501 ;; (apply #'mul* (cdr (delete monom (copy-list expr) :test #'equal))))
1502 ;; when (and ($sump u)
1503 ;; (setq tem1 ($nc_coeff u monom))
1504 ;; (not (number-and-zerop tem1)))
1505 ;; do
1506 ;; (return (apply #'mul* tem1 (delete u (copy-list (cdr expr)) :test #'equal)))
1507 ;; finally (return 0)))
1508 ;; (mplus (loop named sue for v in (cdr expr)
1509 ;; do (setq tem1 ($nc_coeff v monom))
1510 ;; when (not (and (numberp tem1)(zerop tem1)))
1511 ;; collecting tem1 into tem
1512 ;; finally
1513 ;; (if tem
1514 ;; (return-from sue (apply #'add* tem))
1515 ;; (return-from sue 0))))
1516 ;; (mexpt 0)
1517 ;; (rat (cond ((appears-in (cdr expr) monom)
1518 ;; (div* ($nc_coeff (second expr) monom)
1519 ;; (third expr)))))
1521 ;; (mnctimes
1522 ;; (cond ((equal (cdr monom) (cdr expr)) 1)))
1523 ;; (mrat (my-ratcoeff expr monom deg))
1524 ;; (otherwise (error "invalid expression~A" expr))))))
1525 ;; (cond (answer answer)
1526 ;; (t 0)))
1528 (defun ncsimp (expr)
1529 (cond (($scalarp expr) expr)
1530 ((atom expr) expr)
1531 ((member 'ncsimp (car expr)) expr :test #'eq)
1533 (let ((nc-monoms ($list_nc_monomials expr)))
1534 (loop for vv in (cdr nc-monoms)
1535 collecting (mul* vv ($ratsimp ($nc_coeff expr vv)))into the-sum
1536 finally (cond ((> (length (cdr nc-monoms)) 1)
1538 (return (rplaca (apply 'add* the-sum) '(mplus simp ncsimp))))
1539 (t (car the-sum))))))))
1543 (defun $independent_linsolve (eqns independent-monomials &optional unknowns &aux equations)
1544 (setq equations ($extract_linear_equations eqns independent-monomials))
1545 (cond ($fast_solve ($fast_linsolve equations unknowns))
1547 (cond ((null unknowns)
1548 (setq unknowns
1549 ($list_of_variables equations))))
1550 ($linsolve equations unknowns))))
1551 (defun $extr_eqns (eqns independent-monomials &optional unknowns &aux equations)
1552 (setq equations ($extract_linear_equations eqns independent-monomials))
1553 (cond ((null unknowns)(setq unknowns ($list_of_variables equations))))
1554 (macsyma-list equations unknowns))
1556 (defun $nc_coefficients (eqns &aux ans)
1557 (let (vars (rat-subs ($tellrat)))
1558 (setq ans ($extr_eqns eqns ($list_nc_monomials eqns)))
1559 (setq vars (third ans))
1560 (loop for v in (cdr vars)
1561 when (or ($constantp v)
1562 (appears-in rat-subs v))
1563 do (setq vars (delete v vars :test #'equal)))
1564 (list '(mlist simp) (second ans) vars)))
1566 (defun $find_relations_in_free_ring (a-list &aux answers eqns gen-sum repr)
1567 (check-arg a-list '$listp "macsyma list")
1568 (setq gen-sum ($general_sum a-list $aaaa))
1569 (setq eqns ($nc_coefficients (list '(mlist simp) gen-sum)))
1570 (setq answers ($fast_linsolve eqns))
1571 (setq repr($sublis answers ( $general_sum
1572 (loop for i from 1 to ($length (cdr a-list))
1573 collecting ($concat '$term i) into temm
1574 finally (return (cons '(mlist) temm)))
1575 ; ($create_list ($concat '$term 'i) 'i 1 ($length (cdr a-list)))
1576 $aaaa)))
1577 (list '(mlist simp) repr answers))
1579 (defun $list_of_variables (l &aux variables)
1580 (declare (special variables))
1581 (cond ((atom l) (error "~A is not a list" l))
1582 (t (aux_to_list_of_variables l 'variables)))
1583 (cons '(mlist simp) variables ))
1585 (defun aux_to_list_of_variables (l var1)
1586 (cond ((atom l)
1587 (cond ((and l
1588 (not (numberp l))
1589 (not (member l '(simp mtimes mplus mexpt mlist mrat rat mnctimes
1590 mncexpt mequal $matrix) :test #'eq))
1591 (not (member l (symbol-value var1) :test #'eq)))
1592 (setf (symbol-value var1) (cons l (symbol-value var1))))))
1594 (loop for u in l
1596 (aux_to_list_of_variables u var1)))))
1598 (defun $firstn (n a-list)
1599 (subseq a-list 0 (1+ n)))
1601 (defun create-list2 (form l)
1602 (cons '(mlist) (apply #'create-list1 form l)))
1604 (defun $general_sum (terms &optional coefficients &aux answer)
1605 (when (null coefficients)
1606 (setq coefficients (create-list2 '($concat '$aa i) `(i 1 ,(1- (length terms)))))
1607 (mfuncall '$declare_scalar_list coefficients))
1608 (when (> (length terms) (length coefficients))
1609 (error "not enough coefficients"))
1610 (setq answer (loop for u in (cdr terms) with sum = 0
1611 for v in (cdr coefficients)
1612 do (setq sum (add* sum (mul* u v)))
1613 finally (return sum)))
1614 (values answer coefficients))
1616 (defun a-less (u v) (or (alphalessp u v) (eq u v)))
1618 (defremember commutative-monomials (a-list n &optional (type-of-weight :weight) (reset nil))
1619 (let ((atomic-terms))
1620 (cond (reset (remprop 'commutative-monomials :memory-table)))
1621 (cond ((eql n 0) nil)
1622 ((eql n 1)
1623 (loop for v in a-list
1624 when (eql n (degree v type-of-weight))
1625 collecting (list v) into tem
1626 finally (setq atomic-terms tem))
1627 atomic-terms)
1630 (loop for v in a-list
1631 when (eql n (degree v type-of-weight ))
1632 collecting (list v) into tem
1633 finally (setq atomic-terms tem))
1634 (loop for v in a-list
1635 appending
1636 (loop for w in (commutative-monomials a-list
1637 (- n (degree v type-of-weight))
1638 type-of-weight)
1640 when (a-less v (car w))
1641 collecting (cons v w))
1642 into tem1
1643 finally (return (append atomic-terms tem1)))))))
1647 (defun degree (a-list &optional (type-of-weight :weight) &aux tem)
1648 (cond ((atom a-list) (cond ((setq tem (get a-list type-of-weight)) tem)
1649 (t 1)))
1651 (loop for v in a-list
1652 when (setq tem (get v type-of-weight))
1653 summing tem into answer
1654 else summing 1 into answer
1655 finally(return answer)))))
1657 (defun $commutative_dot_monomials (a-list degree &aux answer)
1658 (setq answer (commutative-monomials (cdr a-list) degree :weight t))
1659 (setq answer (loop for u in answer collecting (cons '(mnctimes) u)))
1660 (cons '(mlist simp) answer))
1662 (defun $declare_scalar_list (l &aux fn)
1663 (setq fn (get '$declare 'mfexpr*))
1664 (cond (fn
1665 (loop for u in (cdr l) do (funcall fn (list nil u '$scalar)) ))
1666 (t (loop for u in (cdr l) do (eval `($declare ,u $scalar))))))
1669 (defun $plusp (x)
1670 (and (consp x) (consp (car x)) (eq (caar x) 'mplus)))
1672 (defun $list_nc_parts (f &aux answer)
1673 (cond ((numberp f) nil)
1674 ((atom f)(cond (($scalarp f) nil)
1675 (t f)))
1676 ((eq (caar f) 'mnctimes) f)
1677 ((eq (caar f) 'mtimes)($extract_nc_part f))
1679 (check-arg f $plusp "Maxima sum")
1680 (setq answer (loop for u in (cdr f)
1681 collecting ($extract_nc_part u)))
1682 (cons '(mlist simp) answer))))
1684 (eval-when
1685 (:load-toplevel :compile-toplevel)
1686 (defvar $poly_vector (make-polynomial-vectors)))
1688 (defvar $type_of_entries_for_poly_vector :any-macsyma)
1690 (defun $constant_term (expr variables)
1691 (cond ((atom expr)
1692 (cond ((member expr variables :test #'eq) 0)
1693 (t expr)))
1694 ((not ($plusp expr))
1695 (cond ((appears-in expr 'mplus)
1696 (error "should expand expr before taking const"))
1698 (loop for v in (cdr variables)
1699 when (appears-in expr v)
1700 do (return 0)
1701 finally (return expr)))))
1703 (loop for v in (cdr expr)
1704 when (not (loop for w in (cdr variables)
1705 when (appears-in v w)
1706 do (return t)))
1707 collecting v into the-constants
1708 finally (return (addn the-constants t))))))
1709 ;(defun sh ( poly &aux tem)
1710 ; (cond ((equal (cdr poly) 1)nil)
1711 ; (t (setq poly (cons poly 1))))
1712 ; (setq tem (cons (list 'mrat 'simp varlist genvar) poly))
1713 ; (displa tem)
1714 ; tem)
1716 (defvar $sparse_matrix nil)
1718 (defun pv-get-rows-from-macsyma-equations-and-variables
1719 (self equations the-variables &aux (eqn-no -1) rat-vars rat-eqn
1720 constants-column const cof a-row)
1721 (setf (pv-rows self) (make-array (length equations) :fill-pointer 0 :adjustable t))
1722 (cond (( pv-table self)(clrhash (pv-table self) ))
1723 (t (setf (pv-table self) (make-hash-table :test 'equal))))
1724 (setf (pv-type-of-entries self) :rational)
1725 (let
1726 ((.table. (pv-table self)))
1727 (setq constants-column nil)
1728 (setq rat-vars (mapcar 'add-newvar (cdr the-variables)))
1729 (cond (($listp equations)(setq equations (cdr equations))))
1730 (loop for eqn in equations
1732 (cond ((or (rational-functionp eqn) (affine-polynomialp eqn)) nil)
1733 (t (cond (($ratp eqn) (setq eqn ($ratdisrep eqn))))
1734 (setq eqn (bring-to-left-side eqn))))
1735 (cond (($zerop eqn) (format t "~%Eliminating Trivial Equation."))
1736 (($numberp eqn) (error "~%Inconsistent equation ~A" eqn))
1737 (t (incf eqn-no 1)
1738 (setq a-row (make-array (* 2 (equation-length eqn)) :fill-pointer 0 :adjustable t))
1739 (vector-push-extend a-row (pv-rows self))
1740 (setq rat-eqn (function-numerator (st-rat eqn)))
1741 (loop for v in rat-vars
1742 for vv in (cdr the-variables)
1743 count v into n
1744 when (not ($zerop
1745 (setq cof (pcoeff rat-eqn (list v 1 1)))))
1747 (cond ((not (numberp cof))
1748 (setf (pv-type-of-entries self) :any-macsyma)))
1749 (vector-push-extend n a-row)
1750 (vector-push-extend cof a-row)
1751 (setf (gethash vv .table.) n))
1752 (cond ((not ($zerop (setq const
1753 (pcoeff rat-eqn 1 rat-vars))))
1754 (cond ((not (numberp const))
1755 (setf (pv-type-of-entries self) ':any-macsyma)))
1756 (cond (constants-column nil)
1757 (t (setq constants-column
1758 (make-array (length equations)
1759 :fill-pointer
1760 (length equations)
1761 :adjustable t
1762 :initial-element '0))
1764 (setf (aref constants-column eqn-no) const)
1765 (setf (pv-constants-column-number self) 0))))))
1767 (adjust-array (pv-rows self)
1768 (max (length (the cl:array (pv-rows self)))
1770 :fill-pointer (fill-pointer (pv-rows self)))
1771 (cond (constants-column (setf (pv-constants-column-number self) 0)
1772 (adjust-array
1773 constants-column
1774 (max (length (the cl:array (pv-rows self))) 1)
1776 :fill-pointer
1777 (fill-pointer (pv-rows self)))
1779 (pv-set-up-sparse-matrix-from-rows self )
1780 (cond (constants-column
1781 (setf (sp-constants-column (pv-the-sparse-matrix self)) constants-column))))
1783 ;(defun pv-get-rows-from-macsyma-equations-and-variables
1784 ; (self equations the-variables &aux (eqn-no -1)
1785 ; constants-column const cof a-row)
1786 ; (setf (pv-rows self) (make-array (length equations) :fill-pointer 0 :adjustable t))
1787 ; (cond (( pv-table self)(clrhash (pv-table self) ))
1788 ; (t (setf (pv-table self) (make-hash-table :test 'equal))))
1789 ; (setf (pv-type-of-entries self) :rational)
1790 ; (let
1791 ; ((.table. (pv-table self)))
1792 ; (setq constants-column nil)
1793 ; (loop for eqn in (cdr equations)
1794 ; do (cond (($ratp eqn) (setq eqn ($ratdisrep eqn))))
1795 ; (setq eqn (bring-to-left-side eqn))
1796 ; (cond (($zerop eqn) (format t "~%Eliminating Trivial Equation."))
1797 ; (($numberp eqn) (error "~%Inconsistent equation ~A" eqn))
1798 ; (t (incf eqn-no 1)
1800 ; (setq a-row (make-array (* 2 (equation-length eqn)) :fill-pointer 0 :adjustable t))
1801 ; (array-push-extend (pv-rows self) a-row)
1802 ; (loop for v in (cdr the-variables)
1803 ; count v into n
1804 ; when (not ($zerop
1805 ; (setq cof ($nc_coeff eqn v))))
1806 ; do
1807 ; (cond ((not (numberp cof))
1808 ; (setf (pv-type-of-entries self) :any-macsyma)))
1809 ; (array-push-extend a-row n)
1810 ; (array-push-extend a-row cof)
1811 ; (setf (gethash v .table.) n))
1812 ; (cond ((not ($zerop (setq const
1813 ; ($constant_term eqn the-variables))))
1814 ; (cond ((not (numberp const))
1815 ; (setf (pv-type-of-entries self) ':any-macsyma)))
1816 ; (cond (constants-column nil)
1817 ; (t (setq constants-column
1818 ; (make-array (length equations)))
1819 ; (fillarray constants-column '(0))))
1820 ; (aset const constants-column eqn-no)
1821 ; (setf (pv-constants-column-number self) 0))))))
1823 ; (adjust-array-size (pv-rows self) (array-active-length (pv-rows self)))
1824 ; (cond (constants-column (setf (pv-constants-column-number self) 0)
1825 ; (adjust-array-size constants-column (array-active-length (pv-rows self)))))
1826 ; (pv-set-up-sparse-matrix-from-rows self )
1827 ; (cond (constants-column
1828 ; (setf (sp-constants-column (pv-the-sparse-matrix self)) constants-column)))))
1831 (defun fast-linsolve (poly-eqns variables &aux answer (add-to-dim 0) table)
1832 (cond ((get (car variables) 'disrep))
1833 (t (fsignal "variables should be genvars")))
1834 (setq variables (cons '(mlist) (loop for v in variables collecting (get v 'disrep))))
1835 ( pv-get-rows-from-macsyma-equations-and-variables $poly_vector
1836 poly-eqns variables)
1838 (format t "~%Assuming entries of type ~A" ( pv-type-of-entries $poly_vector ))
1839 (cond (variables (setf table ( pv-table $poly_vector ))
1840 (setf add-to-dim
1841 (loop for u in (cdr variables)
1842 when (null (gethash u table ))
1843 counting u and do
1844 (format t "~%The variable ~A did not appear." u)))
1845 (cond
1846 ((not (zerop add-to-dim))
1847 (format
1848 t "~%Thus we should add ~D to the dimension of the solution space."
1849 add-to-dim)))))
1850 (setf answer ( pv-solve-suitable-to-sublis $poly_vector ))
1851 answer)
1853 (defun $fast_linsolve (eqn &optional variables &aux answer table add-to-dim)
1854 "Solves list of EQUATIONS in a list of VARIABLES"
1855 (cond ((polynomial-vectors-p $poly_vector) nil)
1856 (t (setf $poly_vector (make-polynomial-vectors ))))
1857 (setf (pv-type-of-entries $poly_vector) $type_of_entries_for_poly_vector )
1858 (cond (variables ( pv-get-rows-from-macsyma-equations-and-variables $poly_vector
1859 eqn variables))
1861 ( pv-get-rows-from-macsyma-equations $poly_vector eqn)))
1862 (cond (modulus (setf (pv-type-of-entries $poly_vector) modulus)))
1863 (format t "~%Assuming entries of type ~A" ( pv-type-of-entries $poly_vector ))
1864 (cond (variables (setf table ( pv-table $poly_vector ))
1865 (setf add-to-dim
1866 (loop for u in (cdr variables)
1867 when (null (gethash u table ))
1868 counting u and do
1869 (format t "~%The variable ~A did not appear." u)))
1870 (cond
1871 ((not (zerop add-to-dim))
1872 (format
1873 t "~%Thus we should add ~D to the dimension of the solution space."
1874 add-to-dim)))))
1875 (setf answer ( pv-solve-suitable-to-sublis $poly_vector ))
1876 answer)
1878 (defun $nexp (u n &aux answer)
1879 (cond ((atom u) (ncmuln (loop for i below n collecting u) t))
1881 (setf answer
1882 (loop for i below n
1883 appending (cdr u)))
1884 (ncmuln answer t))))
1886 (defun $collect (expr)
1887 (let (($expop 0))
1888 ($ratsimp expr)))
1890 (defun $subtract_monomial (expr mon)
1891 (sub expr (mul ($nc_coeff expr mon) mon)))
1893 (defvar *start-dot-replace* nil)
1895 (defun replace-dot-simplifications (expr)
1896 (let ((dot-simps $dot_simplifications) (answer expr) )
1897 (cond ((and dot-simps *start-dot-replace*)
1898 (setf dot-simps (cdr dot-simps))
1899 (loop while dot-simps
1901 (setf answer (test_pattern answer (car dot-simps)
1902 (second dot-simps)))
1903 (setf dot-simps (cddr dot-simps))
1904 finally (return answer)))
1905 (t answer))))
1907 ;;faster version
1908 (defun test_pattern (adp pattern replacement &aux tem)
1909 "replaces the pattern in ADP (a dot product) by replacement. When
1910 inserted in the simplifier simpmnct it does the replacement whenever
1911 called."
1912 (cond ((atom adp) adp)
1913 ((equal (caar adp) 'mnctimes)
1914 (cond ((setf tem (ordered-sublist (cdr pattern ) (cdr adp)))
1915 (ncmul (ncmuln (car tem) t ) replacement (ncmuln (cadr tem) t)))
1916 (t adp)))
1917 (t adp)))
1919 (defun $nsdot (&rest l)
1920 (let (($dot_simplifications nil))
1921 (ncmuln l t)))
1922 (defun $sort_mono (variables degree)
1923 ($sort ($mono variables degree) $order_function))
1925 (defun tail-alphalessp (x y)
1926 "If x and y are lists ordering priority is based on the ends not the beginning of the lists"
1927 (cond ((and (atom x) (atom y)) (alphalessp x y))
1928 ((atom x) (alphalessp x (car (last y))))
1929 ((atom y) (alphalessp (car (last x)) y))
1930 (t (let ((lengx (length x))(lengy (length y)) xi yj)
1931 (loop for i downfrom (1- lengx) to 0
1932 for j downfrom (1- lengy) to 0
1934 (setf xi (nth i x)) (setf yj (nth j y))
1935 (cond ((alphalessp xi yj)(return t))
1936 ((alphalessp yj xi)(return nil)))
1937 finally (return (< lengx lengy)))))))
1939 (deff $tail_alphalessp #'tail-alphalessp)
1941 (defun unreplaced-monomials-in-dot-simplifications
1942 (&optional (macsyma-list $dot_simplifications)&aux tem answer)
1943 (check-arg macsyma-list $listp "macsyma list")
1944 (loop for i from 2 below (length macsyma-list) by 2
1946 (setf tem
1947 ($list_nc_parts (nth i macsyma-list)))
1948 (cond (($listp tem)(setf tem (cdr tem)))
1949 (t (setf tem (list tem))))
1951 (setf answer (zl-union answer tem)))
1952 answer)
1955 (defun ordered-sublist (small big &aux answer (some-of-big big))
1956 "Returns nil unless small appears in big in which case a list
1957 of alternating terms before and terms after each occurrence is returned"
1958 (loop while some-of-big
1959 when (initial-sublist small some-of-big)
1960 do (setf answer (append
1961 (list (subseq big 0 (- (length big) (length some-of-big)))
1962 (nthcdr (length small) some-of-big))
1963 answer))
1965 (setf some-of-big (cdr some-of-big)))
1966 answer)
1968 (defvar $table_of_unreplaced nil)
1970 (defvar $unreplaced nil)
1972 (defun $set_dot_simplifications( l)
1973 (setf $dot_simplifications nil)
1974 (setf l (meval l))
1975 (setf $dot_simplifications (copy-list l))
1977 (show l)
1978 (setf $dot_simplifications (subseq l 0 3))
1979 (setf l (cdddr l))
1981 (loop while l
1983 (setf $dot_simplifications (append $dot_simplifications
1984 (list (meval (car l)))))
1985 (setf $dot_simplifications (append $dot_simplifications
1986 (list (meval (cadr l)))))
1988 (setf l (cddr l))))
1991 (defvar $free_monomials nil)
1992 (defvar $do_not_change_free_monomials nil)
1994 (defun $generate_array_of_relations (variables degree relations
1995 &aux left-times-gen
1996 additional-degree answer ($expop 100) ans1
1997 ($dot_simplifications nil))
1999 (setf
2000 answer (make-array 64 :fill-pointer 0 :adjustable t))
2001 (loop for gen in (cdr relations)
2003 (setf additional-degree (- degree ($nc_degree gen)))
2004 (loop for j to additional-degree
2006 (loop for left-multiple in (cdr ($mono variables j))
2008 (setf left-times-gen (ncmul left-multiple gen))
2010 (loop for right-multiple in (cdr ($mono variables
2011 (sub additional-degree j)))
2013 (vector-push-extend
2014 (ncmul left-times-gen
2015 right-multiple) answer)))))
2017 (setf ans1 (adjust-array answer (length (the cl:array answer))
2018 :fill-pointer (fill-pointer answer)))
2019 answer)
2024 ;(defun $tes (n relations &aux tem)
2025 ; (setf tem ($generate_array_of_relations '((mlist simp) $x $y) n relations))
2026 ; ( pv-get-rows-from-array-of-polynomials $poly_vector tem 'sc_and_nc_parts)
2027 ; ( pv-set-up-sparse-matrix-from-rows $poly_vector )
2028 ; ( pv-reduce $poly_vector ))
2029 (defvar $poly_vector1 (make-polynomial-vectors))
2031 (defun $find_rank (nc-polynomials )
2032 ( pv-get-rows-from-array-of-polynomials
2033 $poly_vector1 nc-polynomials 'sc_and_nc_parts)
2034 ( pv-set-up-sparse-matrix-from-rows $poly_vector1 )
2035 ( pv-reduce $poly_vector1 )
2036 ( sp-number-of-pivots ( pv-the-sparse-matrix $poly_vector1 )))
2039 (defun $find_simplifications (nc-polynomial-relations)
2040 (pv-get-rows-from-array-of-polynomials $poly_vector nc-polynomial-relations
2041 'sc_and_nc_parts)
2042 (pv-set-up-sparse-matrix-from-rows $poly_vector )
2043 (pv-solve-suitable-to-sublis $poly_vector ))
2045 (defun join-arrays (&rest l &aux answer)
2046 (setf answer (make-array 100 :fill-pointer 0 :adjustable t))
2047 (loop for u in l
2049 (loop for i below (length (the cl:array u))
2051 (vector-push-extend (aref u i) answer)))
2052 (adjust-array answer (length (the cl:array answer))
2053 :fill-pointer (fill-pointer answer)))
2056 (defvar $new_fast_dotsimp t)
2057 (defun $com (x y &optional (zet 1) &aux term1 term2 )
2058 (setf term1 ( ncmul* x y))
2059 (setf term2 ( ncmul* y x))
2060 (setf term2 (mul* zet term2))
2061 ($ratsimp ($dotsimp (sub* term1 term2))))
2067 (defvar $relations nil)
2068 (defvar $previous_degree nil)
2069 (defvar $graded_relations nil)
2070 (defun set-up-graded-relations (the-variables deg new-relations
2071 &aux poly-vectors nc-polynomials finished)
2072 (cond ((not (arrayp $graded_relations))(setf $graded_relations (make-array 25 :adjustable t))))
2073 (cond ((null (aref $graded_relations deg))
2074 (setf (aref $graded_relations deg) (make-polynomial-vectors))))
2075 (setf poly-vectors (aref $graded_relations deg))
2076 (cond ((or (not (equal ( pv-relations poly-vectors ) new-relations))
2077 (not (equal ( pv-variables poly-vectors ) the-variables)))
2078 (unwind-protect
2079 (progn
2080 (format t "~%Calculating relations in degree ~A of" deg)
2081 (displa new-relations)
2082 (setf (pv-relations poly-vectors) new-relations )
2083 (setf ( pv-variables poly-vectors) the-variables)
2084 (setf nc-polynomials ($generate_array_of_relations
2085 the-variables deg new-relations))
2086 ( pv-get-rows-from-array-of-polynomials poly-vectors nc-polynomials
2087 'sc_and_nc_parts)
2088 ( pv-set-up-sparse-matrix-from-rows poly-vectors )
2089 (setf finished t))
2090 (cond (finished nil)
2091 (t (setf (pv-relations poly-vectors) nil))))
2092 ( pv-reduce poly-vectors ))))
2094 (defun $find_central_elements (variables degree &optional (relations $relations) ;(reset nil)
2095 &aux poly-vectors terms gen-sum answer a-row com basis all-eqns)
2096 "assumes relations homogeneous of same degree"
2097 (check-arg relations $listp "macsyma list")
2099 ; (setf tem ($generate_array_of_relations variables (1+ degree) relations))
2100 ; ($find_rank tem)
2101 (set-up-graded-relations variables (1+ degree) relations)
2102 (set-up-graded-relations variables degree relations)
2103 (setf basis (cons '(mlist simp)( pv-get-basis (aref $graded_relations degree) )))
2104 (setf poly-vectors (aref $graded_relations (1+ degree)))
2105 (cond ((< (length $aaaa) (length (setf terms basis)))
2106 (setf $aaaa (loop for i below (length terms)
2107 collecting ($concat '$aa i) into vars
2108 finally (return (cons '(mlist simp) vars))))
2109 ($declare_scalar_list $aaaa)))
2110 (setf gen-sum ($general_sum basis $aaaa))
2112 (loop for u in (cdr variables)
2114 (setf com ($com gen-sum u))
2115 (setf a-row (convert-polynomial-to-vector com ( pv-table poly-vectors )
2116 nil 'sc_and_nc_parts))
2117 (sp-set-type-of-entries ( pv-the-sparse-matrix poly-vectors ) ':any-macsyma)
2118 (sp-reduce-row-with-respect-to-rows ( pv-the-sparse-matrix poly-vectors ) a-row)
2119 appending (loop for i below (length (the cl:array a-row)) by 2
2120 when (aref a-row i)
2121 collecting ($rat (aref a-row (1+ i))))
2122 into eqns
2123 finally (setf all-eqns (cons '(mlist simp) eqns)))
2125 ; (loop for v in (cdr all-eqns) do (displa v))
2127 (setf answer ($fast_linsolve all-eqns (subseq $aaaa 0 (length terms))))
2128 (setf answer ($sublis answer gen-sum)))
2129 ; (break aft)
2130 ; ($express_in_terms_of_basis variables answer relations))
2132 (defvar *ans* nil)
2134 (defun pv-get-basis (self &aux monoms)
2135 "Grabs the non-pivots"
2136 (setf *ans* nil)
2137 (let ((col-used-to-pivot ( sp-columns-used-to-pivot (pv-the-sparse-matrix self)))
2138 ($dot_simplifications nil))
2140 (setf monoms (cdr ($mono (pv-variables self)
2141 ($nc_degree (get-key (pv-table self) 1)))))
2142 (loop for v in monoms
2143 when (not (gethash
2144 (gethash v (pv-table self) ) col-used-to-pivot ))
2145 collecting v)))
2148 ;(defun $test ($generators &aux tem temp2 relations)
2149 ; (setf tem ($generate_array_of_relations 1 2 (cons '(mlist simp)
2150 ; (list (nth 2 $generators)))))
2151 ; (setf temp2 ($generate_array_of_relations 1 1 (cons '(mlist simp)
2152 ; (list (nth 1 $generators)
2153 ; (nth 3 $generators)))))
2154 ; (setf relations (join-arrays tem temp2))
2155 ; ($find_rank relations))
2158 (defun $express_in_terms_of_basis ( variables form &optional
2159 (relations $relations);(reset nil)
2160 &aux a-row deg poly-vectors)
2161 (setf deg ($nc_degree form))
2162 (set-up-graded-relations variables deg relations)
2163 (setf poly-vectors (aref $graded_relations deg))
2164 (setf a-row (convert-polynomial-to-vector form ( pv-table poly-vectors )
2165 nil 'sc_and_nc_parts))
2166 (sp-set-type-of-entries ( pv-the-sparse-matrix poly-vectors ) ':any-macsyma)
2167 (sp-reduce-row-with-respect-to-rows
2168 ( pv-the-sparse-matrix poly-vectors ) a-row)
2169 (loop for ii below (length (the cl:array a-row)) by 2
2170 when (aref a-row ii)
2171 collecting (mul* (aref a-row (1+ ii))
2172 ( get-key ( pv-table poly-vectors ) (aref a-row ii)))
2173 into tem
2174 finally (return (apply 'add* tem))))
2176 (defun $test ($generators )
2177 ($find_rank ($generate_array_of_relations (macsyma-list '$w '$x '$y) 4 $generators)))
2178 (defun $find_rank_of_relations (var deg &optional (relat $relations))
2179 ($find_rank ($generate_array_of_relations var deg relat)))
2181 (defvar $leading_monomial_is_lowest_degree t "Should be true for power series")
2183 (defun $nc_degree (f &optional (type-of-weight :weight) &aux tem)
2184 (cond ((null f) 0)
2185 ((atom f)
2186 (cond ((or (numberp f)($scalarp f))0)
2187 (t (cond ((setf tem (get f type-of-weight)) tem)
2188 (t 1)))))
2189 ((affine-polynomialp f) (+ ($nc_degree (get (car f) 'disrep)) ($nc_degree (fifth f))))
2191 ;;; (($plusp f)($nc_degree (second f) type-of-weight ))
2192 (($ratp f) ($nc_degree (num (cdr f))))
2193 (($plusp f)
2194 (cond ($leading_monomial_is_lowest_degree
2195 (loop for v in (cdr f)
2196 minimize ($nc_degree v type-of-weight )))
2197 (t (loop for v in (cdr f)
2198 maximize ($nc_degree v type-of-weight )))))
2199 ((eq (caar f) '$power) (vmul* ($nc_degree (second f) type-of-weight) (third f)))
2200 (($scalarp f) 0)
2201 ((eq (caar f) 'mtimes)
2202 (loop for u in (cdr f)
2203 maximize ($nc_degree u type-of-weight)))
2204 ;;; ($nc_degree (extract_nc_and_sc_parts f) type-of-weight ))
2205 ((eq (caar f) 'rat) 0)
2206 ((eq (caar f) 'mrat)
2207 (cond ($leading_monomial_is_lowest_degree
2208 (loop for v in (varlist f)
2209 for w in (genvar f)
2210 when (and (not (fast-scalarp v))(appears-in (cdr f) w))
2211 minimize ($nc_degree v type-of-weight)))
2213 (loop for v in (varlist f)
2214 for w in (genvar f)
2215 when (and (not (fast-scalarp v))(appears-in (cdr f) w))
2216 maximize ($nc_degree v type-of-weight)))))
2217 ((eq (caar f) 'mnctimes)
2218 (loop for u in (cdr f)
2219 summing
2220 ($nc_degree u type-of-weight)))
2221 (t (error "The degree of ~A is undefined." f))))
2222 (defvar $current_replacements nil)
2223 (defvar $current_weights nil)
2225 (defun free-ncmul (&rest l)
2226 (let (($dot_simplifications nil))
2227 (ncmuln (copy-list l) t)))
2229 (defun $mono (variables n &optional reset &aux deg)
2230 (cond (reset (clear-memory-function '$mono-aux)))
2231 (loop for v in (cdr $dot_simplifications) by #'cddr
2232 when (<= (setq deg ($nc_degree v)) n)
2233 collecting v into repls
2234 when (eql deg 0)
2235 do (return '(mlist))
2236 finally (return
2237 ($mono-aux variables n repls))))
2239 (defremember $food (a b)
2240 (+ a b))
2242 (defremember $mono-aux (variables n repls &aux tem)
2243 (cond ((< n 0) nil)
2244 ((eql n 0) '((mlist) 1))
2246 (cons '(mlist)
2247 (loop for v in (cdr variables)
2248 for deg = ($nc_degree v)
2249 with op = '(mnctimes simp)
2250 appending
2251 (loop for mon in (cdr ($mono-aux variables (- n deg) repls))
2252 with answ = nil
2254 (cond ((numberp mon)
2255 (cond ((not ($must_replacep v))
2256 (push v answ))))
2257 ((symbolp mon)
2258 (cond ((not ($must_replacep
2259 (setq tem (list op v mon))))
2260 (push tem answ))))
2261 ((listp mon)
2262 (cond ((not ($must_replacep
2263 (setq tem (cons op (cons v (cdr mon))))))
2264 (push tem answ)))))
2265 finally (return (nreverse answ))))))))
2267 ;;;this is too messy.
2268 ;(defun $mono (variables n &optional reset &aux answer tem)
2269 ; (cond (reset (setq $current_variables nil)))
2270 ; (cond
2271 ; ((< n 0) (cons '(mlist simp)nil))
2272 ; (t
2273 ; (check-current-variables variables n)
2274 ; (cond ((> (1+ n) (array-total-size $current_monomials))
2275 ; (setq $current_monomials
2276 ; (adjust-array-size $current_monomials (+ n 10)))))
2277 ; (loop for v in (cdr variables)
2278 ; when ($must_replacep v)
2279 ; do (setq variables (zl-delete v variables )))
2280 ; (cond
2281 ; ((setq answer (aref $current_monomials n)) answer)
2282 ; ((eql n 0) (aset '((mlist simp) 1) $current_monomials 0)
2283 ; '((mlist simp) 1))
2284 ; (t
2286 ; (loop for u in (cdr variables)
2287 ; when (not (zerop ($nc_degree u)))
2288 ; appending
2289 ; (loop for ww
2290 ; in (cdr ($mono variables (- n ($nc_degree u))))
2291 ; when (not (initial-segment-is-replaced
2292 ; (setq tem (free-ncmul u ww))))
2293 ; collecting tem)
2294 ; into monos
2295 ; else
2296 ; appending
2297 ; (list u ) into monos
2298 ; finally (setq answer (cons '(mlist simp) monos))
2301 ; (aset answer
2302 ; $current_monomials n)(return answer)))))))
2305 ;(defun check-current-variables (variables n &aux deg )
2306 ; (cond ((or (null $current_variables)(null $current_replacements))
2307 ; (setq $current_variables variables)
2308 ; (setq $current_weights
2309 ; (loop for v in (cdr variables)
2310 ; collecting
2311 ; ($nc_degree v) into weight-list
2312 ; finally (return (cons '(mlist simp) weight-list))))
2313 ;; (loop for arr in '($current_replacements $current_monomials)
2314 ;; do
2315 ;; (cond ((arrayp (symbol-value arr))(fillarray (symbol-value arr) nil))
2316 ;; (t (setf (symbol-value arr) (make-array 35 :fill-pointer 0 adjustable t :leader-length 2 )))))
2317 ; (cond ((arrayp $current_monomials)(fillarray $current_monomials nil))
2318 ; (t (setq $current_monomials
2319 ; (zl-make-array 35 :fill-pointer 0 :adjustable t :leader-length 2 ))))
2320 ; (cond ((arrayp $current_replacements)(fillarray $current_replacements nil))
2321 ; (t (setq $current_replacements
2322 ; (make-array 35 :fill-pointer 0 :adjustable t :leader-length 2 ))))
2323 ; (loop for u in (cdr $dot_simplifications)
2324 ; by #'cddr
2325 ; do
2326 ; (setq deg ($nc_degree u))
2327 ; (aset (cons u (aref $current_replacements deg))
2328 ; $current_replacements deg))
2329 ; (setf (array-leader $current_replacements 1) $current_variables))
2330 ; (t (cond
2331 ; ((not
2332 ; (and
2333 ; (equal $current_variables variables)
2334 ; (equal (array-leader $current_replacements 1) variables)
2335 ; (loop for u in (cdr variables) and v in (cdr $current_weights)
2336 ; when (not (eql ($nc_degree u) v))
2337 ; do
2338 ; (show u v)
2339 ; (return nil)
2340 ; finally (return t))))
2341 ; (setq $current_variables nil)(check-current-variables variables n))
2342 ; ((not
2343 ; (loop for u in (cdr $dot_simplifications)
2344 ; by #'cddr
2345 ; when (<=
2346 ; (setq deg ($nc_degree u)) n)
2347 ; count 1 into num-repl
2348 ; and do
2349 ; (cond ((not (zl-member u(aref $current_replacements deg)))
2350 ; (return nil)))
2351 ; finally (cond ((not (eq num-repl
2352 ; (loop for i to n summing
2353 ; (length (aref
2354 ; $current_replacements i)))))
2355 ; (return nil))
2356 ; (t (return t)))))
2357 ; (loop for i from n below (array-total-size $current_monomials)
2358 ; do (aset nil $current_monomials i)
2359 ; (aset nil $current_replacements i))
2360 ; (loop for u in (cdr $dot_simplifications)
2361 ; by #'cddr
2362 ; when (>= (setq deg ($nc_degree u)) n)
2363 ; do
2364 ; (aset
2365 ; (cons u (aref
2366 ; $current_replacements deg))
2367 ; $current_replacements deg)))
2368 ; (t 'they-were-ok)))))
2370 ;(defun $separate_parameters (expr list-parameters)
2372 ; (loop for par in (cdr list-parameters)
2373 ; do (setf answer (copy-list expr))
2375 ; collecting
2376 ; (loop for other-par in (cdr list-parameters)
2377 ; when (not (eq other-par par))
2378 ; do (setf answer (nsubst 0 other-par answer))
2379 ; else do (setf answer (nsubst 1 other-par answer))
2380 ; do (displa answer)
2381 ; finally (return ($ratsimp answer)))
2382 ; into tem
2383 ; finally (return (cons '(mlist simp) tem))))
2385 (defun $separate_parameters (expression &rest parameters &aux answer list-parameters)
2386 (cond ((null parameters) (setf parameters '("aa" "par"))))
2387 (setf list-parameters (apply '$list_variables expression parameters))
2388 (loop for par in (cdr list-parameters)
2389 do (setf answer (copy-list expression))
2390 collecting
2391 (loop for other-par in (cdr list-parameters)
2392 when (not (eq other-par par))
2393 collecting (list '(mequal) other-par 0) into subs
2394 else collecting (cons '(mequal) (list other-par 1)) into subs
2395 finally (return ($ratsimp
2396 ($sublis (cons '(mlist simp)subs) answer))))
2397 into tems
2398 finally (return (cond ((null (cdr list-parameters))
2399 (format t "~%Special soln:")
2400 (list '(mlist) expression))
2401 (t (cons '(mlist simp) tems))))))
2403 (defun pv-clean-up (self)
2404 (setf (pv-relations self) nil)
2405 (setf (pv-variables self) nil)
2406 (setf (sp-rows (pv-the-sparse-matrix self)) nil)
2407 (setf (pv-rows self) nil)
2408 (clrhash (pv-table self) ))
2412 (defun $find_relation (variables degree monoms &optional (relations $relations)
2413 ;;(reset nil)
2414 &aux poly-vectors terms gen-sum answer a-row eqns all-eqns)
2415 "assumes relations homogeneous of same degree"
2416 (check-arg relations $listp "macsyma list")
2417 (check-arg monoms $listp "macsyma list")
2418 ; (setf tem ($generate_array_of_relations variables (1+ degree) relations))
2419 ; ($find_rank tem)
2421 (set-up-graded-relations variables degree relations)
2422 ; (setf basis (cons '(mlist simp)( pv-get-basis (aref $graded_relations degree) )))
2423 (setf poly-vectors (aref $graded_relations degree))
2426 (cond ((< (length $aaaa) (length (setf terms monoms)))
2427 (setf $aaaa (loop for i below (length terms)
2428 collecting ($concat '$aa i) into vars
2429 finally (return (cons '(mlist simp) vars))))
2430 ($declare_scalar_list $aaaa)))
2431 (setf gen-sum ($general_sum monoms $aaaa))
2433 (setf a-row (convert-polynomial-to-vector gen-sum ( pv-table poly-vectors )
2434 nil 'sc_and_nc_parts))
2435 (sp-set-type-of-entries
2436 ( pv-the-sparse-matrix poly-vectors ) ':any-macsyma)
2437 (sp-reduce-row-with-respect-to-rows
2438 ( pv-the-sparse-matrix poly-vectors ) a-row)
2439 (setf eqns (loop for i below (length (the cl:array a-row)) by 2
2440 when (aref a-row i)
2441 collecting ($rat (aref a-row (1+ i)))))
2443 (setf all-eqns (cons '(mlist simp) eqns))
2444 (setf answer ($fast_linsolve all-eqns (subseq $aaaa 0 (length monoms))))
2445 (setf answer ($sublis answer gen-sum)))
2446 (defvar *show-entry-type* t)
2448 (defun $determinant_of_equations (eqn &optional variables &aux answer )
2449 (cond ((eq (type-of $poly_vector) 'polynomial-vectors) nil)
2450 (t (setq $poly_vector (make-polynomial-vectors))))
2451 (setf (pv-type-of-entries $poly_vector) $type_of_entries_for_poly_vector)
2452 (cond (variables ( pv-get-rows-from-macsyma-equations-and-variables $poly_vector
2453 eqn variables))
2455 ( pv-get-rows-from-macsyma-equations $poly_vector eqn)))
2456 (cond (*show-entry-type*
2457 (format t "~%Assuming entries of type ~A" (pv-type-of-entries $poly_vector))))
2458 (setq answer (sp-determinant (pv-the-sparse-matrix $poly_vector)))
2459 (new-disrep answer))
2462 ;(defun fast-linsolve (eqns vari &aux solu)
2463 ; (setq solu ($fast_linsolve eqns (cons '(mlist)(mapcar #'(lambda (u) (get u 'disrep)) vari))))
2464 ; (show (length solu))
2465 ; (loop for v in (cdr solu)
2466 ; collecting (cons (add-newvar (second v)) (st-rat (third v)))))
2470 (defun $special_find_central_elements (vari deg infinites
2471 &aux mons gen-sum $vari_left
2472 comu ncmonos eqns solus general)
2473 (setq mons ($mono vari deg))
2474 (setq mons
2475 (append mons (loop for v in (cdr mons)
2476 collecting (ncmul* infinites v))))
2477 (displa mons)
2478 (setq gen-sum ($general_sum mons $aaaa))
2479 (setq general gen-sum)
2480 (loop for v in (cdr vari)
2482 (setq comu ($com general v))
2483 (setq ncmonos ($list_nc_monomials comu))
2484 (setq eqns ($extract_linear_equations `((mlist) ,comu) ncmonos))
2485 (setq solus ($fast_linsolve eqns ($list_variables eqns "aa")))
2486 (setq general (meval* ($sublis solus general)))
2487 (displa general)
2488 (setq $vari_left ($list_variables general "aa" "par"))
2489 (loop for v in (cdr $vari_left)
2490 for aa in (cdr $aaaa)
2491 collecting (cons v aa) into subs
2492 finally (setq general (sublis subs general)))
2493 (displa general))
2494 ($separate_parameters general))
2497 (defun $solve_nc_coefficients ($list-eqns &rest variable-strings)
2498 ($fast_linsolve ($extract_linear_equations $list-eqns ($list_nc_monomials $list-eqns))
2499 (apply '$list_variables $list-eqns variable-strings)))
2503 (defun gencoeff (form mon &optional( vars-to-exclude (list-variables mon)) &aux answ)
2504 "coerces to poly if possible. FORM should be a affine-polynomialp or rational-functionp"
2505 (cond ((affine-polynomialp form) (pcoeff form mon vars-to-exclude))
2506 ((rational-functionp form)(setq answ (pcoeff (num form) mon vars-to-exclude) )
2507 (cond ((pzerop answ) 0)
2508 (t (setq answ (ratreduce answ (denom form)))
2509 (cond ((eql 1 (denom answ))(num answ))
2510 (t answ)))))
2511 (t (fsignal "unknown type. Wants a polynomial or rational-function."))))
2513 (defun poly-data-from-nc-matrix (nc-matrix &aux mat-polys monom-vector monoms-in-each-column
2514 the-segment
2515 rows a-row cof )
2516 "Takes input like matrix([x.y+a*y.z,z.z+v,..],[...,...,..],...,[...,...,]])
2517 and returns a poly-data. pd-convert-to-maxima-format is the inverse."
2518 (iassert ($matrixp nc-matrix))
2519 (setq mat-polys
2520 (loop for v in (cdr nc-matrix)
2521 collecting
2522 (loop for vv in (cdr v)
2523 collecting (st-rat vv))))
2524 (setq monom-vector
2525 (loop for i from 0 below (length (first mat-polys))
2526 collecting
2527 (loop for v in mat-polys
2528 with tem
2529 do (setq tem (zl-union (list-variables (nth i v)) tem))
2530 when (and (not (member 1 tem))
2531 (not (pzerop (gencoeff (nth i v) 1 tem))))
2532 do (setq tem (cons 1 tem))
2533 finally (return
2534 (loop for va in tem when (eql va 1)
2535 collecting va
2536 else when (> ($nc_degree (get va 'disrep)) 0)
2537 collecting (list va 1 1 ))))))
2538 (setq monoms-in-each-column (mapcar 'length monom-vector))
2539 (setq the-segment (loop for v in monoms-in-each-column
2540 collecting all
2541 summing v into all))
2542 (setq rows (make-array (length mat-polys) :fill-pointer (length mat-polys)))
2543 (loop for ro in mat-polys
2544 for ii from 0
2546 (setq a-row (make-array 10 :fill-pointer 0 :adjustable t))
2547 (setf (aref rows ii) a-row)
2548 (loop for pol in ro
2549 for monoms in monom-vector
2550 for n in monoms-in-each-column
2552 (loop for mon in monoms
2553 for i from 0
2554 when (eql 1 mon)
2555 do(setq cof (gencoeff pol mon(list-variables monoms)))
2556 else
2557 do (setq cof (gencoeff pol mon))
2558 when (not (pzerop cof))
2560 (vector-push-extend (+ i tot-monoms) a-row)
2561 (vector-push-extend cof a-row))
2562 summing n into tot-monoms))
2563 (make-poly-data :segments the-segment
2564 :rows rows
2565 :big-monom-list (loop for v in monom-vector nconc v)))
2567 (defun segment-interval (segments spot)
2568 (loop for v in segments
2569 for ii from 0
2570 when (> v spot)
2571 do (return (1- ii))
2572 finally (return ii)))
2574 (defun pd-convert-to-maxima-format (pd &aux tem where lis a-row)
2575 (cons '($matrix)
2576 (loop for i below (fill-pointer (pd-rows pd))
2578 (setq lis (make-list (length (pd-segments pd)) :initial-element 0))
2579 (loop for k below (fill-pointer (setq a-row (aref (pd-rows pd) i))) by 2
2580 when (setq tem (aref a-row k))
2581 do (setq where (segment-interval (pd-segments pd) tem) )
2582 (setf (nth where lis) (n+ (nth where lis)
2583 (n* (aref a-row (1+ k))
2584 (nth tem (pd-big-monom-list pd))))))
2585 (setq lis (mapcar 'new-disrep lis))
2586 when (loop for v in lis when (not (pzerop v))do (return t))
2587 collecting (cons '(mlist) (mapcar 'new-disrep lis)))))
2589 (defun id (mat &aux (pd (poly-data-from-nc-matrix mat)) )
2590 (describe pd)
2591 (pd-convert-to-maxima-format pd))
2593 (defun reduce-poly-data (pd &aux sp)
2594 (setq sp (sp-make-sparse-matrix (pd-rows pd)))
2595 (sp-reduce sp)
2599 (defun $nc_matrix_row_reduce (mat &aux pd)
2600 "Does row reduction, assuming that the set of non commutative monomials
2601 are linearly independent, so that matrix([x.y,0],[x,0],[1,0]) is already
2602 reduced. Like most of the nc stuff it assumes that scalars preced non
2603 scalars in the alphabet"
2604 (setq pd (poly-data-from-nc-matrix mat))
2605 (reduce-poly-data pd)
2606 (pd-convert-to-maxima-format pd))
2608 (defun $nc_matrix_quotient (mat1 modulo-mat &aux all-rows big-mat big-pd )
2609 "returns a matrix whose rows are a basis for the quotient row space of mat1 modulo modulo-mat"
2610 (iassert ($matrixp modulo-mat)) (iassert ($matrixp mat1))
2611 (setq big-mat (append modulo-mat (cdr mat1)))
2612 (setq big-pd (poly-data-from-nc-matrix big-mat))
2613 (setq all-rows (listarray (pd-rows big-pd)))
2614 (multiple-value-bind (sp1 sp2)
2615 (sp-quotient-space-basis (subseq all-rows 0 ($length modulo-mat))
2616 (nthcdr ($length modulo-mat) all-rows))
2618 (setf (pd-rows big-pd) (sp-rows sp1))
2619 (pd-convert-to-maxima-format big-pd)))