1 ;;; -*- Mode: LISP; Package: cl-maxima; Syntax: Common-lisp -*-
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ;;; Copyright (c) 1984 by William Schelter,University of Texas ;;;;;
5 ;;; All rights reserved ;;;;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 ;;then have a compiler optimizer which does the selection.
13 (n+ (car l
) (apply 'nn
+ (cdr l
))))
14 (t (n+ (car l
) (second l
)))))
16 ;;a and b should be polynomials or rational-functions with the following
17 ;;restrictions: Any noncommutative variables or monomials occur with
18 ;;higher pointergp than any scalars. This will be the case with
19 ;;add-newvar if you stick to using a,b,%zeta, etc for the scalars and
20 ;;x,y,z,.. for the noncommutative variables. All the nc parts thus will
21 ;;come first so that a polynomial will be scalar if its main variable is
22 ;;scalar. General assumption is that nc polynomial will have all the nc
23 ;;parts before any of the nc parts and no non commutative denominators.
24 ;;We also assume that a noncommutative polynomial looks like
25 ;; ncprod-or-var*cof+ncpolynomial where cof is a scalar polynomial
26 ;;probably the default should be that variables are scalar, but
27 ;;at present the central variables must satisfy ($scalarp var) ==> t
32 ((numberp b
) (n* a b
))
33 ((atom b
) (setq b
(st-rat b
))(n. a b
))
34 ((affine-polynomialp a
)
35 (cond ((affine-polynomialp b
)
36 (let ((va (get (p-var a
) 'disrep
)) vb ncprod
)
39 (($scalarp
(setq vb
(get (p-var b
) 'disrep
)))
41 (t (check-arg a
(and (<= (length a
) 5)
42 (<= (p-deg a
) 1)) "an nc polynomial")
43 (check-arg b
(and (<= (length b
) 5)
44 (<= (p-deg b
) 1)) "an nc polynomial")
45 (setq ncprod
(add-newvar (ncmul* va vb
)))
46 (nn+ (ptimes (list ncprod
1 1) (ptimes (p-cof a
) (p-cof b
)))
47 (cond ((cdddr a
) (n.
(fifth a
) (subseq b
0 3)))
49 (cond ((cdddr b
) (n.
(subseq a
0 3) (fifth b
) ))
51 (cond ((and (cdddr a
) (cdddr b
))
52 (n.
(fifth a
) (fifth b
)))
54 ((rational-functionp b
) (nred (n. a
(num b
)) (denom b
)))
55 (t (n. a
(st-rat b
)))))
56 ((rational-functionp a
)
57 (nred (n.
(num a
) b
) (denom a
)))
58 (t (setq a
(st-rat a
))
62 (defun $find_sygy
(degn &aux monoms general-term eqns sols simp
)
63 (setq monoms
($mono $current_variables
(1- degn
)))
66 (loop for v in
(cdr monoms
)
67 collecting
(ncmul* v
'$x
)
68 collecting
(ncmul* v
'$y
))))
70 (setq general-term
($general_sum monoms $aaaa
))
71 (setq simp
($ratdisrep
($dotsimp general-term
)))
73 (mshow ($list_nc_monomials simp
))
74 (setq simp
($ratsimp
($numerator simp
)))
75 (setq eqns
($extract_linear_equations
`((mlist) ,simp
)))
76 (setq sols
($fast_Linsolve eqns
($list_variables eqns
"aa")))
78 ($separate_parameters
($sublis sols general-term
)))
81 (defun $find_sygy
(degn matrix
82 &aux monoms eqns sols pref general-image general-from from-n to-n simp scal
)
83 " find_sygy(2,matrix([x],[y]))===> pq"
84 (setq from-n
($length matrix
))
85 (setq to-n
($length
(second matrix
)))
86 (setq monoms
($mono $current_variables degn
))
87 (setq pref
(loop for i
89 collecting
($concat
'$aa i
)))
91 (cons '(mlist) (loop for u in pref do
92 (setq scal
(loop for i below
($length monoms
)
93 collecting
($concat u i
)))
94 ($declare_scalar_list
(setq scal
(cons '(mlist) scal
)))
95 collecting
($general_sum monoms scal
))))
97 (setq general-image
(ncmul* general-from matrix
))
100 (setq simp
($ratdisrep
($dotsimp general-image
)))
103 (mshow ($list_nc_monomials simp
))
104 (setq simp
($ratsimp
($numerator simp
)))
105 (cond (($listp simp
) nil
)
106 (($matrixp simp
)(setq simp
($list_matrix_entries simp
)))
107 (t (setq simp
(list '(mlist) simp
))))
108 (setq eqns
($extract_linear_equations simp
))
109 (setq sols
($fast_Linsolve eqns
($list_variables eqns
"aa")))
111 ($separate_parameters
($sublis sols general-from
)))
113 (defmacro matrix-row
(mat n
)`(nth ,n
,mat
))
115 (defun matrix-column (mat n
)
116 (cons '(mlist) (loop for v in
(cdr mat
)
117 collecting
(nth n v
))))
119 (defvar $module_simp_for_kernel nil
)
120 (defun $find_kernel
(in-deg matrix
&optional multiply-on-left
121 &aux first eqns sols general-image $general_from simp
)
122 "if matrix is m x n then it finds the kernel of the MAPL on the right
123 multiplication B:A^m-->A^n v |---> vB or the kernel of the left
124 multiplication A^m <--- A^n:B Bv<----|v"
125 (cond (multiply-on-left (setq first
(matrix-row matrix
1)))
127 (setq first
(matrix-column matrix
1))))
129 ;;in-deg refers to degree of image in 1-1 position
130 (setq $general_from
(cons '(mlist)
131 (loop for u in
(cdr first
)
133 collecting
($scalar_sum
($concat
'$ff i
)
134 ($mono $current_variables
135 (- in-deg
($nc_degree u
)))))))
136 (mshow $general_from
)
137 (cond (multiply-on-left
138 (setq general-image
(ncmul* matrix
($transpose $general_from
) )))
139 (t (setq general-image
(ncmul* $general_from matrix
))))
140 (mshow general-image
)
141 (setq simp
($ratdisrep
($dotsimp general-image
)))
142 (cond ($module_simp_for_kernel
(format t
"~%Simplifying by ~A" $module_simp_for_kernel
)
143 (setq simp
($totaldisrep
(funcall $module_simp_for_kernel simp
)))))
145 (setq simp
($ratsimp
($numerator simp
)))
146 (cond (($listp simp
) nil
)
147 (($matrixp simp
)(setq simp
($list_matrix_entries simp
)))
148 (t (setq simp
(list '(mlist) simp
))))
149 (setq eqns
($extract_linear_equations simp
))
150 (setq sols
($fast_Linsolve eqns
($list_variables eqns
"ff")))
152 ($separate_parameters
($sublis sols $general_from
) "par" "ff"))
154 (defun $find_basis
(list-vectors &aux sum eqns sols rk
)
155 (setq sum
($scalar_sum
'$aa list-vectors
))
156 (setq eqns
($ratsimp
($numerator
($ratdisrep
($dotsimp sum
)))))
157 (setq eqns
($extract_linear_equations eqns
))
158 (setq sols
($fast_Linsolve eqns
($list_variables eqns
"aa")))
159 (setq rk
(sp-number-of-pivots (pv-the-sparse-matrix $poly_vector
)))
160 ($separate_parameters
($sublis sols sum
) "par" "aa"))
162 (defun $scalar_sum
(prefix monoms
&aux scal
)
163 ; (declare (values general-sum scalars))
164 (setq scal
(loop for i below
($length monoms
)
165 collecting
($concat prefix i
)))
166 ($declare_scalar_list
(setq scal
(cons '(mlist) scal
)))
167 (values ($general_sum monoms scal
) scal
))
169 (defun replace-parameters-by (expr prefix
&aux olds pars tem
)
170 (setq pars
(cdr ($list_variables expr
"par")))
171 (setq olds
($list_variables expr prefix
))
172 (loop for i from
0 while pars
173 when
(not (member (setq tem
($concat prefix i
)) olds
:test
#'equal
))
174 collecting
(cons (car pars
) tem
) into repl
176 do
(setq pars
(cdr pars
))
178 (loop for v in repl do
(format t
"~%Replacing ~A by ~A" (car v
) (cdr v
)))
179 (return (sublis repl expr
)))
182 (defun $leftsocle
(in-degree module-relations rad
&aux h newh relats allrelats
183 monoms eqns vari solns hh condition tem
)
184 "currently the modulue is a cyclic left module M=A/A.module-relations and
185 we test to find solutions for h of v.h-A.module-relations for v in rad
186 everything is supposed to be homogeneous"
187 (setq h
($scalar_sum
'$bbb
($mono $current_variables in-degree
)))
189 (loop for v in
(cdr module-relations
)
192 (setq tem
($scalar_sum
($concat
'$ccc i
)
193 ($mono $current_variables
194 (1+ (- in-degree
($nc_degree v
))))))
195 collecting
(ncmul* tem v
)))
196 (setq allrelats
(meval* (cons '(mplus) relats
)))
198 (setq monoms
($mono $current_variables in-degree
))
199 ;;impose condition x.h-general-sum module-relations
200 (loop for v in
(cdr rad
)
201 with all-rel
= (num (new-rat allrelats
))
202 do
(setq v
(st-rat v
))
203 (setq hh
(n. v
(num (new-rat h
))))
204 (setq condition
(n- hh all-rel
))
205 ; (setq condition (sub* (ncmul* v h)
207 ; (setq conditon (num (new-rat
208 ; (setq condition ($numerator condition))
209 ; (setq condition ($ratdisrep ($numerator ($dotsimp condition))))
210 (setq condition
(new-rat-dotsimp (cons condition
1)))
212 (setq condition
($totaldisrep
($numerator condition
)))
213 (setq eqns
($extract_linear_equations
(list '(mlist) condition
)))
214 (setq vari
($list_variables eqns
"bbb" "ccc" ))
215 (setq solns
($fast_linsolve eqns vari
))
216 (setq newh
($ratsimp
($sublis solns h
)))
218 (return '((mlist)))))
219 (setq h
(replace-parameters-by newh
'$bbb
))
221 finally
(return ($separate_parameters newh
"bbb" "par"))))
223 (defun $try_bezout
( f g
&optional
(linears #$
[z-a
*x
,y-b
*x
]$
) &aux
(deg ($nc_degree f
)) eqns cofs cof-eqns answ det tem
)
224 "solve f=f1*(z-a*x)+f2*(z-b*x),g=g1*(z-a*x)+g2*(z-b*x)"
225 (setq cofs
(loop for v in
'(f1 f2 g1 g2
)
227 ($scalar_sum
($concat
'$ccc v
)
228 ($mono $current_variables
(- deg
1))))
231 (loop for
(aa bb
) on cofs by
#'cddr
234 (loop for lin in
(cdr linears
)
235 for acof in
(list aa bb
)
237 do
(setq eqn
(sub* eqn
(ncmul* acof lin
)))
238 finally
(return eqn
))))
239 (setq eqns
(loop for v in eqns collecting
($ratdisrep
($dotsimp v
))))
240 (setq cof-eqns
($extract_linear_equations
(cons '(mlist) eqns
) ($mono $current_variables deg
)))
242 (setq answ
($fast_linsolve cof-eqns
($list_variables cof-eqns
"cc")))
243 (setq det
(sp-determinant (pv-the-sparse-matrix $poly_vector
)))
244 (list '(mlist) answ
(new-disrep det
)))
246 (defun $intersect_principals_variety
($f1 $f2 in-deg
&optional in-free-ring
247 &aux $g1 $g2 eqn eqns
)
248 "Af1 intersect f2A yielding g1.f1=f2.g2, and returns a equations.."
249 (declare (special $g1 $g2 $f1 $f2
))
250 (setq $g1
($scalar_sum
'$gg1
($mono $current_variables
(- in-deg
($nc_degree $f1
)))))
251 (setq $g2
($scalar_sum
'$gg2
($mono $current_variables
(- in-deg
($nc_degree $f2
)))))
252 (setq eqn
#$
[g1.f1-f2.g2
]$
)
253 (cond (in-free-ring nil
)
254 (t (setq eqn
($totaldisrep
($dotsimp eqn
)))))
255 (setq eqns
($extract_linear_equations eqn
)))
257 (defun $intersect_principals
($f1 $f2 in-deg
&optional modulo-free-ring
258 &aux free-result result $g1 $g2 eqn eqns solns
)
259 "Af1 intersect f2A yielding g1.f1=f2.g2, and returns a matrix([g1,g2],[g1p,g2p],...)"
260 (declare (special $g1 $g2 $f1 $f2 $eqns
))
261 (cond (modulo-free-ring
262 (let ($dot_simplifications
)
263 (setq free-result
($intersect_principals $f1 $f2 in-deg
)))
264 (setq free-result
($totaldisrep
($dotsimp free-result
)))
265 (setq result
($intersect_principals $f1 $f2 in-deg
))
266 ($nc_matrix_quotient result free-result
))
268 (setq $g1
($scalar_sum
'$gg1
($mono $current_variables
(- in-deg
($nc_degree $f1
)))))
269 (setq $g2
($scalar_sum
'$gg2
($mono $current_variables
(- in-deg
($nc_degree $f2
)))))
270 (setq eqn
#$totaldisrep
(dotsimp([g1.f1-f2.g2
]))$
)
272 (setq $eqns
(setq eqns
($extract_linear_equations eqn
)))
273 (setq solns
($fast_linsolve eqns
($list_variables eqns
"gg")))
274 (setq result
($sublis solns
#$
[g1
,g2
]$
))
275 (cons '($matrix
) (cdr ($separate_parameters result
"par" "gg")))
278 ;(defun $find_basis_module (in-deg matrix-relations &optional right)
279 ; "given matrix([[f1,f2,..,fr],[g1,g2,..,gr],...]) compute a basis
280 ; for the free module A^r modulo the left(resp right) submodule generated by the
281 ; rows of matrix. Each row must satisfy nc_degree(fi)= nc_degree(fj)."
283 (defvar $module_simplifications nil
)
285 (defun module-monom-must-replacep (monom &aux repl
)
287 (setq repl
(member monom
(cdr $module_simplifications
) :test
#'eq
))
288 (cond (repl (list monom
(second repl
)))))
290 (loop for v on
(cdr $module_simplifications
) by
#'cddr
291 with leng
= (length monom
)
294 (or (and (listp (car v
))
295 (>= leng
(setq leng-first-v
(length (car v
))))
296 (equal (nthcdr (- leng leng-first-v
) (cdr monom
)) (cdar v
)))
297 (eql (car v
) (nth (1- (length monom
)) monom
)))
298 do
(return (list (first v
) (cond ((numberp (second v
)) (second v
))
299 (t (cdr (second v
))))))))))
300 ;(defun module-must-replacep (poly)
301 ; (*catch 'found-replace
302 ; (mod-must-replace1 poly)))
304 (defun module-must-replacep (poly &aux monom
)
307 (cond ((atom poly
) (return nil
))
308 ((module-monom-must-replacep (setq monom
(get (car poly
) 'disrep
)))
309 (return (cons (car poly
) (module-monom-must-replacep monom
))))
310 (t (setq poly
(fifth poly
))))))
312 (defun rat-simplifications (simps)
313 (cons '(mlist) (loop for
(mon rep
) on
(cdr simps
) by
#'cddr
315 collecting
(cons *fake-rat
* (new-rat rep
)))))
317 (defun module-simp (fun &aux did-replace num-fun den-fun
318 mon actual-repl repl den prev-mon lft symbo num-repl repl-data
)
319 "argument satisfies rational-functionp"
320 (cond ((affine-polynomialp fun
)(setq num-fun fun
)(setq den-fun
1))
321 ((rational-functionp fun
)(desetq (num-fun . den-fun
) fun
))
322 (t (fsignal "takes poly or rat'l function for argument")))
323 ; (show $module_simplifications)
324 (loop while
(setq repl-data
(module-must-replacep num-fun
)) do
325 (desetq (symbo mon repl
) repl-data
)
326 (setq prev-mon
(get symbo
'disrep
))
328 (setq lft
(dot-right-quotient prev-mon mon
))
329 (setq actual-repl
(n.
(st-rat lft
) repl
))
330 (cond ((affine-polynomialp actual-repl
) (setq num-repl actual-repl
) (setq den
1))
331 ((rational-functionp actual-repl
)(desetq (num-repl . den
) actual-repl
))
332 (t (fsignal "bad repl")))
333 (format t
"~%Module simp replacing ~A" (get symbo
'disrep
))
334 (setq num-fun
(psublis(list (cons symbo num-repl
)) den num-fun
))
335 (setq den-fun
(n* den den-fun
))
336 finally
(return (cond (did-replace (ratreduce num-fun den-fun
))
339 (defun delete-from-simps (simps mon repl
)
340 (loop for v on
(cdr simps
) by
#'cdr
341 when
(and (equal (car v
) mon
)
342 (equal (second v
) repl
))
343 do
(return (cons '(mlist)(nconc tem
(cddr v
))))
345 nconc
(subseq v
0 2) into tem
))
348 ;;;needs work:note that we have not been using new-rat-dotsimp and we need to!
349 ;;;maybe the best plan is to sort the simps in increasing order of degree,
350 ;;;then to (let the modsimps be just one term and one replacement and check
351 ;;;alll remaining ones for subs. Any replacement will be further down the
352 ;;;list. Also if you do a replacement you could not get earlier in the list
353 ;;;if they are sorted by degree, and within degree by worst monom
354 ;(defun simplify-module-simplifications ()
355 ; (loop named sue for (mon rep) on (cdr $dot_simplifications) by #'cddr
357 ; (let (($module_simplifications (delete-from-simps $module_simplifications mon repl)))
358 ; (loop for (mon1 rep1) on (cdr $dot_simplifications) by #'cddr
359 ; when (or (module-monom-must-replacep mon1)
360 ; (module-must-replacep rep1))
362 ; (setq relat (function-numerator (module-simp (make-relation mon1 rep1))))
363 ; (setq relat (module-simp relat))
365 ; (return-from sue 'start-over))
366 ; (setq new (plain-add-to-module-simps relat)))))
368 (defun make-relation (monom repl
)
369 ; (iassert (or (numberp repl) (eql (caar repl) 'mrat)))
370 (cond ((numberp repl
) nil
)
371 ((affine-polynomialp repl
)(setq repl
(cons repl
1)))
372 ((rational-functionp repl
) nil
)
373 ((eql (caar repl
) 'mrat
) (setq repl
(cdr repl
)))
374 (t (fsignal "bad repl")))
375 (function-numerator (n- monom repl
)))
378 (defun sort-simps-by-degree (simps)
379 (cons (car simps
) (sort-grouped-list (cdr simps
) 2 #'(lambda (u v
)
382 ((< (length u
) (length v
)) )
383 ((> (length u
) (length v
)) nil
)
384 (( funcall $order_function v u
)))))))
387 (defun module-and-dot-simp (pol &aux
(changed t
))
390 (cond ((module-must-replacep pol
)
391 (setq pol
(module-simp pol
)) (setq changed t
)))
392 (cond (($must_replacep pol
)
393 (setq pol
(cdr (new-rat-dotsimp pol
)))
396 finally
(return pol
)))
398 (defun gen-dot-check-associative (a b c
&optional
(simplifier 'module-and-dot-simp
) &aux answ
)
399 "simplifier should return a polynomial or rational function"
400 (setq answ
(n- (n.
(funcall simplifier
(n. a b
)) c
)
401 (n. a
(funcall simplifier a b
))))
402 (cond ((pzerop answ
) (format t
"~%It was associative"))
406 ;(defun find-right-overlap (left right &aux answ)
410 ; (cond ((eql left right)(list nil left nil))
411 ; ((equal left (car (last right)))
412 ; (list (butlast right) left nil))
415 ; (cond ((equal right (car (last left)))
416 ; (list (butlast left) right nil))
419 ; (multiple-value-bind (lap right-excess)
420 ; (find-lap1 (cdr left) (cdr right))
421 ; (cond (lap (list (firstn (- (length left) 1 (length lap)) (cdr left)) lap right-excess)))))))
426 ; (loop for v on answ
430 ; finally (return answ))))
432 (defun coerce-nctimes (a)
433 "nil-->1, '(a) -->a '(x y z) --> x.y.z , x.y--> x.y"
437 (cond ((listp (car a
))
438 (cond ((eql (caar a
) 'mnctimes
)
439 (cond ((null (cdr a
)) 1)
442 (t (fsignal "what am i like?"))))
445 (t (cons '(mnctimes) a
))))
448 (defun $lastn_ncdegree
(mon n
)
449 "Returns an final segment of mon of degree n if possible, otherwise nil"
452 (and (equal ($nc_degree mon
) n
)
455 for i downfrom
(1- (length mon
)) to
1
457 summing
($nc_degree u
) into tot
461 (return (coerce-nctimes (nthcdr i mon
))))
462 (t (return nil
)))))))
464 (defun $firstn_ncdegree
(mon n
)
465 "Returns an initial segment of mon of degree n if possible, otherwise nil"
468 (and (equal ($nc_degree mon
) n
)
470 (t (loop for u in
(cdr mon
)
472 summing
($nc_degree u
) into tot
476 (return (coerce-nctimes (subseq mon
0 i
))))
477 (t (return nil
)))))))
481 (defun $find_right_lap
(left right tot-deg
&aux size-lap a-lap
)
482 "tot-deg is the degree of the lapped left and right. It will not catch left a subset
483 of right since it is presumed the right is in reduced form "
484 (let ((ld ($nc_degree left
))
485 (rd ($nc_degree right
)))
486 (setq size-lap
(- (+ ld rd
) tot-deg
))
487 (cond ((<= size-lap
0) nil
)
488 (t (setq a-lap
($lastn_ncdegree left size-lap
))
494 (initial-seg (cdr a-lap
) (cdr right
)))
495 (t (equal (second right
) a-lap
)))))))
496 (list ($firstn_ncdegree left
(- ld size-lap
))
498 ($lastn_ncdegree right
(- rd size-lap
)))))))))
500 (defun $find_right_lap
(left right tot-deg
&aux size-lap a-lap
)
501 "tot-deg is the degree of the lapped left and right. It will not catch left a subset
502 of right since it is presumed the right is in reduced form "
503 (let ((ld ($nc_degree left
))
504 (rd ($nc_degree right
)))
505 (setq size-lap
(- (+ ld rd
) tot-deg
))
506 (cond ((<= size-lap
0) nil
)
507 (t (setq a-lap
($lastn_ncdegree left size-lap
))
508 (cond ((and a-lap
;;have match
509 (cond ((equal a-lap right
))
510 ((and (listp a-lap
) (listp right
)
511 (initial-seg (cdr a-lap
) (cdr right
))))
512 ((and (atom a-lap
) (listp right
)
513 (equal (second right
) a-lap
)))))
514 (list ($firstn_ncdegree left
(- ld size-lap
))
516 ($lastn_ncdegree right
(- rd size-lap
)))))))))
519 ;(defun $find_right_lap (left right tot-deg &aux size-lap a-lap )
520 ; "tot-deg is the degree of the lapped left and right. It will not catch left a subset
521 ; of right since it is presumed the right is in reduced form "
522 ; (let ((ld ($nc_degree left))
523 ; (rd ($nc_degree right)))
524 ; (setq size-lap (- (+ ld rd) tot-deg ))
525 ; (cond ((<= size-lap 0) nil)
526 ; (t (setq a-lap ($lastn_ncdegree left size-lap))
528 ;; (setq b-lap ($firstn_ncdegree right size-lap))))
531 ; (or (equal a-lap right)
532 ; (and (listp a-lap) (listp right)
533 ; (initial-seg (cdr a-lap) (cdr right)))
534 ; (listp right) (equal (second right) a-lap))
536 ;; (equal (cdr a-lap) (cdr b-lap)))))
537 ; (list ($firstn_ncdegree left (- ld size-lap))
539 ; ($lastn_ncdegree right (- rd size-lap)))))))))
541 (defun initial-seg (seg lis
)
542 "'(1 2) '(1 2 3) --> values: t '(3), '(1 2) '(0 1 2 3) --> nil, '(1 2) '(1) --> nil"
545 (or (eql (car seg
) (car lis
)) (return nil
))
548 (cond ((null seg
) (return (values t lis
))))
549 (and (null lis
) (return nil
))
555 (defun plain-add-to-module-simps (poly)
556 (cond ($module_simplifications nil
)
557 (t (setq $module_simplifications
'((mlist)))))
558 (setq $module_simplifications
559 (append $module_simplifications
(make-simp (function-numerator poly
)))))
563 ;;I reduce module-simps leading terms wrt themselves.
564 ;;II If M is a leading term of f and DM is a dotsimp replacement,
565 ;; and there is a dotsimp repl R and the tail of R overlaps the left side of M
566 ;;then we have two ways of simplifying and need to add the difference.
567 ;;add in the simp dotsimp(Df). Note this is essentially checking for overlaps
568 ;;between the module simps and the dotsimps.
569 ;;Have two functions: I one which checks for type I and if finds, returns the (changed list of simps , t)
570 ;;else returns simps,nil
571 ;;II one which checks for the II type and returns the new list of simps ,t or just old list of simps.
574 (defun make-simp (relat &aux answ
)
575 "inverse of make-relation, except that constants will be cancelled."
576 (setq answ
(cond ((numberp relat
)
577 (cond ((zerop relat
) nil
)
579 (t (list (get (car relat
) 'disrep
)
581 (cons *fake-rat
* (ratreduce (pminus (fifth relat
)) (third relat
))))
586 (defun dot-right-quotient (a b
&aux tem answ
)
587 "a.b^^-1 with error if b not final segment"
591 (t (fsignal "doesn't divide evenly"))))
592 ((equal (car (last a
)) b
)
593 (setq answ
(butlast a
)))
594 (t (fsignal "not tail"))))
596 (loop for v in
(cdr b
)
597 for w in
(nthcdr (setq tem
(1+ (- (length a
) (length b
)))) a
)
599 when
(not (equal v w
))
600 do
(fsignal "b is not a tail of a"))
601 (setq answ
(subseq a
0 tem
))))
602 (cond ((cddr answ
) answ
)
603 ((cdr answ
) (second answ
))
606 (defvar *module-overlaps-checked
* nil
)
608 (defun simplify-module-simps (to-deg &aux changed new-simps
( present-deg
0))
609 (declare (special present-deg
))
610 (user-supply *module-overlaps-checked
*)
611 (loop do
(setq changed nil
)
612 (loop for f in
'(type-i-simp type-ii-simp
) do
615 (funcall f present-deg to-deg
))
616 (setq $module_simplifications new-simps
)
617 (cond (changed (return 'try-again
))))
619 finally
(return $module_simplifications
)))
621 (defun type-i-simp (&rest ignore
&aux old-simps relat new-relat
)
622 (declare (ignore ignore
))
623 "eliminate simps such that one leading term is a left multiple of another, ie common right overlap"
624 (setq old-simps
(setq $module_simplifications
(sort-simps-by-degree $module_simplifications
)))
625 (loop named sue for tail-simps on
(cdr old-simps
) by
#'cddr
628 (let (($module_simplifications
(cons '(mlist) (subseq tail-simps
0 2))))
629 (loop for
(mon repl
) on
(cddr tail-simps
) by
#'cddr
630 for jj from
(+ i
2) by
2
631 when
(or (module-monom-must-replacep mon
)
633 (module-must-replacep (function-numerator (cdr repl
)))))
634 do
(setq relat
(make-relation mon repl
))
635 (setq new-relat
(module-simp relat
))
636 (setq new-relat
(new-rat-dotsimp new-relat
))
637 (cond ((numberp new-relat
)
638 (cond ((zerop new-relat
) nil
)))
639 (t (setq new-relat
(cdr new-relat
))
640 (iassert (rational-functionp new-relat
))
641 (setq new-relat
(num new-relat
))))
642 (return-from sue
(values (nconc (subseq old-simps
0 (- jj
2))
643 (make-simp new-relat
)
644 (nthcdr jj old-simps
))
646 finally
(return-from sue
(values old-simps nil
))))))
648 (defun dotsimp (ratl-or-poly)
649 ; (declare (values ratl-function))
650 (new-rat (new-rat-dotsimp ratl-or-poly
)))
652 (defun ratl-function-id (number-or-rational-function &aux tem
)
653 (cond ((affine-polynomialp number-or-rational-function
)
654 number-or-rational-function
)
655 ((rational-functionp number-or-rational-function
)
656 number-or-rational-function
)
657 ((and (listp number-or-rational-function
)
658 (listp (setq tem
(car number-or-rational-function
)))
659 (eql (car tem
) 'mrat
))
660 (cdr number-or-rational-function
))
661 (t (fsignal "not right type"))))
663 (defun type-ii-simp (from-deg to-deg
&aux old-simps new-repl tem tem1 a b c
)
664 "checks overlaps of type (a b c) where a.b is a dotsimp and b.c is a modsimp and deg(a.b.c)<=i
665 then replacement(a.b).c is a module relation to be added."
666 (declare (special present-deg
))
667 (setq old-simps
(setq $module_simplifications
(sort-simps-by-degree $module_simplifications
)))
668 (loop for i from from-deg to to-deg do
671 (loop for
(mon repl
) on
(cdr $dot_simplifications
) by
#'cddr do
672 (loop for
(monmod repmod
) on
(cdr old-simps
) by
#'cddr
673 when
(setq tem
($find_right_lap mon monmod i
))
675 ;;(show (list mon monmod))
677 ;;(setq tem (list mon monmod i)) ;but only maximal overlaps need to be checked and since we go up in degree
678 (setq tem1
(cons mon monmod
))
679 (cond ((not (member tem1
*module-overlaps-checked
* :test
#'equal
))
680 (push tem1
*module-overlaps-checked
*)
681 (iassert (nc-equal (ncmul* (first tem
) (second tem
)) mon
))
682 (iassert (nc-equal (ncmul* (second tem
) (third tem
)) monmod
))
683 (iassert (nc-equal ($nc_degree
(ncmul* mon
(third tem
))) i
))
684 (iassert (not (numberp (second tem
))))
685 ;;(setq mod-prod (n. (first tem)(function-numerator repmod)))
686 ;;(setq new-repl (n- (n. (function-numerator repl) (third tem)) mod-prod))
687 ;; rep.c - a.repmod is in the ideal defining the module!
689 (setq new-repl
(n- (n.
(ratl-function-id repl
) c
)
690 (n. a
(ratl-function-id repmod
))))
691 (setq new-repl
(dotsimp new-repl
))
692 (setq new-repl
(function-numerator new-repl
))
693 (setq new-repl
(function-numerator (module-simp new-repl
)))
695 (mapcar #'displa
(make-simp new-repl
))
696 (cond ((pzerop new-repl
) nil
)
697 (t (return-from sue
(values (append old-simps
(make-simp new-repl
)) t
)))))))))
698 finally
(return (values old-simps nil
))))
700 ;(defun type-II-simp ( to-deg &aux old-simps new-repl repl-data tem)
701 ; (setq old-simps (setq $module_simplifications (sort-simps-by-degree $module_simplifications)))
702 ; (loop for (mon repl) on (cdr $dot_simplifications) by #'cddr
703 ; when (setq repl-data (module-monom-must-replacep mon))
704 ; do (cond ((not (member (setq tem (cons mon (car repl-data))) *module-overlaps-checked*))
705 ; (push tem *module-overlaps-checked*)
706 ; (setq new-repl (n. (dot-right-quotient mon (car repl-data)) (apply 'make-relation repl-data)))
707 ; (setq new-repl (cadr (new-rat-dotsimp new-repl)))
708 ; (return (values (append old-simps (make-simp new-repl))
710 ; finally (return (values old-simps nil))))
712 ;(let (($module_simplifications)(*module-overlaps-checked*))
713 ; (loop for v in (st-rat #$[x,-(y.z+x.x)]$)
714 ; do (plain-add-to-module-simps v))
715 ; ( simplify-module-simps))
717 (defun fake-header (form)
719 ((affine-polynomialp form
)(cons *fake-rat
* (cons form
1)))
720 ((rational-functionp form
) (cons *fake-rat
* form
))
721 (t (fsignal "not poly or rat'l fun"))))
722 (defun $modsimp
(form)
723 (cond ((atom form
)(fake-header (module-simp (new-rat form
))))
724 ((or (affine-polynomialp form
)
725 (rational-functionp form
))
726 (fake-header (module-simp form
)))
727 ((mbagp form
)(cons (car form
) (mapcar '$modsimp
(cdr form
))))
728 (t (fake-header (module-simp (new-rat form
))))))
730 (defun $cyclic_module_basis
(degree &optional
(variables $current_variables
) )
731 (cyclic-module-basis variables degree
($replacements
) ($module_replacements
)))
733 (defun $module_replacements
( &optional
(module-simps $module_simplifications
))
734 (cons '(mlist) (loop for
(mon rep
) on
(cdr module-simps
) by
#'cddr
737 (defremember cyclic-module-basis
(variables deg dot-replacements module-replacements
&aux tem
)
739 (cond ((not (or (member 1 dot-replacements
:test
#'equal
)
740 (member 1 module-replacements
:test
#'equal
)))
745 (loop for v in
(cdr variables
)
747 (loop for w in
(cdr (cyclic-module-basis variables
(1- deg
) dot-replacements module-replacements
))
748 do
(setq tem
(ncmul* v w
))
749 unless
(or (module-monom-must-replacep tem
) ($must_replacep tem
))
753 (defun $module_dimensions
(to-n &optional
(variables $current_variables
) &aux tem
)
754 (loop for i from
0 to to-n
755 collecting
(setq tem
($length
($cyclic_module_basis i variables
))) into dims
757 do
(format t
"~%The dimension of the cyclic module in deg ~A is ~A." i tem
)
758 finally
(format t
"~%The total dimension through degree ~A is ~A." to-n tot
)
759 (return (cons '(mlist) dims
))))
762 (defun $set_up_module_simplifications
(relations &optional to-deg
)
763 (setq $module_simplifications nil
)
764 (setq *module-overlaps-checked
* nil
)
765 (loop for v in
(st-rat relations
) do
766 (plain-add-to-module-simps v
))
768 (simplify-module-simps to-deg
)))
769 $module_simplifications
)
771 (defun $cyclic_module_basis
(deg &optional
(variables $current_variables
))
772 (cons '(mlist) (loop for v in
(cdr ($mono variables deg
))
773 when
(not (module-monom-must-replacep v
))
776 (defun $shift_sequence
(seq n
&aux
(tem (make-list (abs n
) :initial-element
0)))
777 "shifts a sequence of degrees over by n to use for adding to check sums"
778 (cond ((zerop n
) seq
)
780 (append ($rest seq n
) tem
))
781 (t ($append
(cons '(mlist) tem
) ($rest seq n
)))))
783 (defun $euler_sum
(deg-seq size-of-module map-degs
)
784 (loop for v in
(reverse (cdr map-degs
))
785 for s in
(cdr size-of-module
)
791 do
(setq ans
(add* ans
(mul* s
($shift_sequence deg-seq
(- tot
)))))
792 else do
(setq ans
(sub* ans
(mul* s
($shift_sequence deg-seq
(- tot
)))))
793 finally
(return ans
)))
795 (defun $solve_sp
(try eqns
&aux simp syst solns ld
)
796 (setq eqns
($sublis try eqns
))
797 (setq ld
(make-ldata :eqns
(mapcar 'function-numerator
(st-rat eqns
))))
799 (setq simp
(simplify-ldata ld
))
801 (setq syst
(loop for u in simp collecting
(cons '(mlist) (mapcar 'new-disrep
(ldata-eqns u
)))))
802 (setq solns
(loop for v in syst collecting
($append try
($fast_linsolve v
($list_variables v
)))))
803 (cons '(mlist) solns
))
806 (defun $nc_linear_factor
(pol &aux answ
(deg ($nc_degree pol
)) lin fac2 result eqns solns general
)
807 (setq lin
($scalar_sum
'$bb
($mono $current_variables
1)))
808 (setq fac2
($scalar_sum
'$cc
($mono $current_variables
(- deg
1))))
809 (setq result
(sub* pol
(ncmul* lin fac2
)))
810 (setq result
($dotsimp result
))
811 (setq eqns
($extract_linear_equations
(list '(mlist) result
)))
817 (format t
"~%Supply a macsyma list of possible solns")
818 (setq try
(mread-noprompt))
820 (setq solns
($solve_sp try eqns
))
822 (setq solns
($ratsimp solns
))
823 (cond ((null (y-or-n-p "Try again?"))
824 (setq general
(list '(mlist) lin fac2
))
825 (return (cons '(mlist) (loop for v in
(cdr solns
)
826 appending
(cdr ($separate_parameters
($sublis v general
) "bb" "cc" "par")))))))))
827 (cond((y-or-n-p "Verify factors:?")
828 (loop for v in
(cdr answ
)
831 do
(setq simp
($dotsimp
(sub* pol
(ncmul* (meval*(second v
)) (meval* (third v
))))))
832 (cond ((pzerop simp
)(format t
"~%soln ~A is correct:" i
)
833 (displa (list '(mequal) pol
(cons '(mnctimes) (cdr v
) ))))
834 (t(format t
"~%soln ~A is not correct ****************"))))))
837 (defun $degless
(u v
&aux
(u-deg ($nc_degree u
)) (v-deg ($nc_degree v
)))
838 (cond ((< u-deg v-deg
))
839 ((eql u-deg v-deg
) (funcall $order_function u v
))