1 /* CharSets Version 1.0 (December 1990) */
2 /* CharSets Version 1.1 (January 1992) for Maple V */
3 /* CharSets Version 1.2 (January 1994) for Maple V.2 */
4 /* CharSets Version 2.0 (February 1996) for Maple V.3 */
5 /*#################################################################### */
7 /* CHARACTERISTIC SETS PACKAGE # */
9 /* Author: Dongming Wang # */
10 /* Laboratoire LEIBNIZ # */
11 /* Institut IMAG, 46, avenue Felix Viallet # */
12 /* 38031 Grenoble Cedex, France # */
13 /* E-mail: Dongming.Wang@imag.fr # */
15 /* Date: February 1996 # */
17 /* Copyright (C) 1990-1996 by Dongming Wang # */
19 /* Copyright Notice: Permission is granted to use, copy or re- # */
20 /* distribute this package, provided that the title is # */
21 /* retained and the file is not altered. # */
23 /*#################################################################### */
24 /*===================================================================# */
25 /* This package is implemented for computing characteristic sets # */
26 /* of (multivariate) polynomial sets, decomposing polynomial sets # */
27 /* into ascending sets and irreducible ascending sets, decomposing # */
28 /* algebraic varieties into irreducible components, decomposing # */
29 /* polynomial ideals into primary components, factorizing # */
30 /* polynomials over algebraic extension fields and solving systems # */
31 /* of polynomial equations. It is based on the method of charac- # */
32 /* teristic sets introduced by J. F. Ritt and developed by Wu Wen- # */
33 /* tsun. The algorithms with variants implemented here are on the # */
34 /* basis of a generalization given by this author. Other modifica- # */
35 /* tions are also made. For references, see # */
36 /* Ritt J. F. Differential Algebra. AMS, 1950. # */
37 /* Wang D. M. Characteristic Sets and Zero Structure of Polynomial # */
38 /* Sets. Lecture Notes, RISC-LINZ, 1989. # */
39 /* Wu W. T. Basic Principles of Mechanical Theorem Proving in # */
40 /* Elementary Geometries. J. Sys. Sci. & Math. Scis. 4 (1984) # */
41 /* 207-235; J. Automated Reasoning 2 (1986) 221-252. # */
42 /*===================================================================# */
43 /* 1st change on May 29, 1991 */
44 /* 2nd change on September 22, 1991 */
45 /* 3rd change in December 1991 */
46 /* 4th change in May 1992 */
47 /* 5th change in October 1993 */
48 /* 6th change in January 1994 */
49 /* 7th change in April 1994 */
50 /* 8th change in April 1995 */
51 /* 9th change in August 1997 (for maxindset) */
52 /* 10th change in February 1998 (for class and lvar) */
53 /* Translated into macsyma by Dan Stanger */
54 /* Info for maxima implementation: */
55 /* Do not create variables with the name args, until the argument name */
58 load ("charsets_set.lisp");
59 load ("charsets_flatten.lisp");
60 load ("charsets_powers.lisp");
61 load ("charsets_length.lisp");
65 define_variable(charsets_printlevel,0,any)$
66 define_variable(charsets_qs,true,any,"Used as array")$
67 define_variable(charsets_fact,1,any,"Stores a factor")$
68 define_variable(charsets_ListOrSet,["[",set],any,"Used by charsets_operatorp")$
70 charsets_operatorp (e, l) :=
71 if atom(e) then false else operatorp (e, l);
74 define_variable(charsets_basset,[],any)$
75 define_variable(charsets_brank,[],any)$
76 define_variable(charsets_fwcharsetn,[],any)$
77 define_variable(charsets_wcharsetn,[],any)$
78 define_variable(charsets_con,[],any)$
79 define_variable(charsets_fqcharsetn,[],any)$
80 define_variable(charsets_wbasset,[],any)$
81 define_variable(charsets_die,[],any)$
84 /*#### Part 0. Definition of User Functions ##### */
85 /* set of non-zero remainders of polys in ps wrt ascending set as */
86 /* user level function */
88 primpart(e,x):=part(content(e,x),2)$
90 /* This function is true if x is a name in the maple sense */
91 namep(x):=is(symbolp(x) or subvarp(x))$
92 /* This function is used to debug charsets_setify */
93 setify1(x):=if listp(x) then charsets_setify(x) else charsets_setify([x])$
95 /* This is no more necessary, charsets_set.lisp has been fixed */
96 /* charsets_union([x]):=listify(apply(union, maplist(lambda([y],setify(expand(y))),x)))$ */
98 /* This macro is used to deconstruct a list of 2 elements */
99 ml2(u,v,l)::=buildq([u,v,l],
100 (block([ml2_temp:l],u:first(ml2_temp),v:second(ml2_temp))))$
101 ml3(u,v,w,l)::=buildq([u,v,w,l],(block([ml3_temp:l],
102 u:first(ml3_temp),v:second(ml3_temp),w:third(ml3_temp))))$
103 /* This function is used when there is a possibility that lcoeff could be
106 if mapatom(p) then p /* what should lcoeff(x,y) be */
108 if "-" = op(p) then -lcoeff(-p,v)
110 if "*" = op(p) then safeLcoeff(first(p),v)*safeLcoeff(rest(p),v)
113 /* this function is used to set up the charsets_qs variable */
114 init_qs(ord):=block([l:length(ord)],
115 if true = member(charsets_qs,arrays) then block([cl],
116 cl:first(third(arrayinfo(charsets_qs))),
117 if cl # l then array(charsets_qs,l))
118 else array(charsets_qs,cl:l))$
120 /* this function is used to return the length of the charsets_qs variable */
121 length_qs():= first(third(arrayinfo(charsets_qs)))$
122 /* this function is used to flatten the charsets_qs array */
123 flatten_qs(i,j):=block([o:[]],
125 if listp(charsets_qs[ii]) then o:append(o,charsets_qs[ii])
126 else o:endcons(charsets_qs[ii])),
130 charsets_remset ( ps,as,ord):= block(
132 if length ( ps) < 1 or length ( as) < 1 then (
133 error ("no polynomials specified"))
134 else if length ( ord) < 1 then (
135 error ("no indeterminates specified"))
136 else if not listp(ord) then (
137 error (ord, "must be a list")),
138 if not every(map(namep, ord))
140 error ("bad variable list")),
142 for i : 1 thru length ( as) do
143 if charsets_class ( as[i], ord) <= _ind
145 error ("second argument must be a non-contradictory (weak-, quasi-) ascending set"))
147 _ind : charsets_class ( as[i], ord)),
148 if charsets_operatorp(ps, charsets_ListOrSet)
150 if not every(map(lambda([p],polynomialp(p,ord,'ratnump)),ps))
152 not every(map(lambda([p],polynomialp(p,ord,'ratnump)),as))
154 error ("input must be polynomials over Q in", ord)),
155 charsets_remseta ( ps, as, ord))
157 if not every(map(lambda([p],polynomialp(p,ord,'ratnump)),as))
159 error ("input must be polynomials over Q in", ord)),
160 charsets_premas ( ps, as, ord))
162 /* the char set of poly set ps: user function */
164 charsets_charset ( ps,lst,[args]):= block( [ mset,ord,qs,y],
165 if length ( ps) < 1 then ( error ("no polynomials specified"))
166 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
167 else if 2 < length(args) then ( error ("too many arguments")),
168 if not every(map(namep, lst)) then ( error ("bad variable list")),
169 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
170 error ("input must be polynomials over Q in", lst)),
171 qs : charsets_setdifference( setify1(charsets_expand( ps)), setify1([ 0 ])),
172 /* sort qs to try to get it in the same order as maple for testing */
173 qs : sort(qs, charsets_setorderp),
174 if listp(lst) then ( ord : lst)
175 else ( ord : charsets_reorder ([ lst ], charsets_degord, qs)),
176 if length(args) = 0 then (mset:charsetn, y:ord)
177 else if length(args) = 1 then (mset:first(args), y:ord)
178 else if length(args) = 2 then (mset:first(args), y:second(args)),
179 if member(mset, setify1([charsetn, wcharsetn, qcharsetn, wbasset, qbasset,
180 triset, trisetc, basset ])) then (
181 charsets_charseta( qs, ord, concat(charsets_,mset)))
183 error ("medial set must be one of `basset`,`wbasset`, `qbasset`, `charsetn`,`wcharsetn`,`qcharsetn`,`triset` and `trisetc`"))
186 /* modified from expand for lists */
187 charsets_expand ( s) :=block(
189 then (maplist(expand,s))
190 else if charsets_setp(s) then (
191 apply(setify1,maplist(expand,s)))
195 /* the modified char set of poly set ps: user function */
197 charsets_mcharset ( ps,lst,[args]):= block( [ mset,ord,qs,y],
198 if length ( ps) < 1 then ( error ("no polynomials specified"))
199 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
200 else if 2 < length(args) then ( error ("too many arguments")),
201 if not every(map(namep, lst)) then (error ("bad variable list")),
202 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
203 error ("input must be polynomials over Q in", lst)),
204 qs : charsets_setdifference ( setify1(charsets_expand ( ps)), setify1([ 0 ]) ),
205 /* sort qs to try to get it in the same order as maple for testing */
206 qs : sort(qs, charsets_setorderp),
207 if listp(lst) then ( ord : lst)
208 else ( ord : charsets_reorder ( (lst), charsets_degord, qs)),
209 if length(args) = 0 then (mset:charsetn, y:ord)
210 else if length(args) = 1 then (mset:first(args), y:ord)
211 else if length(args) = 2 then (mset:first(args), y:second(args)),
212 if member(mset, setify1([ charsetn, wcharsetn, qcharsetn, wbasset,
213 qbasset, triset, trisetc, basset ])) then (
214 charsets_fcharseta ( qs, ord, concat(charsets_,mset)))
215 else ( error ("medial set must be one of `basset`,`wbasset`,`qbasset`,`charsetn`,`wcharsetn`,`qcharsetn`,`triset` and `trisetc`"))
217 /* the set of all nonconstant factors of initials of polys in as: user function */
219 charsets_iniset ( as,ord):=block(
222 if length ( as) < 1 then (
223 error ("no polynomials specified"))
224 else if length ( ord) < 1 then (
225 error ("no indeterminates specified"))
226 else if not listp(ord) then (
227 error (ord, "must be a list")),
228 if not every(map(namep, ord))
230 error ("bad variable list")),
231 if not every(map(lambda([p],polynomialp(p,ord,'ratnump)),as))
233 error ("input must be polynomials over Q in", ord)),
234 for i : 1 thru length ( as) do
235 if charsets_class ( as[i], ord) <= _ind
237 error ("first argument must be a non-contradictory (weak-, quasi-) ascending set"))
239 _ind : charsets_class ( as[i], ord)),
240 charsets_initialset ( charsets_expand ( as), ord)
242 /* the char series of poly set ps: user function */
244 charsets_charser ( ps,lst,[args]):=block( [ mset,ord,qs, y],
245 if length ( ps) < 1 then ( error ("no polynomials specified"))
246 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
247 else if 2 < length(args) then ( error ("too many arguments")),
248 if not every(map(namep, lst)) then ( error ("bad variable list")),
249 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
250 error ("input must be polynomials over Q in", lst)),
251 qs : charsets_setdifference ( setify1(charsets_expand( ps)), setify1([ 0 ]) ),
252 /* sort qs to try to get it in the same order as maple for testing */
253 qs : sort(qs, charsets_setorderp),
254 if listp(lst) then ( ord : lst)
255 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
256 if length(args) = 0 then (mset:charsetn, y:ord)
257 else if length(args) = 1 then (mset:first(args), y:ord)
258 else if length(args) = 2 then (mset:first(args), y:second(args)),
259 if member(mset,setify1([charsetn,wcharsetn,wbasset,trisetc,basset])) then (
260 charsets_charseries ( qs, ord, concat(charsets_,mset)))
262 error ("medial set must be one of 'basset','wbasset', 'charsetn','wcharsetn' and 'trisetc'"))
264 /* the char series of poly set ps -- allowing to remove factors */
267 charsets_mcs ( ps,lst,[args]):=block(
269 if length ( ps) < 1 then (
270 error ("no polynomials specified"))
271 else if length ( lst) < 1 then (
272 error ("no indeterminates specified"))
273 else if 2 < length(args) then (
274 error ("too many arguments")),
275 if not every(map(namep, lst))
277 error ("bad variable list")),
278 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps))
280 error ("input must be polynomials over Q in", lst)),
281 qs : charsets_setdifference ( setify1([ (charsets_expand ( ps)) ]), setify1([ 0 ]) ),
286 ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
287 if length(args) = 0 then (mset:charsetn, y:ord)
288 else if length(args) = 1 then (mset:first(args), y:ord)
289 else if length(args) = 2 then (mset:first(args), y:second(args)),
290 if member(mset, setify1([ charsetn, wcharsetn, wbasset, trisetc, basset ]))
292 charsets_fcharser ( qs, ord, concat(charsets_,mset)))
294 error ("medial set must be one of 'basset','wbasset', 'charsetn','wcharsetn' and 'trisetc'"))
296 /* the extended char series of poly set ps */
299 charsets_ecs ( ps,lst,[args]):=block( [ mset,ord,qs,y],
300 if length ( ps) < 1 then ( error ("no polynomials specified"))
301 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
302 else if 2 < length(args) then ( error ("too many arguments")),
303 if not every(map(namep, lst)) then ( error ("bad variable list")),
304 if listp(ps[1]) then (
305 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps[1])) then (
306 error ("input must be polynomials over Q in", lst)))
307 else if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
308 error ("input must be polynomials over Q in", lst)),
309 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
310 qs:[charsets_setdifference(setify1(charsets_expand(ps[1])),setify1([0])),ps[2]])
312 qs : charsets_setdifference (setify1(charsets_expand ( ps)),setify1([ 0 ]))),
313 if listp(lst) then ( ord : lst)
315 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
316 ord : charsets_reorder ( [ (lst) ], charsets_degord, qs[1]))
317 else ( ord : charsets_reorder ( lst, charsets_degord, qs))),
318 if length(args) = 0 then (mset:charsetn, y:ord)
319 else if length(args) = 1 then (mset:first(args), y:ord)
320 else if length(args) = 2 then (mset:first(args), y:second(args)),
321 if member(mset, setify1([ charsetn, wcharsetn, wbasset, trisetc, basset ]))
323 charsets_excharser ( qs, ord, concat(charsets_,mset)))
325 error ("medial set must be one of 'basset','wbasset', 'charsetn','wcharsetn' and 'trisetc'"))
327 /* the extended char series of poly set ps -- allowing to remove factors */
330 charsets_mecs ( ps,lst,[args]):=block( [ mset,ord,qs,y],
331 if length ( ps) < 1 then ( error ("no polynomials specified"))
332 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
333 else if 2 < length(args) then ( error ("too many arguments")),
334 if not every(map(namep, lst)) then ( error ("bad variable list")),
335 if listp(ps[1]) then (
336 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps[1])) then (
337 error ("input must be polynomials over Q in", lst)))
338 else if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
339 error ("input must be polynomials over Q in", lst)),
340 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
341 qs:[sort(charsets_setdifference(setify1(charsets_expand (ps[1])),setify1([0])),
342 charsets_setorderp),ps[2]])
344 qs : sort(charsets_setdifference(setify1(charsets_expand(ps)), setify1([0])),
345 charsets_setorderp)),
346 if listp(lst) then ( ord : lst)
348 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
349 ord : charsets_reorder ( [ (lst) ], charsets_degord, qs[1]))
350 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs))),
351 if length(args) = 0 then (mset:charsetn, y:ord)
352 else if length(args) = 1 then (mset:first(args), y:ord)
353 else if length(args) = 2 then (mset:first(args), y:second(args)),
354 if member(mset, setify1([ charsetn, wcharsetn, wbasset, trisetc, basset ]))
355 then ( charsets_fexcharser ( qs, ord, concat(charsets_,mset)))
357 error ("medial set must be one of 'basset','wbasset', 'charsetn','wcharsetn' and 'trisetc'"))
359 /* the irreducible char series of poly set ps: user function */
361 charsets_ics ( ps,lst,[args]):=block( [ mset,ord,qs,y],
362 if length ( ps) < 1 then ( error ("no polynomials specified"))
363 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
364 else if 2 < length(args) then ( error ("too many arguments")),
365 if not every(map(namep, lst)) then ( error ("bad variable list")),
366 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
367 error ("input must be polynomials over Q in", lst)),
368 qs : charsets_setdifference( setify1(charsets_expand ( ps)), setify1([ 0 ]) ),
369 if listp(lst) then ( ord : lst)
370 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
371 if length(args) = 0 then (mset:charsetn, y:ord)
372 else if length(args) = 1 then (mset:first(args), y:ord)
373 else if length(args) = 2 then (mset:first(args), y:second(args)),
374 if member(mset, setify1([ charsetn, trisetc, basset ])) then (
375 charsets_irrcharser ( qs, ord, concat(charsets_,mset)))
376 else (error ("medial set must be one of 'basset','charsetn' and 'trisetc'"))
378 /* the extended irreducible char series of poly set ps: user function */
380 charsets_eics ( ps,lst,[args]):=block( [ mset,ord,qs,y],
381 if length ( ps) < 1 then ( error ("no polynomials specified"))
382 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
383 else if 2 < length(args) then ( error ("too many arguments")),
384 if not every(map(namep, lst)) then ( error ("bad variable list")),
385 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
386 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps[1])) then (
387 error ("input must be polynomials over Q in", lst)))
388 else if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
389 error ("input must be polynomials over Q in", lst)),
390 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
391 qs:[sort(charsets_setdifference(setify1(charsets_expand (ps[1])),setify1([0])),
392 charsets_setorderp),ps[2]])
394 qs : sort(charsets_setdifference(setify1(charsets_expand(ps)), setify1([0])),
395 charsets_setorderp)),
396 if listp(lst) then ( ord : lst)
398 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
399 ord : charsets_reorder ( [ (lst) ], charsets_degord, qs[1]))
401 ord : charsets_reorder ( [ (lst) ], charsets_degord, qs))),
402 if length(args) = 0 then (mset:charsetn, y:ord)
403 else if length(args) = 1 then (mset:first(args), y:ord)
404 else if length(args) = 2 then (mset:first(args), y:second(args)),
405 if member(mset, setify1([ charsetn, trisetc, basset ])) then (
406 charsets_exirrcharser(charsets_expand(qs),ord,concat(charsets_,mset)))
408 error("medial set must be one of `basset`, `charsetn` and `trisetc`"))
410 /* the quasi-irreducible char series of poly set ps: user function */
412 charsets_qics ( ps,lst,[args]):=block( [ mset,ord,qs,y],
413 if length ( ps) < 1 then ( error ("no polynomials specified"))
414 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
415 else if 2 < length(args) then ( error ("too many arguments")),
416 if not every(map(namep, lst)) then ( error ("bad variable list")),
417 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
418 error ("input must be polynomials over Q in", lst)),
419 qs : charsets_setdifference ( setify1(charsets_expand ( ps)), setify1([ 0 ]) ),
420 if listp(lst) then ( ord : lst)
421 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
422 if length(args) = 0 then (mset:charsetn, y:ord)
423 else if length(args) = 1 then (mset:first(args), y:ord)
424 else if length(args) = 2 then (mset:first(args), y:second(args)),
425 if member(mset,setify1([charsetn,wcharsetn,wbasset,trisetc,basset])) then (
426 charsets_qirrcharser ( qs, ord, concat(charsets_,mset)))
428 error ("medial set must be one of `basset`,`wbasset`, `charsetn`,`wcharsetn` and `trisetc`"))
430 /* factorize poly f over algebraic number field with minimal polys in as */
431 /* wrt ord: user function */
432 /* used for linear transformation */
434 charsets_cfactor ( f,[args]):=block( [ _ind,inda,ff,i,as,ord,last],
435 if length(args) = 0 then ( return ( factor ( f) )),
436 if length(args) # 2 then ( error ("improper number of arguments"))
437 else (as:first(args),ord:second(args)),
438 if length ( as) < 1 then ( error ("no polynomials specified"))
439 else if length ( ord) < 1 then ( error ("no indeterminates specified"))
440 else if not listp(ord) then ( error (ord, "must be a list"))
441 else if not every(map(namep, ord)) then ( error ("bad variable list"))
442 else if not every(map(lambda([p],polynomialp(p,ord,'ratnump)),as)) then (
443 error ("input must be polynomials over Q in", ord)),
446 for i : 1 thru length ( as) do (
447 inda : charsets_class ( as[i], ord),
448 if inda <= _ind then (
449 error ("second argument must be a non-contradictory ascending set"))
450 else ( _ind : inda)),
451 if 1 < charsets_printlevel then (
452 print("Warning: be sure the ascending set is irreducible")),
453 if charsets_class( ff, ord) <= charsets_class( as[length( as)], ord) then (
456 last:apply("+", maplist( lambda([p],charsets_degreel( p, ord)), as)),
457 charsets_das :if charsets_degreel ( ff, ord) < last then
458 [ -1, 1, -2, 2, -3, false] else [ 1, -1, 2, -2, -3, false],
460 if "-" = op(last) then last:-last,
461 charsets_cfactorsub ( last, as, ord))
463 /* prepare a list of triangular forms from poly set ps: user function */
464 /* I am not sure if I got the argument handling correct */
465 /* In fact the argument handling is incorrect. Either it is triser(ps,ord) */
466 /* where ord is a list, or triser(ps,lst,ord) where lst is the unordered set */
467 /* of variables and ord the order computed by charsets_reorder (lst, charsets_degord, qs) */
468 /* and automatically filled */
470 charsets_triser ( ps,[args]):=block( [ i,ord,qs, lst,y],
471 if length ( ps) < 1 then ( error ("no polynomials specified"))
472 else if 2 < length(args) then ( error ("too many arguments"))
473 else if length(args) >= 1 then (
475 if length ( lst) < 1 then ( error ("no indeterminates specified")),
476 if not every(map(namep, lst)) then ( error ("bad variable list"))),
477 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
478 error ("input must be polynomials over Q in", lst)),
479 qs : charsets_setdifference( setify1(charsets_expand ( ps)), setify1([ 0 ])),
480 if length(args) < 1 then (
481 ord : charsets_reorder ( maplist(listofvars, ps), charsets_degord, qs))
482 else if listp(lst) then ( ord : lst)
483 else ( /* this is never executed? as length(lst) will fail above */
484 ord : charsets_reorder ( lst, charsets_degord, qs)),
485 if length(args) = 1 then y : ord else y:second(args),
486 charsets_trisersub ( qs, ord)
488 /* solve a set of poly eqs ps=0: user function */
489 /* Arg handling is copied from triser */
491 charsets_csolve ( ps,[args]):=block( [ i,ord,qsi,qs, lst,y],
492 if length ( ps) < 1 then ( error ("no polynomials specified"))
493 else if 2 < length(args) then ( error ("too many arguments"))
494 else if length(args) >= 1 then (
496 if length ( lst) < 1 then ( error ("no indeterminates specified")),
497 if not every(map(namep, lst)) then ( error ("bad variable list"))),
498 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
499 error ("input must be polynomials over Q in", lst)),
500 qs : charsets_setdifference( setify1(charsets_expand ( ps)), setify1([ 0 ])),
501 if length(args) < 1 then (
502 ord : charsets_reorder ( maplist(listofvars, ps), charsets_degord, qs))
503 /* else if listp(lst) then ( ord : lst) Needed if sets are not lists */
504 else ( ord : charsets_reorder( lst, charsets_degord, qs)),
505 if length(args) = 1 then y : ord else y:second(args),
506 /* sort to try to get things in maple order */
507 qs : sort (qs, charsets_lenord),
508 qsi : setify1( charsets_trisersub ( qs, ord)),
509 if qsi = setify1(setify1([])) then ( setify1([]))
510 else setify1( maplist(lambda([q],charsets_solveas( q, ord)), qsi))
512 /* irreducible decomposition of algebraic variety defined by ps */
515 charsets_ivd ( ps,lst,[args]):=block( [ mset,ord,qs,y],
516 if length ( ps) < 1 then ( error ("no polynomials specified"))
517 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
518 else if 2 < length(args) then ( error ("too many arguments")),
519 if not every(map(namep, lst)) then ( error ("bad variable list")),
520 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
521 error ("input must be polynomials over Q in", lst)),
522 qs : charsets_setdifference( setify1(charsets_expand ( ps)), setify1([ 0 ]) ),
523 if listp(lst) then ( ord : lst)
524 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
525 if length(args) = 0 then (mset:charsetn, y:ord)
526 else if length(args) = 1 then (mset:first(args), y:ord)
527 else if length(args) = 2 then (mset:first(args), y:second(args)),
528 if member(mset, setify1([ charsetn, trisetc, basset ])) then (
529 charsets_irrvardec ( qs, ord, concat(charsets_,mset)))
531 error ("medial set must be one of `basset`,`charsetn` and `trisetc`"))
533 /* primary decomposition of polynomial ideal generated by ps */
536 charsets_pid ( ps,lst,[args]):=block( [ mset,ord,qs,y],
537 if length ( ps) < 1 then ( error ("no polynomials specified"))
538 else if length ( lst) < 1 then ( error ("no indeterminates specified"))
539 else if 2 < length(args) then ( error ("too many arguments")),
540 if not every(map(namep, lst)) then ( error ("bad variable list")),
541 if not every(map(lambda([p],polynomialp(p,lst,'ratnump)),ps)) then (
542 error ("input must be polynomials over Q in", lst)),
543 qs : charsets_setdifference ( setify1(charsets_expand ( ps)), setify1([ 0 ]) ),
544 if listp(lst) then ( ord : lst)
545 else ( ord : charsets_reorder ( [ (lst) ], charsets_degord, qs)),
546 if length(args) = 0 then (mset:charsetn, y:ord)
547 else if length(args) = 1 then (mset:first(args), y:ord)
548 else if length(args) = 2 then (mset:first(args), y:second(args)),
549 if member(mset, setify1([ charsetn, trisetc, basset ])) then (
550 charsets_pridealdec ( qs, ord, concat(charsets_,mset)))
552 error ("medial set must be one of `basset`, `charsetn` and `trisetc`"))
554 /*#### Part I. Routines for Computing Characteristic Sets ##### */
555 /* the class of poly f wrt variable ordering ord */
557 charsets_class ( f,ord):=block(
559 for i : length ( ord) thru 1 step - 1 do
560 if member(ord[i], listofvars( f))
565 /* the leading variable of poly f wrt variable ordering ord */
567 charsets_lvar ( f,ord):=block([ i,r:0],
568 for i : length ( ord) thru 1 step - 1 do
569 if member(ord[i], listofvars ( f)) then (
571 if r # 0 then return(r),
572 if 1 < charsets_printlevel then (
573 print("Warning: lvar is called with constant")),
576 /* the index set of a poly (or a poly set f) wrt ord */
578 charsets_index( f,ord):=block( [ i,g,ng,O],
580 map(lambda([p],charsets_index( p, ord)), f))
581 else if /* WARNING: listp should be charsets_setp */listp(f) then (
582 apply(setify1,map(lambda([p],charsets_index( p, ord)), f)))
585 ng : charsets_terms ( g),
586 if charsets_class ( g, ord) = 0 then (
587 i : part( [ (listofvars ( g)), O ], 1))
589 i : charsets_lvar ( g, ord)),
593 /* number of terms in g */
595 charsets_terms ( g):=block(
596 if "+" = inpart(g, 0)
600 /* the initial of poly p wrt ord */
602 charsets_initial ( p,ord):=block(
605 if charsets_class ( f, ord) = 0 then 1
607 last:lcoeff ( f, charsets_lvar ( f, ord) ),
608 /* rncombine worked here but is not implemented in maxima */
609 num(xthru(multthru( last / lcoeff ( last,ord)))))
611 /* modified rank of two polys: comparing further the rank */
612 /* of initials when f and g have same rank */
614 charsets_mrank ( f,g,ord):=block(
616 cf : charsets_class ( f, ord),
617 cg : charsets_class ( g, ord),
618 if cf = 0 then ( true)
619 else if cf < cg then ( true)
620 else if cf = cg then (
621 cf : charsets_degreel ( f, ord),
622 cg : charsets_degreel ( g, ord),
623 if cf < cg then ( true)
624 else if cf = cg then (
625 charsets_mrank ( charsets_initial ( f, ord), charsets_initial ( g, ord), ord))
629 /* modified rank of two polys: comparing further the rank of */
630 /* initials, the terms of initials and the terms of f and g */
631 /* when they are the same */
633 charsets_rank ( f,g,ord):=block(
635 ml2(find,_ind, charsets_subrank ( f, g, ord)),
636 if find and _ind = 1 then (
637 cf : charsets_polylength ( expand ( charsets_initial ( f, ord) ) ),
638 cg : charsets_polylength ( expand ( charsets_initial ( g, ord) ) ),
641 else if cf = cg then (
642 if charsets_polylength ( expand ( f) ) < charsets_polylength ( expand ( g) )
648 /* subroutine for rank */
650 charsets_subrank ( f,g,ord):=block(
652 cf : charsets_class ( f, ord),
653 cg : charsets_class ( g, ord),
655 if cg = 0 then (_ind : 1), [true,_ind])
656 else if cf < cg then ( [true,_ind])
657 else if cf = cg then (
658 cf : charsets_degreel ( f, ord),
659 cg : charsets_degreel ( g, ord),
660 if cf < cg then ( [true,_ind])
661 else if cf = cg then (
662 charsets_subrank ( charsets_initial ( f, ord),
663 charsets_initial ( g, ord), ord))
664 else ( [false,_ind]))
667 /* the rank of two polys with same classes: */
668 /* used for computing tiangular form */
670 charsets_trank ( f,g,ord):=block(
672 cf : charsets_degreel ( f, ord),
673 cg : charsets_degreel ( g, ord),
678 else if cf = cg then (
679 charsets_mrank ( charsets_initial ( f, ord), charsets_initial ( g, ord), ord))
683 /* modified pseudo division: I1^s1...Ir^sr*uu = q*vv + r, */
684 /* where I1, ..., I_r are all distinct factors of lcoeff(vv,x) */
685 /* and s1, ..., sr are chosen to be the smallest */
686 charsets_prem( uu,vv,x):=block(
687 if charsets_operatorp(vv,charsets_ListOrSet) = true then (
688 if length(vv) > 1 then error("charsets_prem length vv > 1, not implemented", vv)
690 if charsets_operatorp(uu,charsets_ListOrSet) = true then
691 map(lambda([u],charsets_prem1(u,vv,x)),uu)
693 charsets_prem1(uu,vv,x)
695 charsets_prem1( uu,vv,x):=block( [ r,v,dr,dv,l,t,lu,lv,g,di],
696 if integerp(vv / x) then ( subst(x = 0,uu))
704 v : expand ( v - l * x ^ dv))
706 if 1 < charsets_printlevel and 500 < length ( r) + length ( v) then (
707 print("pseudo-division:",[length(r),x,dr], [ length ( v), x, dv ])),
708 while (dv <= dr and r # 0) do (
709 g:gcd ( lu:l, lv:coeff(r,x,dr)),
710 lu:first(di:divide(lu,g)),
711 if second(di) # 0 then error("prem1 divide by gcd yielded remainder!",
713 lv:first(di:divide(lv,g)),
714 if second(di) # 0 then error("prem1 divide by gcd yielded remainder!",
716 t : expand ( x ^ ( ( dr - dv)) * v * lv),
717 if dr = 0 then ( r : 0)
718 else ( r : subst(x ^ dr = 0, r)),
719 r : expand ( lu * r) - t,
720 dr : degree ( r, x)),
723 /* pseudo remainder of poly f wrt ascending set as */
725 charsets_premas ( f,as,ord):=block([ remd,i],
727 for i : length ( as) thru 1 step - 1 do
728 remd : charsets_prem ( remd, as[i], charsets_lvar ( as[i], ord) ),
729 if remd # 0 then ( num(xthru(multthru( remd / lcoeff( remd,/* reverse */(ord))))))
732 /* set of non-zero remainders of polys in ps wrt ascending set as */
734 charsets_remseta ( ps,as,ord):=block([retval],
735 retval:sort(charsets_setdifference (
736 setify1(maplist(lambda([p],charsets_premas( p, as, ord)),ps)),
737 setify1([ 0 ])),charsets_setorder_reversep),
740 /* pseudo remainder of poly f wrt ascending set as -- version b */
742 charsets_premasb ( f,as,ord):=block(
745 if 1 < length ( as) then (
746 for i : length ( as) thru 2 step - 1 do
747 remd : charsets_prem ( remd, as[i], charsets_lvar ( as[i], ord))),
748 l:divide ( remd, primpart(as[1],charsets_lvar(as[1],ord))),
749 if first(l)=0 then ( remd : 0)
750 else ( remd : charsets_prem ( remd, as[1], charsets_lvar ( as[1], ord))),
751 if remd # 0 then ( num(xthru(multthru( remd / lcoeff( remd,/* reverse */(ord))))))
754 /* set of non-zero remainders of polys in ps wrt ascending set as -- version b */
756 charsets_remsetb ( ps,as,ord):=block([last],
757 last:maplist(lambda([p],charsets_premasb( p, as, ord)),ps),
758 charsets_setdifference( setify1(if listp(last) then last else [last]),setify1([0]))
760 /* reorder the list ord of variables wrt poly set ps */
762 charsets_reorder ( ord,p,ps):=block([last],
763 last:charsets_reordera ( ord, ps),
764 append(charsets_reorderb(charsets_setdifference(setify1(ord),setify1(last)),p,ps),
767 /* subroutine for reorder: first criterion */
769 charsets_reordera ( ord,ps):=block([ qs,pp,orb,i,last],
770 if length ( ps) = 0 then ( ord)
773 qs : setify1([ (ps) ]),
774 orb : setify1([ (ord) ]),
776 pp : charsets_deg0 ( ps, i),
777 if length ( pp) = 1 then (
778 return (last:cons(i,charsets_reordera(charsets_setdifference(orb,setify1(i)),
779 charsets_setdifference( qs, pp) ))))),
783 /* subroutine for reorder -- modified from sort: second criterion */
784 /* local works in maxima, but not in macsyma */
785 charsets_reorderb ( l,p,ps):=block([ n,tn,gap,ggap,i,j,temp,v],
789 for i : 1 thru n do v[i - 1] : l[i],
790 for ggap:(gap:4) while ggap <= n do (gap:(ggap : 3*ggap+1)),
791 gap : quotient( gap, 3),
793 for i : gap thru n - 1 do (
797 if tn ( v[j], temp, ps) then return(true),
803 gap : quotient( gap, 3)
805 temp:makelist(v[i],i,0,n-1),
808 /* determine the order between x and y wrt ps */
810 charsets_degord ( x,y,ps):=block(
811 if part(charsets_degpsmax(ps,y),2) < part(charsets_degpsmax(ps,x),2)
813 else if part(charsets_degpsmax(ps,x),2) < part(charsets_degpsmax(ps,y),2)
815 else if part(charsets_degpsmax(ps,y),1) < part(charsets_degpsmax(ps,x),1)
817 else if part(charsets_degpsmax(ps,x),1) < part(charsets_degpsmax(ps,y),1)
819 else if part(charsets_degpsmin(ps,x),2) < part(charsets_degpsmin(ps,y),2)
821 else if part(charsets_degpsmin(ps,y),2) < part(charsets_degpsmin(ps,x),2)
823 else if part(charsets_degpsmin(ps,y),1) < part(charsets_degpsmin(ps,x),1)
825 else if part(charsets_degpsmin(ps,x),1) < part(charsets_degpsmin(ps,y),1)
827 else if part(charsets_deg1(ps,y),1) < part(charsets_deg1(ps,x),1) then true
828 else if part(charsets_deg1(ps,x),1) < part(charsets_deg1(ps,y),1) then false
829 else if part(charsets_deg1(ps,y),2) < part(charsets_deg1(ps,x),2) then true
832 /* the maximal degree of polys in qs wrt x */
833 /* and the number of polys having this degree */
835 charsets_degpsmax ( qs,x):=block(
837 /* Is this charsets_expand? */
839 m : apply(max,maplist(lambda([p],degree(p, x)),ps)),
841 for i : 1 thru length ( ps) do
842 if degree ( ps[i], x) = m then ( mm : mm + m),
845 /* the minimal non-zero degree of polys in qs wrt x */
846 /* and the number of polys having this degree */
848 charsets_degpsmin ( qs,x):=block( [ i,m,mm,ps,last],
850 last:charsets_setdifference( setify1(map(lambda([p],degree( p, x)),ps)),
852 if last = setify1([]) then ( m : 0)
853 else m : apply(min, last),
855 for i : 1 thru length ( ps) do
856 if degree ( ps[i], x) = m then ( mm : mm + m),
859 /* determine if ps has one and only one poly involving x */
861 charsets_deg0 ( ps,x):=block( [ i,ms],
864 if length( ms) >= 2 then return(false),
865 if member(x, listofvars( i)) then ms : charsets_adjoin2( i, ms)),
868 /* the minimal total degree of lcoeffs of polys in PS wrt x */
869 /* and the minimal number of terms of those lcoeffs */
870 /* I think this function was memoized */
872 charsets_deg1 ( _PS,x):=block( [ i,ps,qs,k],
875 k : part( charsets_degpsmin( ps, x), 2),
876 for i : 1 thru length ( ps) do (
877 if degree( ps[i], x) = k then qs : charsets_adjoin2(lcoeff( ps[i], x),qs)),
878 [ apply(min, maplist(lambda([u],degree( u, listofvars( u))),qs)),
879 apply(min, maplist(lambda([u],charsets_polylength( expand (u))),qs))]
881 /* search an element with lowest rank in ps */
882 /* and assign the rest of polys to qs */
884 charsets_sort ( ps,theRankFunction,ord):=block(
886 if length ( ps) = 1 then ( [ps[1],[]])
890 for i : 2 thru length ( ps) do
891 if theRankFunction( ps[i], l, ord)
896 qs : cons( ps[i], qs)),
899 /* the difference of two lists */
901 charsets_minus ( ps,qs):=block(
902 charsets_setdifference ( setify1(ps), setify1(qs))
904 /* the product of all elements in a list */
906 charsets_prod ( ps):=block( [ i],
907 product ( ps[i], i, 1, length ( ps) )
909 charsets_degree ( f,x):=block([c:facsum( f, x)],
910 if mapatom(x) then charsets_degree(c,[x]),
911 if listp(f) then lmax(maplist(lambda([u],degree(u,x)),c))
912 else charsets_degree([f],x)
914 charsets_degreel ( f,ord):=block([last],
916 degree ( last, charsets_lvar ( last, ord) )
918 /* the macro which creates the set functions */
919 makeBasicSetFunction(theName,theRank)::=buildq([theName,theRank],
920 theName( ps,ord):=block([ qs,qs1,i,b],
921 if length ( ps) < 2 then ( ps)
923 ml2(b,qs1, charsets_sort ( ps, charsets_rank, ord)),
925 if 0 < charsets_class ( b, ord) then (
927 if theRank( i, b, ord) then (
931 cons( b, theName( qs, ord)))
933 /* the basic set of poly set ps */
934 makeBasicSetFunction(charsets_basset,charsets_brank)$
935 /* the weak-basic set of poly set ps */
936 makeBasicSetFunction(charsets_wbasset,charsets_wbrank)$
937 /* the quasi-basic set of poly set ps */
938 makeBasicSetFunction(charsets_qbasset,charsets_qbrank)$
939 /* subroutines for basset, wbasset and qbasset */
941 charsets_brank ( a,b,ord):=block(
942 if charsets_degree( a, charsets_lvar( b, ord)) < charsets_degreel( b, ord)
947 charsets_wbrank ( a,b,ord):=block(
948 if charsets_class( b, ord) < charsets_class( a, ord) and
949 charsets_brank ( charsets_initial ( a, ord), b, ord) then ( true)
953 charsets_qbrank ( a,b,ord):=block(
954 if charsets_class( b, ord) < charsets_class( a, ord) then true else false
957 /* the char set of poly set ps */
958 /* add univariate gcd on May 5, 2000 */
959 charsets_charseta ( ps,ord,medset):=block(
961 if length ( ps) < 2 then (ps)
963 ps:charsets_unigcd(ps,ord),
964 if medset = charsets_qcharsetn then (
965 charsets_with : setify1([]),
966 cs : charsets_qcharsetn ( ps, ord, charsets_remsetaA))
967 else ( cs : medset ( ps, ord)),
968 if 0 < charsets_class ( cs[1], ord) then (
969 if member(medset,setify1([charsets_wbasset,charsets_qbasset,
970 charsets_basset])) then (
971 rs:charsets_remseta(charsets_setdifference(setify1(ps),setify1(cs)),cs,ord))
972 else if medset = charsets_qcharsetn and charsets_checkwith(
973 charsets_with, charsets_initialset1 ( cs, ord) ) then (
974 if 1 < charsets_printlevel then (
975 print("Strategy for 0 remainder succeed")),
978 if medset = charsets_qcharsetn and 1 < charsets_printlevel then (
979 print("Strategy for 0 remainder failed")),
980 block([temp:charsets_canonlt,sd],
981 charsets_canonlt:charsets_setorder_reversep,
982 sd:charsets_setdifference(
983 setify1(if listp(ps) then ps else [ps]),
984 setify1(if listp(cs) then cs else [cs])),
985 sd:sort(sd,lambda([x,y],not charsets_lenord(x,y))),
986 rs : charsets_remsetb( sd, cs, ord),
987 charsets_canonlt:temp
991 if rs = setify1([]) then (
992 changesign(maplist(lambda([c],num(c/lcoeff(expand(c),/* reverse */(ord)))),cs)))
993 else charsets_charseta( charsets_union( rs, cs, ps), ord, medset))
996 changesign(l):=block([i],
997 i:read("changesign 0 or item #"),
998 if i # 0 then l[i]:-l[i],
1002 charsets_unigcd(PS,ord):=block([_ps,p,c],
1003 _ps :charsets_setify([]),
1005 c : charsets_class(p,ord),
1006 if c = 0 then return(charsets_setify([1]))
1007 else (if c = 1 then _ps : charsets_union(_ps, charsets_setify( [p])))
1009 if length(_ps) < 2 then PS
1010 else charsets_union(charsets_setdifference(PS,_ps), setify1(apply(charsets_GCD,_ps)))
1013 charsets_GCD([args]) :=
1014 if length(args) = 2 then apply('gcd,args)
1015 else gcd(first(args),apply(charsets_GCD(rest(args))))$
1017 /* the modified char set of poly set ps */
1019 charsets_fcharseta ( ps,ord,medset):=block(
1021 ml2(csf,fset, charsets_fcharsetsub ( charsets_nopower ( ps), ord, medset,
1022 [ setify1([]), listofvars ( ps) ])),
1023 [csf,factors_removed:fset[1]]
1026 /* the main subroutine for fcharseta */
1027 /* add univariate gcd and change removecont on May 5, 2000 */
1028 define_variable(charsets_fcharsetsub_alist,
1029 maplist(lambda([x], concat(charsets_,x)=concat(charsets_f,x)),
1030 [charsetn, wcharsetn, qcharsetn, triset, trisetc]),any_check,
1031 "Used to convert medset to fmedset, BTW any_check didnt work")$
1033 charsets_fcharsetsub ( _ps,ord,medset,fset1):=block(
1034 [ ps,cs,rs,l,fset3,fset2,ts,fmedset,med,fset,last],
1035 if length ( _ps) < 2 then ( [_ps,fset1])
1037 ps : charsets_unigcd(_ps,ord),
1038 fmedset:assoc(medset,charsets_fcharsetsub_alist),
1039 if fmedset # false then (
1040 if fmedset = charsets_fqcharsetn then (
1041 charsets_with : setify1([]),
1042 ml2(cs,fset2,charsets_fqcharsetn(ps, ord, fset1, charsets_remsetaA))
1044 else (ml2(cs,fset2, fmedset ( ps, ord, fset1))),
1045 last:if length( cs) > 1 then cs[1] else [],
1046 if 0 < charsets_class ( last, ord) then (
1047 if fmedset = charsets_fqcharsetn and
1048 charsets_checkwith ( charsets_with,
1049 charsets_union ( charsets_initialset1 ( cs, ord), fset2[1])) then (
1050 if 1 < charsets_printlevel then (
1051 print("Strategy for 0 remainder succeed")),
1052 return ( [cs,fset2]))
1054 if medset = charsets_qcharsetn and 1 < charsets_printlevel then (
1055 print("Strategy for 0 remainder failed")),
1056 rs : charsets_remsetb(charsets_setdifference(setify1(ps),setify1(cs)),
1059 return ( [[ 1 ],fset2] )),
1060 if rs = setify1([]) then (
1061 [map(lambda([c],num(c/lcoeff(expand(c),/* reverse */(ord)))),cs),fset2])
1063 charsets_fcharsetsub(charsets_union(rs,cs, ps),ord,medset,fset2)))
1065 if medset = [] then cs: ps else cs : medset ( ps, ord),
1066 fset2 : [ fset1[1], charsets_union( fset1[2], charsets_initialset1(cs, ord))],
1067 if 0 < charsets_class ( cs[1], ord) then (
1068 rs:charsets_remseta(charsets_setdifference(setify1(ps),setify1(cs)),cs,ord),
1069 if length(rs) # 0 then (
1070 ml2(rs,ts,charsets_removecont(rs,ord)),
1071 ml2(rs,fset3,charsets_removefactor ( rs, ord, fset2)),
1072 fset3:[charsets_union(fset3[1],ts),fset3[2]])
1073 else ( rs:[], fset3:fset2))
1075 return ( [[ 1 ],fset2])),
1077 [map(lambda([c],num(c/lcoeff(expand(c),/* reverse */(ord)))),cs),fset3])
1079 charsets_fcharsetsub ( charsets_union ( rs, cs, ps), ord,
1082 /*## The following few routines implement a strategy for speeding-up */
1083 /*## the computation of charsets by remembering all appearing initials */
1084 /*## in the quasi-sense. */
1086 charsets_premA ( uu,vv,x):=block( [ r,v,dr,dv,l,t,lu,lv,g],
1087 if integerp(vv / x) then ( subst( x = 0,uu))
1090 dr : degree ( r, x),
1092 dv : degree ( v, x),
1095 v : expand ( v - l * x ^ dv))
1097 if 1 < charsets_printlevel and 500 < length ( r) + length ( v) then (
1098 print("pseudo-division:, [ length ( r), x, dr ] ",[length(v),x,dv])),
1099 while (dv <= dr and r # 0) do (
1100 g:gcd ( lu:l, lv:coeff(r,x,dr)), lu:lu/g, lv:lv/g,
1101 t : expand ( x ^ ( ( dr - dv)) * v * lv),
1102 if dr = 0 then ( r : 0)
1103 else ( r : subst(x ^ dr = 0, r)),
1104 r : expand ( lu * r) - t,
1105 if not ratnump(lu) and /* WARNING: listp should be charsets_setp */listp(charsets_with)
1107 charsets_with : charsets_union ( charsets_with, setify1([ lu ]) )),
1112 charsets_remsetaA ( ps,as,ord):=block( [ i],
1113 charsets_setdifference(setify1([map(charsets_premasA(ps[i],as,ord))]),setify1([0]))
1115 charsets_premasA ( f,as,ord):=block( [ remd,i],
1117 for i : length ( as) thru 1 step - 1 do
1118 remd : charsets_premA ( remd, as[i], charsets_lvar ( as[i], ord) ),
1120 num( remd / lcoeff ( remd,ord) ))
1123 charsets_checkwith ( ps1,ps2):=block( [ rs,i,j,r,g,last],
1124 rs : charsets_setdifference ( ps1, ps2),
1125 if rs = setify1([]) then ( true)
1127 if ps2 = setify1([]) then ( false)
1129 rs : setify1(map(charsets_pfactor,map(sqfr,rs))),
1131 for i : 1 thru length ( rs) do (
1133 for j : 1 thru length ( ps2) do (
1134 g:gcd ( r, ps2[j]), r:r/g,
1135 if ratnump(r) then ( return(last:true))),
1136 if not ratnump(r) then ( return ( last:false))),
1139 /* replace the power of factors of polys in as by 1 if any */
1141 charsets_nopower ( as):=block(
1143 if not charsets_operatorp(as, charsets_ListOrSet)
1145 if charsets_operatorp(as,"^")
1148 else if charsets_operatorp(as,"*") then (
1149 apply("*",maplist(charsets_nopower, as)))
1154 maplist(charsets_nopower, as))
1156 /* macro to define the nearly char set -- a medial set */
1157 makeCharsetnFunction(theName,theSetType)::=buildq([theName,theSetType],
1158 theName( _ps,ord, [theRemsetFunction]):=block([ ps,cs,rs],
1159 if theRemsetFunction = [] then
1160 theRemsetFunction:charsets_remseta
1161 else theRemsetFunction:first(theRemsetFunction),
1162 if length ( _ps) < 2 then ( _ps)
1164 ps:charsets_unigcd(_ps,ord),
1165 cs : theSetType ( ps, ord),
1166 if 0 < charsets_class ( cs[1], ord) then (
1167 rs : charsets_remseta ( charsets_minus ( ps, cs), cs, ord))
1168 else ( return ( cs)),
1169 if rs = setify1([]) then ( cs)
1170 else ( theName( append(rs, cs), ord)))
1173 /* the nearly char set -- a medial set */
1174 makeCharsetnFunction(charsets_charsetn,charsets_basset)$
1175 /* the nearly weak-char set -- a weak-medial set */
1176 makeCharsetnFunction(charsets_wcharsetn,charsets_wbasset)$
1178 /* the nearly quasi-char set -- a quasi-medial set */
1179 makeCharsetnFunction(charsets_qcharsetn,charsets_qbasset)$
1181 makeFcharsetnFunction(theName,theSetType)::=buildq([theName,theSetType],
1182 theName( _ps,ord,fset1,[theRemsetFunction]):=block(
1183 [ ps,cs,rs,ts,fset2,fset3,last,fset],
1184 if theRemsetFunction = [] then
1185 theRemsetFunction:charsets_remseta
1186 else theRemsetFunction:first(theRemsetFunction),
1187 if length ( _ps) < 2 then ([_ps,fset1])
1189 ps : charsets_unigcd(_ps,ord),
1190 cs : theSetType( ps, ord),
1191 fset2 : [ fset1[1], charsets_union ( fset1[2], charsets_initialset1 ( cs, ord) )],
1192 if 0 < charsets_class ( cs[1], ord) then (
1193 rs:charsets_remseta ( charsets_minus ( ps, cs), cs, ord),
1194 if length(rs) # 0 then (
1195 ml2(rs,ts,charsets_removecont(rs,ord)),
1196 ml2(rs,fset3, charsets_removefactor ( rs, ord, fset2)),
1197 fset3 : [charsets_union(fset3[1],ts),fset3[2]])
1202 return ( [cs,fset2]))),
1206 theName( append(rs,cs), ord, fset3))
1208 /* the modified nearly char set -- a modified medial set */
1209 makeFcharsetnFunction(charsets_fcharsetn,charsets_basset)$
1211 /* the modified nearly weak-char set -- a modified weak-medial set */
1212 makeFcharsetnFunction(charsets_fwcharsetn,charsets_wbasset)$
1214 /* the modified nearly quasi-char set -- a modified quasi-medial set */
1215 makeFcharsetnFunction(charsets_fqcharsetn,charsets_qbasset)$
1217 /* the triangular set of poly set ps -- a quasi-medial set */
1219 charsets_triset ( _ps,ord):=block(
1221 if length ( _ps) < 2 then ( _ps)
1224 ps:charsets_unigcd(_ps,ord),
1225 for i : 0 thru length ( ord) do charsets_qs[i] : [],
1227 charsets_qs[charsets_class ( i, ord) ] :
1228 endcons(i,charsets_qs[charsets_class ( i, ord) ])),
1230 for i : length ( ord) thru 1 step - 1 do
1231 if charsets_qs[0] = []
1233 charsets_subtriset ( i, ord))
1234 else ( return(flag:true)),
1235 if flag = true then return ( [ 1 ] ),
1236 if charsets_qs[0] # []
1241 for i:1 thru length(ord) do r:append(r,charsets_qs[i]),
1245 /* subroutine for triset */
1247 charsets_subtriset ( i,ord):=block(
1249 if 1 < length ( charsets_qs[i])
1251 ml2(ss1,ss, charsets_sort( charsets_qs[i], charsets_trank, ord)),
1252 charsets_qs[i] : [ ss1 ],
1254 p : charsets_prem ( j, ss1, ord[i]),
1256 charsets_qs[charsets_class ( p, ord) ] :
1257 endcons(num( p/ lcoeff ( p,ord)),
1258 charsets_qs[charsets_class( p, ord)]))),
1259 charsets_subtriset ( i, ord))
1261 /* remove factor g from f until f has no factor g */
1262 /* if g is removed then assign true to ja */
1264 charsets_movefactor ( f,g,ord):=block([ fg,ja,last_result],
1265 if not charsets_operatorp(f,charsets_ListOrSet) and not ratnump(g)
1266 and ((fg:first(last_result:divide(f,g,
1267 charsets_lvar(g,ord))),second(last_result)) = 0) then (
1268 ja:if 0 < charsets_class ( g, ord) then true else false,
1269 [first(charsets_movefactor ( fg, g, ord)),ja])
1272 /* remove possible factors in fset1[1] and fset1[2] from polys in ps */
1273 /* where fset1[1] contains all factors removed before */
1274 /* if any poly in fset1[2] is removed, it is added to fset1[1] */
1275 /* fset1 is assigned to fset at the end of the procedure */
1277 charsets_removefactor ( ps,ord,fset1):=block(
1278 [ k,rr,ja,fset2,fs,qs,rs,r,fset],
1279 if not charsets_operatorp(ps,charsets_ListOrSet) then (
1280 qs : setify1([ ps ]))
1286 fset2 : setify1([]),
1287 for k in fs[1] do ml2(rr,ja,charsets_movefactor ( rr, k, ord)),
1290 ml2(rr,ja,charsets_movefactor ( rr, k, ord)),
1292 fset2 : charsets_adjoin2(num( k / lcoeff( expand( k),ord)), fset2))),
1293 fs : [ charsets_union ( fs[1], fset2), charsets_setdifference ( fs[2], fset2) ],
1294 rs : charsets_adjoin2( rr, rs)),
1295 rs : charsets_nopower ( rs),
1297 if not charsets_operatorp(ps,charsets_ListOrSet) then ( [rs[1],fset])
1300 /* remove contents of all polys in ps wrt leading variables */
1301 /* the set of removed factors is assigned to ms */
1303 charsets_removecont ( ps,ord):=block(
1304 [ qs,fs,i,cc,pp, ms],
1305 if charsets_operatorp(ps, charsets_ListOrSet) then (
1306 if charsets_class ( ps[1], ord) = 0 then [ps,setify1([])]
1310 for i : 1 thru length ( ps) do (
1311 if charsets_class ( ps[i], ord) > 0 then (
1312 ml2(cc,pp, content ( ps[i], charsets_lvar ( ps[i], ord))),
1313 cc:charsets_nopower(cc),
1314 if 0 < charsets_class ( cc, ord) then (fs : charsets_adjoin2(cc, fs)),
1316 qs : endcons( pp,qs))),
1319 ml2(qs,ms,charsets_removecont([ps],ord)),
1322 /* the modified triangular set of poly set ps -- a modified quasi-medial set */
1324 charsets_ftriset ( ps,ord,fset1):=block([i,fset2,var,last],
1326 if length ( ps) < 2 then ([ps, fset1])
1328 fset2 : setify1([]),
1330 for i : 0 thru length ( ord) do
1331 charsets_qs[i] : [],
1334 charsets_qs[charsets_class ( i, ord) ] :
1335 endcons( i, charsets_qs[charsets_class ( i, ord) ])),
1336 var : listofvars ( ps),
1337 for i : length ( ord) thru 1 step - 1 do
1338 if charsets_qs[0] = [] then (
1339 last : charsets_fsubtriset ( i, ord, ps, var),
1340 fset2 : charsets_union ( fset2, last)
1342 else ( return ( last:[[ 1 ],[ fset2, setify1([]) ]])),
1343 if last # [] then return(last),
1344 if charsets_qs[0] # [] then ([[1], [ fset2, setify1([]) ]])
1345 else ([flatten_qs(1,length( ord)),[fset2,setify1([])]]))
1347 /* subroutine for ftriset */
1349 charsets_fsubtriset ( i,ord,ps,var):=block(
1350 [ fset2,ss,ss1,j,k,l,p,pp,qq,ja,ts,last],
1351 if 1 < length ( charsets_qs[i]) then (
1352 ml2(ss1,ss,charsets_sort( charsets_qs[i], charsets_trank, ord)),
1353 charsets_qs[i] : [ ss1 ],
1354 fset2 : setify1([]),
1355 qq: setify1( maplist(lambda([p],num(p/lcoeff(expand(p),ord))),ps)),
1357 pp : charsets_prem ( j, ss1, ord[i]),
1359 if pp # charsets_fact and charsets_fsubtrisetsub(var,charsets_fact)
1360 and not member(charsets_fact, qq) then (
1361 ml2(p,ts, charsets_removecont ( pp, ord)),
1362 fset2 : setify1(append(fset2,ts)), /* could be charsets_union */
1363 ml2(p,ja,charsets_movefactor ( p, charsets_fact, ord)),
1365 fset2:charsets_adjoin2(num(charsets_fact
1366 /lcoeff(expand(charsets_fact),ord)),fset2)
1370 if p # k and not member(k, qq) then (
1371 ml2(p,ja,charsets_movefactor ( p, k, ord)),
1373 fset2 : charsets_adjoin2( k, fset2)))),
1374 charsets_qs[charsets_class ( p, ord) ] :
1375 endcons( charsets_nopower(num(p/lcoeff(p,ord))),
1376 charsets_qs[charsets_class ( p, ord)])
1378 last:charsets_initial ( ss1, ord),
1379 charsets_fact : num( last / lcoeff ( expand ( last),ord ) ),
1380 last : charsets_fsubtriset ( i, ord, ps, var),
1381 charsets_union ( fset2, last ))
1384 /* subroutine for fsubtriset */
1386 charsets_fsubtrisetsub ( aa,bb):=block(
1388 for i : 1 thru length ( aa) do
1389 if subst( aa[i] = 0, bb) = 0 then ( return ( flag:false)),
1392 /* reduce a triangular set into an ascending set */
1394 charsets_trisetc ( ps,ord):=block(
1396 charsets_cs : charsets_triset ( ps, ord),
1397 ml2(cs,_ind, charsets_subtrisetc ( ord, setify1([]))),
1399 charsets_charsetn ( append(ps,cs), ord))
1402 /* reduce a triangular set into an ascending set with factors moved */
1404 charsets_ftrisetc ( ps,ord,fset1):=block( [ i,_ind,cs,fs,last,fset],
1405 ml2(charsets_cs,fs, charsets_ftriset ( ps, ord, fset1)),
1407 if fs[1] # setify1([]) then (
1408 last:setify1(maplist(charsets_pfactor, fs[1])))
1411 ml2(cs,_ind, charsets_subtrisetc ( ord, last)),
1412 if _ind = 0 then ( charsets_fcharsetn ( append(ps,cs), ord, fset1))
1415 /* subroutine for ftrisetc */
1417 charsets_subtrisetc ( ord,var):=block([ r,i,j,cs,_ind,nops],
1418 nops:if setify1(charsets_cs) = [[]] then 0 else length(charsets_cs),
1419 /* print("subtrisetc nops",nops), */
1420 if nops = 0 then ( cs : [])
1421 else (cs : [ charsets_cs[1] ]),
1423 for i : 2 thru nops do (
1424 r : charsets_premas ( charsets_cs[i], cs, ord),
1425 if charsets_class( r, ord) # charsets_class( charsets_cs[i],ord) then (
1428 cs : endcons( charsets_nopower( num(r/lcoeff(r,ord))),cs)),
1431 for j in var do r : first(charsets_movefactor ( r, j, ord)),
1432 cs : endcons( charsets_nopower( num( r / lcoeff ( r,ord))),cs),
1433 if charsets_class( r, ord) #
1434 charsets_class( charsets_cs[i], ord) then (
1438 /* the set of nonconstant initials of as */
1439 /* with certain repeated factors cancelled */
1441 charsets_initialset1 ( as,ord):=block(
1445 last:charsets_initial ( i, ord),
1446 if 0 < (charsets_class ( last, ord)) then (
1447 __is : charsets_adjoin2(charsets_pfactor ( last), __is))),
1448 __is : charsets_compress ( __is, ord),
1451 if 0 < charsets_class ( i, ord)
1453 iss : charsets_adjoin2(i, iss)),
1456 /* compress some repeated factors */
1458 charsets_compress ( ps,ord):=block([_is,is1,i,j,ss],
1460 if 1 < length ( _is) then (
1462 for i : 1 thru length ( _is) - 1 do (
1464 for j : i + 1 thru length ( _is) do
1465 ss : first(charsets_movefactor ( ss, _is[j], ord)),
1466 if 0 < charsets_class ( ss, ord) then (
1467 is1 : cons( charsets_pfactor( ss), is1))),
1468 is1 : cons( _is[length ( _is) ], is1),
1470 if 1 < length ( is1) then (
1471 for i : 1 thru length ( is1) - 1 do (
1473 for j : i + 1 thru length ( is1) do
1474 ss : first(charsets_movefactor ( ss, is1[j], ord)),
1475 if 0 < charsets_class ( ss, ord) then (
1476 _is : setify1(charsets_adjoin2( charsets_pfactor ( ss),_is)))),
1477 setify1(charsets_adjoin2( is1[length ( is1) ],_is)))
1478 else ( setify1(is1)))
1479 else ( setify1(_is))
1481 /* the sequence of distinct factors of f */
1483 charsets_pfactor ( f):=block(
1485 if integerp(f) then ( setify1([]))
1486 else if charsets_operatorp(f,"^") then (
1488 num( last / lcoeff ( last) ))
1489 else if charsets_operatorp(f,"*") then (
1490 maplist(charsets_pfactor,f))
1492 num( f / lcoeff ( expand ( f) ) ))
1494 /* the sequence of factors of f */
1496 charsets_sfactor ( f):=block(
1498 if integerp(f) then (setify1([]))
1499 else if charsets_operatorp(f,"^") then (
1501 makelist(numer(last/lcoeff(last)),i,1,part( f, 2)))
1502 else if charsets_operatorp(f,"*") then (
1503 map(charsets_sfactor,f))
1505 num( f / lcoeff ( f) ))
1507 /* the set of all nonconstant factors of initials of polys in as */
1509 charsets_initialset ( as,ord):=block(
1513 last:charsets_initial ( i, ord),
1514 if 0 < (charsets_class ( last, ord)) then (
1515 __is : setify1(cons( last, __is)))),
1516 __is : charsets_factorps ( __is),
1519 if 0 < charsets_class ( i, ord) then (
1520 iss : setify1(cons( i, iss)))),
1523 /* all irreducible nonconstant factors of a set of polynomials */
1525 charsets_factorps ( ps):=block([ qs,i,j,q,c],
1529 c : num(numfactor(q)),
1531 if (charsets_operatorp(q,"*") = true) or (charsets_operatorp(q,"/") = true) then (
1532 for j : 1 thru length ( q) do (
1533 if not integerp(part( q, j)) then (
1534 if charsets_operatorp(part( q, j),"^") then (
1535 qs : setify1(cons( c*num( part( part( q, j), 1)
1536 / lcoeff ( part( part( q, j), 1)) ),qs)))
1538 qs : setify1(cons( c*num( part( q, j)
1539 / lcoeff ( part( q, j)) ),qs))))))
1540 else if charsets_operatorp(q,"^") then (
1541 qs : setify1(cons(c*num( q/ lcoeff ( q)),qs)))
1543 if not integerp(q) then (
1544 qs : setify1(cons(c*num( q / lcoeff ( q) ),qs))))),
1547 /*#### Part II. Routines for Various Decompositions and Others ##### */
1548 /* the char series of poly set ps */
1550 charsets_hack1(iss):=block([l1:first(iss),l2:second(iss)],
1551 [[l1[2],l1[3],l1[4],l1[1]],
1552 [l2[2],l2[3],l2[1],l2[4]]])$
1554 charsets_hack2(a):=[second(a),first(a)]$
1556 charsets_charseries ( ps,ord,medset):=block(
1557 [ qs,cs,iss,n,qsi,qhi,csno,ppi,qqi],
1558 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1(ps))
1559 else ( qhi : setify1([setify1( ps)])),
1564 for n : 0 while qhi # setify1([]) do (
1565 qhi : sort (qhi, charsets_lenord),
1567 ppi : charsets_select ( ppi, length ( qs) ),
1568 qqi : setify1(append(ppi[2], qqi)),
1569 if n = 0 then ( ppi : setify1([]))
1570 else ( ppi : charsets_adjoin2(qs,ppi[1])),
1571 cs : charsets_charseta ( qs, ord, medset),
1572 if 1 < charsets_printlevel then (
1574 print("Characteristic set produced in charseries",
1575 csno,length ( qhi),length ( qsi),length ( qs)),
1577 if 0 < charsets_class ( cs[1], ord) then (
1578 iss : charsets_initialset ( cs, ord),
1579 if charsets_simpa ( iss, cs, ord) # 0 then (
1580 qsi : charsets_adjoin2( cs, qsi)),
1581 iss : charsets_adjoin3 ( iss, qs, qqi))
1582 else ( iss : setify1([])),
1583 /* if read("reorder") = 1 then iss:charsets_hack1iss, */
1584 if 1 < length ( qhi) then (
1585 qhi : setify1(append(iss, rest(qhi))))
1587 if qsi = setify1([]) then ( [])
1588 else ( sort ( charsets_contract ( qsi, ord, 0), charsets_lenord))
1590 /* the char series of poly set ps -- allowing to remove factors */
1592 charsets_fcharser ( ps,ord,medset):=block(
1593 [ qs,cs,iss,n,qhi,qsi,factorset,csno,ppi,qqi,last],
1594 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1(ps))
1595 else ( qhi : setify1([setify1(ps)])),
1600 for n : 0 while qhi # setify1([]) do (
1601 qhi : sort (qhi, charsets_lenord),
1603 ppi : charsets_select ( ppi, length ( qs) ),
1604 qqi : setify1(append(ppi[2], qqi)),
1605 if n = 0 then ( ppi : setify1([]))
1606 else ( ppi : charsets_adjoin2(qs,ppi[1])),
1607 if length ( qs) - 3 < length ( ord) then (
1608 cs : charsets_fcharseta (qs, ord, medset),
1612 cs:charsets_charseta (qs, ord, medset),
1613 factorset:setify1([])),
1614 if 1 < charsets_printlevel then (
1616 print("Characteristic set produced in fcharser",
1617 csno,length ( qhi),length ( qsi),length ( qs)),
1619 if 0 < charsets_class ( cs[1], ord) then (
1620 iss : charsets_initialset ( cs, ord),
1621 if charsets_simpa ( iss, cs, ord) # 0 then (
1622 qsi : charsets_adjoin2( cs, qsi)),
1623 iss : charsets_union ( iss, charsets_factorps ( factorset) ))
1625 iss : charsets_factorps ( factorset)),
1626 iss : charsets_adjoin3 ( iss, qs, qqi),
1627 if 1 < length ( qhi) then (
1628 qhi : setify1(append(iss, rest(qhi))))
1630 if qsi = setify1([]) then ( [])
1631 else ( sort ( charsets_contract ( qsi, ord, 0), charsets_lenord))
1633 /* the extended char series of poly set ps */
1635 charsets_excharser ( ps,ord,medset):=block(
1636 [qs,cs,_is,iss,i,j,qsi,qhi,r,rr,last],
1637 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1([ ps ]))
1638 else ( qhi : setify1([ [ ps, 1 ] ])),
1640 while (qhi # setify1([])) do (
1642 cs : charsets_charseta (qs, ord, medset),
1643 if 1 < charsets_printlevel then (
1644 print("Characteristic set produced in excharser"),
1646 if 0 < charsets_class ( cs[1], ord) then (
1647 _is : charsets_initialset ( cs, ord),
1648 rr : charsets_nopower( charsets_prod( charsets_adjoin2(qhi[1][2],_is))),
1649 last:charsets_premas ( rr, cs, ord),
1651 r : charsets_simp ( last, cs, ord),
1653 if r = 1 then ( qsi : setify1(cons( cs, qsi )))
1654 else ( qsi : charsets_adjoin2([ cs, charsets_simpb( r, rr)], qsi))))
1657 if length ( ord) <= length ( ps) + 1 then (
1658 for i in _is do ( iss : setify1(cons([ charsets_adjoin2( i,qs),qhi[1][2]],iss))))
1660 for i : 1 thru length ( _is) do (
1661 last:if i = 1 then 1 else product ( _is[j], j, 1, i - 1),
1662 iss:charsets_adjoin2([charsets_adjoin2(_is[i],qs),last*qhi[1][2]],iss)
1665 if 1 < length ( qhi) then (
1666 qhi : charsets_union(iss, rest(qhi)))
1669 if qsi = setify1([]) then ( [])
1670 else ( sort ( qsi, charsets_lenord))
1672 /* simplify r to rr so that Zero(cs/r) = Zero(cs/rr) holds still */
1673 charsets_simp ( r,cs,ord):=block([rr,i,fs,j,_ind,last],
1676 fs : setify1(charsets_pfactor( r)),
1679 if 0 < charsets_class ( i, ord) then (
1682 last:subst(i = 0,j),
1684 if charsets_class(first(charsets_movefactor(j,i,ord)),
1688 else if charsets_class ( last, ord) = 0 then (
1691 if _ind = 0 then ( rr : rr * i)
1692 else if _ind = - 1 then (
1694 if _ind = - 1 then ( 0) else ( rr))
1696 /* check whether Zero(cs/fs) is empty */
1698 charsets_simpa ( fs,cs,ord):=block([ i,j,ds,flag],
1699 if length ( cs) = 1 then ( 1)
1702 ds : makelist(cs[i],i,1,length ( cs) - 1),
1705 if subst(0, i, j) = 0 then (
1706 if charsets_class( first(charsets_movefactor(j,i,ord)),ord) = 0
1707 then ( return ( flag:0)))),
1708 if(flag = 0)then return(flag)),
1711 /* the simpler one of a and b */
1713 charsets_simpb ( a,b):=block(
1714 if charsets_measure ( a) < charsets_measure ( b) then ( a) else ( b)
1716 /* the measure of complexity of a according to number of terms */
1718 charsets_measure ( a):=block( [ i],
1719 if charsets_operatorp(a,"^") then ( length ( part( a, 1)))
1720 else if charsets_operatorp(a,"*") then (
1721 sum ( charsets_measure ( part( a, i)), i, 1, length ( a) ))
1722 else if variablep(a) then 1
1725 /* the extended char series of poly set ps -- allowing to remove factors */
1727 charsets_fexcharser ( ps,ord,medset):=block(
1728 [ qs,cs,_is,iss,n,i,j,qhi,qsi,r,rr,factorset,last],
1729 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1([ ps ]))
1730 else ( qhi : setify1([ [ ps, 1 ] ])),
1732 for n : 0 while qhi # setify1([]) do (
1734 if n = 0 then ml2(cs,factorset,charsets_fcharseta(qs, ord, medset))
1736 cs:charsets_charseta (qs, ord, medset),
1737 factorset:setify1([])),
1738 if 1 < charsets_printlevel then (
1739 print("Characteristic set produced"),
1741 if 0 < charsets_class ( cs[1], ord) then (
1742 _is : charsets_union(charsets_initialset(cs,ord),charsets_factorps(factorset)),
1743 rr : charsets_nopower( charsets_prod( charsets_adjoin2(qhi[1][2],_is))),
1744 last:charsets_premas ( rr, cs, ord),
1746 r : charsets_simp ( last, cs, ord),
1748 if r = 1 then ( qsi : setify1(cons( cs, qsi )))
1749 else ( qsi : setify1(endcons([ cs, charsets_simpb( r, rr)],qsi)))))
1750 else ( _is : charsets_factorps ( factorset)),
1752 if length ( ord) <= length ( ps) + 1 then (
1753 for i in _is do ( iss : setify1(endcons([charsets_adjoin2( i,qs),qhi[1][2]],iss))))
1755 for i : 1 thru length ( _is) do (
1756 last:if i = 1 then 1 else product ( _is[j], j, 1, i - 1),
1757 iss:charsets_adjoin2([charsets_adjoin2(_is[i],qs),last*qhi[1][2]],iss)
1760 if 1 < length ( qhi) then qhi : charsets_union(iss,rest(qhi))
1763 if qsi = setify1([]) then ( [])
1764 else (sort ( qsi, charsets_lenord))
1766 /* the irreducible char series of poly set ps */
1767 /* using new factorization method if m=1, Hu-Wang's method if m=-1 */
1768 /* and normalized char set if m=0 */
1770 charsets_irrcharser ( ps,ord,medset,[m]):=block(
1771 [ qs,cs,cst,_is,iss,n,ts,qsi,qhi,pi,factorset,ppi,qqi,csno,_ind,mind,fset],
1772 if length(m) = 0 then ( _ind : 1) else ( _ind : first(m)),
1773 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1([ (ps) ]))
1774 else ( qhi : setify1([ ps ])),
1780 if medset = charsets_basset then ( mind : true) else ( mind : false),
1781 for n : 0 while qhi # setify1([]) do (
1782 qhi : sort ( qhi, charsets_nopsord),
1784 ppi : charsets_select ( ppi, length ( qs) ),
1785 qqi : charsets_union(ppi[2], qqi),
1786 if n = 0 then ( ppi : setify1([]))
1787 else ( ppi : charsets_adjoin2(qs, ppi[1])),
1788 if length ( qs) - 3 < length ( ord) then (
1790 ml2(cs,fset, apply( assoc(medset,charsets_fcharsetsub_alist),
1791 [ qs, ord, [ setify1([]), listofvars( qs)]])),
1792 factorset:first(fset))
1794 ml2(cs,factorset, charsets_fcharseta ( qs, ord, medset)),
1795 if 1 < charsets_printlevel and _ind = 1 then (
1797 print("Characteristic set produced in irrcharser",csno,
1798 length ( qhi),length ( qsi),length ( qs)),
1801 cs : [ charsets_fcnormal ( cs, ord, 2) ],
1802 if 1 < length ( cs) then (
1803 factorset : charsets_union ( factorset, part( cs[2], 2))),
1806 if mind then ml2(cs,factorset,
1807 charsets_removecont ( charsets_charseta ( qs, ord, medset), ord))
1808 else ml2(cs,factorset,charsets_removecont( medset (qs,ord),ord))),
1809 if 0 < charsets_class ( cs[1], ord) then (
1810 ts:charsets_irras ( cs, ord, _ind),
1813 if medset = charsets_autored then
1814 cs:charsets_charseta(charsets_union(qs,cs),ord, charsets_charsetn)
1816 if not charsets_subset ( cs, qs) then
1817 cs : charsets_charseta( charsets_union(qs, cs), ord, medset)),
1818 if 1 < charsets_printlevel and _ind = 1 then (
1820 print("Characteristic set produced in irrcharser",
1821 csno,length ( qhi),length ( qsi),length ( qs)),
1823 if not member(cs, pi) then (
1824 pi : charsets_adjoin2(cs, pi),
1825 if 0 < charsets_class ( cs[1], ord) then (
1826 ts:charsets_irras ( cs, ord, _ind),
1828 qsi : charsets_adjoin2( cs, qsi),
1829 if length ( cs) = length ( ord) then (
1830 _is : charsets_factorps ( factorset))
1832 _is : charsets_union ( charsets_initialset ( cs, ord),
1833 charsets_factorps ( factorset) )),
1834 iss : charsets_adjoin3 ( _is, qs, qqi)))
1836 iss : charsets_adjoin3(charsets_factorps(factorset),qs,qqi)))
1837 else (iss:charsets_adjoin3(charsets_factorps(factorset), qs, qqi))),
1838 if ts[2] # 0 then ( _is : charsets_factorps ( factorset),
1840 cst : part(cs, makelist(i,i,1,ts[2] - 1)),
1841 _is : charsets_union ( _is, charsets_initialset ( cst, ord) ),
1842 iss : charsets_union ( charsets_adjoin3 ( _is, qs, qqi),
1843 charsets_adjoinb ( ts[1], qs, qqi, cst) ))
1844 else ( iss : charsets_adjoin3 ( charsets_union ( _is, ts[1]), qs, qqi))))
1845 else ( iss : charsets_adjoin3 ( charsets_factorps ( factorset), qs, qqi)),
1846 if 1 < length ( qhi) then ( qhi : charsets_union(iss, rest(qhi)))
1848 last:if qsi = setify1([]) then ([])
1849 else (sort( charsets_contract ( qsi, ord, 1), charsets_lenord))),
1852 /* test whether ps is a charsets_subset or sublist of qs */
1854 charsets_subset ( ps,qs):=block( [ p,flag:true],
1856 if not member(p, qs) then ( return ( flag:false)),
1859 /* subroutine for irrcharser, qirrcharser and others */
1861 charsets_adjoinb ( _is,qs,qh,cs):=block( [ iss,i,j,_ind,qhi,itt,qs_],
1863 qhi : charsets_setdifference ( qh, (qs_:setify1(qs))),
1864 if _is # setify1([]) then (
1866 itt : setify1(cons( i, charsets_union(qs_, setify1(cs)))),
1868 if 0 < length ( qhi) then (
1869 for j in qhi while _ind = 0 do (
1870 if charsets_subset ( j, itt) then ( _ind : 1))),
1871 if _ind = 0 then ( iss : charsets_adjoin2(itt,iss)))),
1874 /* examine the irreducibility of as for irrcharser */
1875 /* This function should be memoized */
1876 charsets_irras ( as,ord,inda):=block([ _ind,i,j,p,qs,n,fs,ja,dd,last],
1880 for i : 1 thru length ( as) do (
1881 p : factor ( as[i]),
1882 fs:if mapatom(p) then [p]
1884 if "-" = op(p) then -charsets_dfactors(-p) else charsets_dfactors(p)),
1885 /* print("irras after dfactors",fs), */
1887 for j : 1 thru length ( fs) do (
1888 if 0 < charsets_class ( fs[j], ord) then qs : charsets_adjoin2(fs[j],qs)),
1889 /* print("irras after qs loop",qs), */
1890 last:charsets_lvar ( p, ord),
1891 if charsets_degree ( qs[1], last) < charsets_degree ( p, last) then (
1892 /* print("irras degree compare hit",qs[1],p), */
1896 if _ind = 1 and 1 < length ( as) then (
1898 while (n:nn) < length(as) and charsets_degreel(as[n:nn],ord)=1 do (0),
1899 if n < length(as) then ml3(qs,ja,dd,charsets_irrassub( as, n, ord, inda))
1903 /* subroutine for irras */
1905 charsets_irrassub ( as,n,ord,_ind):=block(
1906 [ m,qs,i,vv,dd,mm,ja],
1907 for mm : (m:n + 1) while (m:mm) <= length ( as)
1908 and charsets_degreel ( as[m:mm], ord) = 1 do (0),
1910 if m <= length ( as) then (
1911 vv : charsets_lvar ( as[m], ord),
1913 qs : charsets_factoras ( as[m], makelist(as[i],i,1,m - 1), ord))
1915 qs : charsets_cfactor ( as[m], makelist(as[i],i,1,m - 1), ord),
1917 qs : setify1(charsets_qfactor ( num( qs), ord))),
1918 if max ( map(lambda([q],charsets_degree (q, vv)),qs))
1919 = charsets_degree ( as[m], vv) then (
1920 ml3(qs,ja,dd, charsets_irrassub ( as, m, ord, _ind)))
1925 /* collect distinct nonconstant factors of a polynomial q */
1927 charsets_dfactors ( q):=block( [ qs,j],
1928 if charsets_operatorp(q,"*") then (
1930 for j : 1 thru length ( q) do
1931 if not integerp(part( q, j)) then (
1932 if charsets_operatorp(part( q, j),"^") then (
1933 qs : setify1([ qs, num( part( part( q, j), 1)
1934 / lcoeff ( part( part( q, j), 1)))]))
1935 else ( qs : charsets_adjoin2( num( part( q, j)/lcoeff( part( q, j))),qs))))
1936 else if charsets_operatorp(q,"^") then (
1937 qs : setify1([ num( part( q, 1) / lcoeff ( part( q, 1)) ) ]))
1939 if not integerp(q) then (
1940 qs : setify1([ num( q / lcoeff ( q))]))),
1943 /* normalize ascending set cs wrt ord */
1945 charsets_fcnorm ( cs,ord,m):=block(
1948 for i : 2 thru length ( cs) do
1949 as : charsets_fcnormal ( [ (as), cs[i] ], ord, m),
1950 if 1 < length ( [ as ] ) then ( return ( cs)) ,
1953 /* normalize the last pol in an ascending set cs wrt ord */
1955 charsets_fcnormal ( cs,ord,m):=block(
1956 [ n,ini,i,j,ggg,gg,ff,ccs,dd,cd,fs,nt,last],
1961 nt : length ( expand ( dd) ),
1962 for i : n - 1 thru 1 step - 1 do (
1963 ini : charsets_initial ( dd, ord),
1964 if 0 < charsets_degree ( ini, charsets_lvar ( cs[i], ord) ) then (
1965 ggg : charsets_gcdex ( cs[i], ini, charsets_lvar ( cs[i], ord) ),
1967 if 0 < charsets_degree ( gg, charsets_lvar ( cs[i], ord) ) then (
1969 gg : setify1([ charsets_pfactor ( gg) ]),
1971 for j : 1 thru length ( gg) do
1972 if charsets_class( gg[j], ord) = charsets_class ( cs[i], ord)
1974 ff : charsets_nopower( first(
1975 charsets_movefactor( ff, gg[j], ord)) ),
1976 cd : setify1([ (cd), gg[j] ])) ,
1977 if charsets_class ( ff, ord) = 0 then (
1981 ccs : [charsets_fcnormal( cs, ord, m)]),
1982 if length ( ccs) = 1 then (
1983 return ([ccs[1], "common divisors", cd]))
1985 return ([ccs[1], "common divisors",
1986 setify1([cd, (part( ccs[2], 2)) ]) ])))
1988 dd : charsets_prem( dd*ggg[2], cs[i], charsets_lvar(cs[i],ord)),
1989 dd :first(charsets_movefactor(dd,
1990 charsets_initial(cs[i],ord),ord)),
1991 dd : charsets_nopower ( dd),
1992 if 4 * m * nt < length ( expand ( dd) ) then ( return ( cs))))),
1993 ccs : makelist(cs[i],i,1,n - 1),
1994 block([temp], ml2(temp,dd,content(dd,charsets_lvar(dd,ord))),last:temp),
1995 fs : setify1([charsets_pfactor(last)]),
1997 for i : 1 thru length ( fs) do
1998 if 0 < charsets_class (fs[i],ord) then ( gg : setify1([gg, fs[i]])),
1999 gg : charsets_prod ( gg),
2000 ini : charsets_initialset ( ccs, ord),
2001 for i : 1 thru length ( ini) do
2002 gg : first(charsets_movefactor ( gg, ini[i], ord)),
2003 dd : charsets_nopower ( gg) * dd,
2004 gg : [ charsets_pfactor ( num( dd / lcoeff ( expand ( dd),ord ) ) ) ],
2006 for i : 1 thru length ( gg) do
2007 if 0 < charsets_class ( gg[i], ord) then ( dd : dd * gg[i]) ,
2008 if m * nt < length ( expand ( dd) ) then (
2009 if 1 < charsets_printlevel then (
2010 print("normalization fails:",nt,length ( expand ( dd) ))) ,
2012 else ( endcons(dd,ccs)))
2014 /* the modified gcdex for fcnormal */
2015 /* This function was memoized, however maybe it can be replaced by the maxima gcd */
2016 charsets_gcdex ( A,B,x):=block(
2017 [ m,pm,cc,cd,c,c1,c2,d,d1,d2,r,r1,r2,q,II,temp],
2018 if A = 0 then ( return ( [ 0, 1, B ] )) ,
2019 if B = 0 then ( return ( [ 1, 0, A ] )) ,
2020 ml2(cc,c,content( A, x)),
2021 ml2(cd,d,content( B, x)),
2022 /* this is a guess about how gcd/degree should work */
2023 II:block([g],g:gcd( c:expand ( c), d:expand ( d), x), c:c/g, d:d/g,
2024 if 1=g then setify1([]) else setify1([g])),
2031 ml3(q,r,m,prem ( c, d, x)),
2032 r:first(divide ( r, pm)),
2033 r1:first(divide ( m * c1 - q * d1, pm)),
2034 r2:first(divide ( c2 * m - q * d2, pm)),
2043 map(expand,subst(II, [ c1 * cd, c2 * cc, c * cc * cd ]))
2045 /* the extended irreducible char series of poly set ps */
2047 charsets_exirrcharser ( ps,ord,medset):=block(
2048 [qs,cs,_is,iss,n,i,j,qhi,qsi,r,rr,factorset,mind,fset,_ind,ts,den,last,temp],
2049 qhi:if charsets_operatorp(ps[1], charsets_ListOrSet) then setify1([ps])
2050 else setify1([[ps,1]]),
2051 mind:if medset = charsets_basset then true else false,
2053 for n : 0 while qhi # setify1([]) do (
2057 ml2(cs,fset, apply( assoc(medset,charsets_fcharsetsub_alist),
2058 [ qs, ord, [ setify1([]), listofvars( qs)]])),
2059 factorset : fset[1])
2061 last:first(apply( assoc(medset,charsets_fcharsetsub_alist),
2062 [ qs, ord,[setify1([]),listofvars(qs)]])),
2063 ml2(cs,factorset, charsets_removecont ( last, ord))))
2066 ml2(cs,factorset, charsets_fcharseta( qs, ord, medset)))
2068 temp:charsets_charseta( qs, ord, medset),
2069 ml2(cs,factorset, charsets_removecont ( temp, ord))),
2070 if 1 < charsets_printlevel then (
2071 print("Characteristic set produced"),
2073 if 0 < charsets_class ( cs[1], ord) then (
2074 /* in the original code ts has 2 elements, here it has 3, so
2075 confirm that the 3rd element is not used, if it is, then
2076 delete it after the assignment to den */
2077 ts:charsets_irras ( cs, ord, _ind),
2081 if medset = charsets_autored then (
2082 cs : charsets_charseta( setify1(append(qs,cs), ord, charsets_charsetn)))
2084 if not charsets_subset( cs, qs) then (
2085 cs:charsets_charseta(setify1(append(qs,cs)),ord,medset))),
2086 if 1 < charsets_printlevel then (
2087 print("Characteristic set produced"),
2089 if 0 < charsets_class ( cs[1], ord) then (
2090 ts:charsets_irras ( cs, ord, _ind),
2093 _is : charsets_union( charsets_initialset( cs, ord), charsets_factorps( factorset)),
2094 if length ( cs) = length ( ord) then (
2095 rr : charsets_nopower ( qhi[1][2]))
2097 rr:charsets_nopower(charsets_prod(charsets_adjoin2(qhi[1][2],_is)))),
2098 last:charsets_premas ( rr, cs, ord),
2099 r : charsets_simp ( last, cs, ord),
2102 qsi : charsets_adjoin2( cs, qsi))
2104 qsi : charsets_adjoin2([cs,charsets_simpb ( r, rr)],qsi))))
2106 _is : charsets_factorps ( factorset),
2110 _is : charsets_union( charsets_initialset( setify1(
2111 makelist(cs[i],i,1,ts[2]-1)),ord),
2112 charsets_factorps(factorset)))
2113 else ( _is : charsets_factorps ( factorset))))
2115 _is : charsets_factorps ( factorset),
2118 if length ( ord) <= length ( ps) + 1 then (
2120 iss : charsets_adjoin2( [charsets_adjoin2( i,qs ), qhi[1][2]],iss)))
2122 for i : 1 thru length ( _is) do (
2123 last:if i = 1 then ( 1) else product ( _is[j], j, 1, i - 1),
2124 iss : charsets_adjoin2([charsets_adjoin2(_is[i],qs), last * second(first(qhi))],iss))),
2125 if ts[2] # 0 and ts[1] # setify1([]) then (
2128 last:if medset = charsets_autored then (
2129 charsets_charseta(setify1(append(qs,cs)),ord,charsets_charsetn))
2131 if not charsets_subset ( cs, qs) then
2132 charsets_charseta(setify1(append(qs,cs)), ord, medset)
2135 if ts[2] = 1 then cs : qs
2136 else cs : setify1(append( qs, makelist(cs[i],i,1,ts[2] - 1))))
2139 iss : charsets_adjoin2([charsets_adjoin2(i,cs),
2140 charsets_prod(charsets_adjoin2(den,charsets_adjoin2(second(first(qhi)),_is)))],iss)),
2141 if 0 < charsets_class ( den, ord) and
2142 ts[2] < charsets_class ( ts[1][1], ord) then (
2143 iss : charsets_adjoin2([ charsets_adjoin2( den, cs ), second(first(qhi))],iss))),
2144 if 1 < length ( qhi) then ( qhi : charsets_union(iss, rest(qhi)))
2146 if qsi = setify1([]) then ( [])
2147 else ( (sort (qsi,charsets_lenord)))
2149 /* subroutine for irrcharser, qirrcharser and others */
2151 /* In maple the condition is n <= nops(i) and nops gives the same thing as maxima's */
2152 /* length for sums and products, excepts that for a single variable nops(x) = 1 while */
2153 /* length (x) produces an error. */
2155 charsets_select ( ppi,n):=block([ i,pp,qq,lli],
2156 lli : if (i=listofvars(i)[1]) then 1 else length(i),
2160 if n <= lli then ( qq : charsets_adjoin2( i, qq))
2161 else ( pp : charsets_adjoin2( i, pp))),
2164 /* subroutine for irrcharser, qirrcharser and others */
2165 /* name this function charsets_adjoin3 to distinguish from 2-arg
2166 * function in charsets_set.lisp.
2168 charsets_adjoin3 ( _is,qs,qh):=block( [ iss,i,j,_ind,qhi,itt],
2170 qhi : charsets_setdifference ( qh, setify1(qs)),
2171 if _is # setify1([]) then (
2173 itt : setify1(endcons( i, qs )),
2175 if 0 < length ( qhi) then (
2176 for j in qhi while _ind = 0 do (
2177 if charsets_subset ( j, itt) then ( _ind : 1))),
2178 if _ind = 0 then ( iss : setify1(cons(itt, iss))))),
2181 /* subroutine for trisersub */
2183 charsets_adjoina ( _is,qs,qh):=block( [ iss,i,j,_ind,qhi,itt],
2185 qhi : charsets_setdifference ( qh, setify1([ qs ])),
2186 if _is # setify1([]) then (
2188 itt : charsets_adjoin2(i, setify1(qs)),
2190 if 0 < length ( qhi) then (
2191 for j in qhi while _ind = 0 do (
2192 if charsets_subset (setify1([j]), itt) then ( _ind : 1))),
2193 if _ind = 0 then (iss: charsets_adjoin2(cons(i,qs),iss)))),
2197 /* if _ind = 0 then ( iss: charsets_adjoin2(charsets_adjoin2(i,qs),iss)))), */
2198 /* subroutine for irrcharser, qirrcharser and others */
2200 charsets_nopsord(a,b):= if symbolp (a) then (false)
2201 else if symbolp (b) then (true) else
2202 if length( b) < length( a) then ( true) else ( false)$
2204 /* remove some redundant ascending sets in cs */
2205 /* irr=1 for irrcharser, irr=2 for qirrcharser, irr=-1 for trisersub */
2206 /* and irr=0 for others */
2208 charsets_contract ( cs,ord,irr):=block( [ i,j,mem,ts],
2211 if not (listp(cs) or charsets_setp(cs)) then break("Contract cs not list or set"),
2212 if length ( cs) < 2 then cs
2214 for i : 1 thru length ( cs) - 1 do
2215 if not member(i, mem) then (
2216 for j : i + 1 thru length ( cs) do
2217 if not member(j, mem) then (
2218 if charsets_linas(cs[j],ord,irr)
2219 and charsets_contractsub ( cs[i], cs[j], ord) then (
2220 ts : charsets_adjoin2(cs[j], ts),
2221 mem : charsets_adjoin2( j, mem))
2223 if charsets_linas ( cs[i], ord, irr)
2224 and charsets_contractsub ( cs[j], cs[i], ord) then (
2225 ts : charsets_adjoin2( cs[i], ts ))))),
2226 charsets_setdifference( setify1(cs), ts))
2228 /* check whether all polys in cs1 have remainders 0 wrt cs2 */
2229 /* but none of their initials does: subroutine for contract */
2231 charsets_contractsub( cs1,cs2,ord):=block( [ i,_is, flag:true],
2233 if charsets_premas( i, if listp(cs2) then cs2 else [cs2], ord) # 0 then (
2234 return ( flag:false)),
2235 if not flag then return(flag),
2236 _is : charsets_initialset1 ( cs1, ord),
2238 if charsets_premas( i, if listp(cs2) then cs2 else [cs2], ord) = 0 then (
2239 return ( flag:false)),
2242 /* check the irreducibility of as: subroutine for contract */
2243 charsets_has(x,y):=block(
2244 if atom(x) then (if x = y then true else false)
2247 charsets_linas ( as,ord,irr):=block([i,j,n,m,nn,mm,flag],
2248 if irr = 1 then ( true)
2252 if 1 < length ( as) then (
2253 for nn:(n:1) while nn < length(as) and
2254 charsets_degreel(as[nn],ord) = 1 do(n:nn),
2255 if n < length ( as) then (
2256 for mm:(m:n+1) while mm <= length(as) and
2257 charsets_degreel(as[mm],ord) = 1 do (m:mm),
2258 if m <= length ( as) then (return ( flag:false)))),
2263 if 1 < charsets_degreel ( i, ord) then ( return ( flag:false))),
2264 if not flag then return(false),
2265 if irr = 0 or length ( as) < 2 then ( true)
2267 for i : 2 thru length ( as) do (
2268 for j : 1 thru i do (
2269 if charsets_has(charsets_initial(as[i],ord),
2270 charsets_lvar(as[j],ord)) then (
2271 return ( flag:false))))
2275 /* the quasi-irreducible char series of poly set ps */
2277 charsets_qirrcharser ( ps,ord,medset):=block(
2278 [ qs,cs,_is,iss,n,ts,qsi,qhi,pi,factorset,ppi,qqi,csno,fset,mind],
2279 if charsets_operatorp(ps[1], charsets_ListOrSet) then ( qhi : setify1([ (ps) ]))
2280 else ( qhi : setify1([ ps ])),
2286 mind:if medset # charsets_basset and medset # charsets_wbasset then true else false,
2287 for n : 0 while qhi # setify1([]) do (
2288 qhi : sort (qhi, charsets_nopsord),
2290 ppi : charsets_select ( ppi, length ( qs) ),
2291 qqi : charsets_union( qqi, ppi[2]),
2292 if n = 0 then ( ppi : setify1([]))
2293 else ( ppi : charsets_adjoin2( qs, ppi[1])),
2294 if length ( qs) - 3 < length ( ord) then (
2296 ml2(cs,fset, apply( assoc(medset,charsets_fcharsetsub_alist),
2297 [ qs, ord, [ setify1([]), listofvars( qs)]])),
2298 factorset : fset[1])
2300 ml2(cs,factorset, charsets_fcharseta ( qs, ord, medset)),
2301 if 1 < charsets_printlevel then (
2303 print("Characteristic set produced in qirrcharser ",csno,length ( qhi),length ( qsi),length ( qs)),
2306 if not mind and 2 < length ( listofvars ( cs[1]) ) then (
2307 ml2(cs,factorset, charsets_removecont( charsets_charseta( qs, ord, medset), ord)))
2309 ml2(cs,factorset, charsets_removecont( medset( qs, ord), ord)))),
2310 if 0 < charsets_class ( cs[1], ord) then (
2311 ts : charsets_qirras ( cs, ord),
2314 if medset = charsets_autored then (
2315 cs : charsets_charseta(charsets_union(qs,cs),ord,charsets_charsetn))
2317 if not charsets_subset ( cs, qs) then (
2318 cs : charsets_charseta( charsets_union( qs, cs), ord, medset))),
2319 if 1 < charsets_printlevel then (
2321 print("Characteristic set produced in qirrcharser ",csno,length ( qhi),length ( qsi),length ( qs)),
2323 if not member(cs, pi) then (
2324 pi : charsets_adjoin2( cs, pi),
2325 if 0 < charsets_class ( cs[1], ord) then (
2326 ts : charsets_qirras ( cs, ord),
2328 qsi : charsets_adjoin2( cs, qsi),
2329 if length ( cs) = length ( ord) then (
2330 _is : charsets_factorps ( factorset))
2332 _is : charsets_union ( charsets_initialset ( cs, ord), charsets_factorps ( factorset) )),
2333 iss : charsets_adjoin3 ( _is, qs, qqi)))
2335 iss : charsets_adjoin3 ( charsets_factorps ( factorset), qs, qqi)))
2337 iss : charsets_adjoin3 ( charsets_factorps ( factorset), qs, qqi))),
2339 _is : charsets_union ( charsets_factorps ( factorset), ts[1]),
2341 _is : charsets_union ( _is, charsets_initialset ( [ part(cs, makelist(i,i,1,ts[2] - 1)) ], ord) )),
2342 iss : charsets_adjoin3 ( _is, qs, qqi)))
2344 iss : charsets_adjoin3( charsets_factorps( factorset), qs, qqi)),
2345 if 1 < length ( qhi) then ( qhi : charsets_union(iss, rest(qhi)))
2347 if qsi = setify1([]) then ( [])
2348 else ( (sort ( charsets_contract ( qsi, ord, 2), charsets_lenord)))
2350 /* examine the irreducibility of as for qirrcharser */
2351 /* I think this function should be memoized */
2352 charsets_qirras ( as,ord):=block([ _ind,i,j,p,qs,fs,n,m,ja,last],
2356 for i : 1 thru length ( as) do (
2357 p : factor ( as[i]),
2358 fs:if mapatom(p) then [p]
2360 if "-" = op(p) then -charsets_dfactors(-p) else charsets_dfactors(p)),
2362 for j : 1 thru length ( fs) do (
2363 if 0 < charsets_class ( fs[j], ord) then qs : charsets_adjoin2(fs[j],qs)),
2364 last:charsets_lvar ( p, ord),
2365 if charsets_degree ( qs[1], last) < charsets_degree ( p, last) then (
2369 if _ind = 1 and 1 < length ( as) then (
2371 while (n:nn) < length(as) and charsets_degreel(as[n:nn],ord)=1 do (0),
2372 if n < length ( as) then (
2373 for mm:(m : n + 1) while mm <= length( as) and charsets_degreel( as[m:mm], ord) = 1 do (0),
2374 if m <= length ( as) then (
2375 print("Warning: factorization over algebraic field required for ics")))),
2378 /* subroutine for `charsets/cfactor` */
2380 charsets_cfactorsub( f,as,ord):=block([ _ind,i,ff,fn,ffn,lind,secondLast,last],
2382 if charsets_operatorp(ff,"^") then (
2383 _ind : map(lambda([f],charsets_newfactoras(f,as, ord)),ff))
2384 else if charsets_operatorp(ff,"*") then (
2385 fn : setify1([ (ff) ]),
2387 for i : 1 thru length ( fn) do
2388 if charsets_operatorp(fn[i],"^") then (
2389 _ind : _ind * map(fn[i],charsets_newfactoras,as, ord))
2391 _ind : _ind * charsets_newfactoras ( fn[i], as, ord)))
2392 else ( _ind : charsets_newfactoras ( ff, as, ord)),
2393 lind:lcoeff( ff,charsets_lvar(ff, ord))
2394 /safeLcoeff(_ind, charsets_lvar(_ind,ord)),
2395 for i : length ( as) thru 1 step - 1 do (
2397 charsets_premB(num(lind),as[i],charsets_lvar(as[i],ord))),
2398 ml2(last,ffn,charsets_premB(denom(lind),as[i],charsets_lvar(as[i],ord))),
2399 lind : secondLast * ffn / last / fn),
2401 if charsets_operatorp(last, [ "*", "^" ]) then ( simplify( last/denom ( f) ))
2404 charsets_cfactor_switch : false $
2405 /* factorize poly f over algebraic number field with minimal polys in as */
2406 /* -- a new method of Wang */
2407 /* first factorize pf over smaller fields */
2409 charsets_newfactoras ( f,as,ord):=block( [ pf,pas,aas,con,vf,va,i,fn,last],
2410 vf : charsets_lvar ( f, ord),
2411 if charsets_class ( vf, ord) <= charsets_class ( as[length ( as) ], ord)
2413 else if charsets_degree ( f, vf) = 1 then ( return ( f)),
2416 for i : 1 thru length ( as) do (
2417 last:charsets_degreel ( as[i], ord),
2419 con : charsets_adjoin2(last,con),
2420 aas : endcons(expand(as[i]),aas))),
2421 if aas = [] then ( return ( f)) ,
2422 va : charsets_lvar ( aas[1], ord),
2423 if length ( aas) = 1 and charsets_degree ( f, va) = 0 then (
2424 last:charsets_trivial ( f, aas[1], vf, va, fn),
2425 if charsets_operatorp(last, setify1([ "*", "^" ])) then (
2426 return ( map(last,charsets_newfactoras,as, ord) / fn))) ,
2427 pas : charsets_fcnorm ( aas, ord, 1),
2428 last:charsets_fcnormal(endcons(f,pas), ord, 1),
2429 if 1 < length (last) then ( pf : f) else ( pf : last[length(last)]),
2430 if charsets_cfactor_switch and 1 < length ( pas) then (
2431 fn : charsets_cfactor ( pf, [ pas[length ( pas) ] ], ord),
2432 if apply(max,map([maplist(lambda([x],x),num(fn))],degree,vf))
2433 < degree ( pf, vf) then (
2434 return( charsets_cfactorsub( num( fn), pas, ord) / denom ( fn)))
2436 fn :charsets_cfactor( pf,makelist(pas[i],i,1,length (pas)-1), ord),
2437 if apply(max , map(lambda([x],degree(x,vf)),num( fn)))
2438 < degree ( pf, vf) then (
2439 return( charsets_cfactorsub( num( fn), pas, ord) / denom( fn))))),
2440 if charsets_adjoin2( charsets_degreel ( pf, ord),con ) = setify1([ 2 ])
2441 and length ( pas) < 3 then (
2442 charsets_factoras ( pf, pas, ord))
2444 if 1 < charsets_printlevel then (
2445 print("newfactoras: factorization over algebraic field: degree",
2446 charsets_degreel ( pf, ord),terms,length ( pf))) ,
2447 charsets_con : true,
2448 charsets_newfactorassub ( pf, pas, ord))
2450 /* test for a trivial case --- can it be extended? */
2451 /* a trivial case */
2452 /* Check the usage of last */
2453 charsets_trivial ( ff,aa,vf,va,fn):=block(
2454 [ f,a,da,df,ss,i,last,secondLast],
2457 da : degree ( a, va),
2458 df : degree ( f, vf),
2459 if num( f / lcoeff ( f) ) = subst(num( a / lcoeff ( a) ), ( va = vf)) and 2
2463 ss : [ coeff(f,vf,da) ],
2464 for i : df - 1 thru 0 step - 1 do
2465 ss : [ ss[1] * va + coeff(f,vf,i), (ss) ],
2466 last:sum ( ss[i + 1] * vf ^ ( ( i - 1)), i, 1, df),
2467 return ( ( ( vf - va)) * last)),
2468 secondLast:sum ( charsets__z ^ ( ( da - i)) * va ^ i * coeff(a,va,i), i, 0, da),
2469 last:sum ( charsets__z ^ ( ( df - i)) * vf ^ i * coeff(f,vf,i), i, 0, df),
2470 last:charsets_premB ( last, secondLast, charsets__z, fn),
2471 if charsets_degree ( last, charsets__z) = 0 then ( factor ( last))
2474 /* modified pseudo-divison with multiplied initial factor as fn */
2476 charsets_premB ( uu,vv,x):=block( [ r,v,dr,dv,l,t,lu,lv,gn,g],
2477 if integerp(vv / x) then [ subst(x = 0,uu),1]
2481 dr : degree ( r, x),
2483 dv : degree ( v, x),
2486 v : expand ( v - l * x ^ dv))
2488 if 1 < charsets_printlevel and 500 < length ( r) + length ( v) then (
2489 print("pseudo-division:",[length(r),x,dr],[length(v),x,dv])),
2490 while (dv <= dr and r # 0) do (
2491 g:gcd ( lu:l, lv:coeff(r,x,dr)), lu:lu/g, lv:lv/g,
2492 t : expand ( x ^ ( ( dr - dv)) * v * lv),
2493 if dr = 0 then ( r : 0) else ( r : subst(( x ^ dr = 0),r)),
2494 r : expand ( lu * r) - t,
2500 /* main subroutine for newfactoras */
2501 /* considerably modified and improved in December 1991 */
2503 charsets_newfactorassub ( f,as,ord,[args]):=block(
2504 [nord,mord,cs,ccs,ccs1,cr,i,con,ff,fff,nas,vf,die,der,ci,fs,m,n,inda,
2505 indb,_is,_CS,fmedset, ncs,cc,bb,last,flag],
2506 /* args is being used as a flag, but there are always 3 or more args */
2507 if length(args) > 0 then args:true else args:false,
2509 vf : charsets_lvar ( f, ord),
2511 for i : 2 thru nas do (
2512 as[i]:charsets_newfactorassub(as[i],makelist(as[i],i,1,i-1),ord))),
2513 last:makelist(charsets_lvar( as[i], ord), i , 1 , nas),
2514 nord : cons( vf, last ),
2515 mord : endcons(vf, last),
2517 for i : 2 thru length ( nord) do
2518 con : con + charsets_degree ( f, nord[i]),
2521 m : charsets_degree ( as[1], nord[2]),
2522 n : charsets_degree ( f, vf),
2523 if gcd ( m, n) = 1 then ( return ( f)))),
2524 last:charsets_setdifference( listofvars(charsets_adjoin2( f, as)), setify1([nord])),
2525 if length ( last) = 1 and args = false then (
2526 return ( charsets_tefactor ( f, as, mord, [ last ] ) )) ,
2534 if con # 0 and charsets_con then (
2539 if charsets_das # [ false ] then (
2540 die : charsets_das[1],
2541 charsets_das : rest(charsets_das))
2542 else ( die : charsets_die ()),
2543 der : sum ( ( ( i - die - 2)) * nord[i], i, 2, length ( nord) ),
2544 ff : expand ( subst(vf = der + vf,f))),
2545 charsets_con : false,
2546 charsets_with : setify1([]),
2547 if 1 < charsets_printlevel then (
2548 print("Characteristic set computation:",
2549 charsets_index(endcons(ff, as), nord))),
2550 fmedset : charsets_fqcharsetn,
2551 _is : nord[length ( nord) ],
2552 if length(as) = 1 and degree( as[1], _is) > 5 and degree( ff, _is) > 5
2553 and length( charsets_union( listofvars( as), listofvars( ff))) = 2 then (
2554 ccs : factor ( resultant ( ff, as[1], _is) ),
2555 if "+" = inpart(ccs, 0) then (return ( flag:true))
2557 if degree ( as[1], _is) < degree ( ff, _is) then (
2558 ccs : [ ccs, as[1] ])
2559 else ( ccs : [ ccs, ff ])),
2560 fs : [ setify1([]), setify1([]) ])
2562 ml2(ccs,fs,fmedset(endcons(ff,as),nord,[setify1([]),setify1([])]))),
2563 _is : charsets_initialset ( ccs, nord),
2564 fs : charsets_factorps ( charsets_movefactorps ( fs[1], _is, nord) ),
2565 cs : setify1(charsets_qfactor( factor( charsets_movefactorps(
2566 ccs[1], charsets_union ( _is, fs), ord) ), nord))),
2567 if not indb or cs = setify1([]) then (
2568 charsets_with : setify1([]),
2569 if fs = setify1([]) then (
2571 _is : charsets_setdifference ( _is, setify1([ _is[1] ]) ))
2574 fs : charsets_setdifference ( fs, setify1([ fs[1] ]) )),
2575 ccs : charsets_charsetn( [ (as), ff, bb ], nord),
2576 _is : charsets_initialset ( ccs, nord),
2577 cs : setify1(charsets_qfactor ( factor ( charsets_movefactorps (
2578 ccs[1], charsets_union ( _is, fs), ord) ), nord)),
2580 if cs # setify1([]) then (
2581 if charsets_checkwith(charsets_with,charsets_union( _is, fs)) then ( inda:true)
2582 else ( inda : false),
2583 if charsets_linearas ( ccs, nord) or 1 < length ( cs) then (
2584 if length ( cs) = 1 then (
2586 ccs1 : [ cs[1], part(ccs, makelist(i,i,2,length ( ccs))) ])
2588 ccs1 : charsets_charseta( [ (as), ff, cs[1],
2589 part(ccs, makelist(i,i,2,length ( ccs))) ],
2590 nord, charsets_charsetn)),
2591 while (charsets_class ( ccs1[1], nord) = 0) do (
2592 if fs = setify1([]) then (
2594 _is : charsets_setdifference ( _is, setify1([ _is[1] ]) ))
2597 fs : charsets_setdifference ( fs, setify1([ fs[1] ]) )),
2598 ccs1 : charsets_charseta ( [ (as), ff, bb ], nord,
2599 charsets_charsetn)),
2600 if ccs1 # ccs then (
2602 cs :charsets_qfactor(factor (ccs[1]),nord))),
2603 if length ( cs) = 1 then (
2604 if charsets_linearas ( ccs, nord) then (
2605 cc :charsets_algcd(f,subst(vf = vf - der,ccs[1]),as,mord),
2606 if 0 < charsets_degree ( cc, vf) then (
2607 cs : [ charsets_arrange ( charsets_union ( _is, fs), vf) ],
2608 if 1 < charsets_printlevel then (
2609 print("A non-trivial factor found:",cc)),
2610 if length ( cs) = 0 then ( ci : [ fff ], fff : 1)
2612 fff : charsets_divide ( fff, cc, as, mord),
2614 _CS : subst(vf = vf - der,cs),
2616 for i : 1 thru length ( _CS) do (
2617 if 2 < charsets_printlevel then (
2618 print("Algebraic GCD:",length ( _CS),i)),
2619 cc : charsets_algcd( fff, expand( _CS[i]), as, mord),
2620 if 0 < charsets_degree ( cc, vf) then (
2621 fff : charsets_divide ( fff, cc, as, mord),
2622 if 1 < charsets_printlevel then (
2623 print("A non-trivial factor found:",cc)),
2624 if charsets_degree ( cc, vf) = 1 then (
2625 ci : endcons(cc, ci))
2626 else ( cr : endcons(cc, cr)))),
2628 else ( indb : false)))
2631 cs : append(charsets_arrange(cs,vf),
2632 charsets_arrange(charsets_union(_is,fs),vf)),
2633 _CS : subst(vf = vf - der,cs),
2634 for i : 1 thru length ( _CS) do (
2635 if 2 < charsets_printlevel then (
2636 print("Algebraic GCD:",length ( _CS),i)) ,
2637 cc : charsets_algcd ( fff, expand ( _CS[i]), as, mord),
2638 if 0 < charsets_degree ( cc, vf) then (
2639 fff : charsets_divide ( fff, cc, as, mord),
2640 if 1 < charsets_printlevel then (
2641 print("A non-trivial factor found:",cc)) ,
2642 if charsets_degree(cc, vf) = 1 then (ci : endcons(cc,ci))
2645 con : part(ccs, makelist(i,i,2,length ( ccs))),
2646 if inda and not charsets_vanish ( cs[i], _is) then (
2647 con : [ cs[i], con ])
2649 con : charsets_charseta ( setify1([ (as),
2650 con, ff, cs[i] ]), nord, charsets_charsetn)),
2651 if con[1] = cs[i] and charsets_linearas ( con, nord)
2652 then ( ci : endcons( cc,ci))
2653 else ( cr : endcons( cc,cr)))
2654 else ( cr : endcons( cc,cr))))),
2655 if 0 < length( ci) or 1 < length( cr) or length( cr) = 1 and
2656 charsets_degree(num( cr[1]), vf) < charsets_degree( f, vf)
2657 then ( return(false)))))),
2658 if flag then return(f),
2659 last:charsets_degree ( fff, vf),
2660 if 1 < last then ( cr : endcons(fff, cr))
2661 else if last = 1 then ( ci : endcons(fff, ci)),
2662 if length ( ci) = 0 then (
2664 makelist(charsets_newfactorassub(cr[i],as,ord),i,1,length(cr))))
2666 if length ( cr) = 0 then ( product ( ci[i], i, 1, length ( ci) ))
2668 product( ci[i],i,1,length(ci)) * charsets_prod(
2669 makelist(charsets_newfactorassub(cr[i],as,ord),i,1,length(cr)))))
2671 /* compute the GCD of f and g over the algebraic field having */
2672 /* adjoining asc set as */
2674 charsets_algcd ( f,g,as,mord):=block( [ nas,fs,last,temp],
2675 nas : length ( as) + 1,
2676 if charsets_degree(f,mord[nas]) = 0 or charsets_degree( g, mord[nas]) = 0
2677 then ( return ( 1)) ,
2678 if 1 < charsets_printlevel then (
2679 print("GCD computation over algebraic field:",charsets_index([f,g],mord),
2680 (charsets_index ( as, mord)))),
2681 ml2(temp,fs,charsets_fcharsetnA(as,[f,g], mord, [setify1([]),setify1([])])),
2682 last:part([charsets_fcnormal(temp ,mord,2)],1),
2683 if length ( last) = nas then ( last[nas]) else ( 1)
2685 /* subroutine for algcd */
2687 charsets_fcharsetnA ( as,ps,ord,fset1):=block([cs,rs,fset2,fset3,nas],
2688 nas : length ( as) + 1,
2689 cs : append(as, charsets_basset ( ps, ord)),
2690 fset2 : [ fset1[1], charsets_union ( fset1[2], charsets_initialset1( cs, ord) )],
2691 if 0 < charsets_degree ( cs[nas], ord[nas]) then (
2692 rs : charsets_remseta ( charsets_minus ( ps, cs), cs, ord),
2693 /* print("before removefactor3"), */
2694 ml2(rs,fset3,charsets_removefactor ( rs, ord, fset2)))
2695 else ( return ( [ 1,fset2 ] )),
2696 if rs = [] then return([cs, fset3])
2697 else ( charsets_fcharsetnA ( as, endcons( rs, cs[nas] ), ord, fset3))
2700 /* division over an algebraic field with adjoining ascending set as */
2702 charsets_divide ( ff,f,as,ord):=block(
2704 sprem ( ff, f, charsets_lvar ( ff, ord), m, q),
2705 charsets_premas ( q, as, ord)
2707 /* check if an ascending set is quasilinear */
2710 charsets_linearas ( cs,ord):=block(
2712 if length ( cs) = 1 then ( true)
2714 for i : 2 thru length ( cs) do
2715 if 1 < charsets_degreel ( cs[i], ord) then ( return ( false)) ,
2718 /* order a set ps of polys according their degrees in x */
2720 charsets_arrange ( ps,x):=block(
2721 charsets_reorderb( ps, charsets_arrangesub, x)
2723 /* subroutine for arrange */
2725 charsets_arrangesub ( f,g,x):=block(
2726 if charsets_degree ( f, x) < charsets_degree ( g, x) then true else false
2728 /* random generator for linear transformation */
2730 charsets_die : random(5)+3 $
2731 /* remove polys in ps as factors from f */
2733 charsets_movefactorps ( f,ps,ord):=block( [ p,ff,i],
2734 if not charsets_operatorp(f, charsets_ListOrSet) then (
2736 for p in ps do ff : first(charsets_movefactor ( ff, p, ord)),
2738 else ( setify1(makelist(charsets_movefactorps(f[i],ps,ord),i,1,length(f))))
2740 /* check if q vansihes one poly in ps */
2742 charsets_vanish ( q,ps):=block( [ p,flag:false],
2743 for p in ps do if 0 = divide ( q, p) then ( return ( flag:true)) ,
2746 /* sequence of non-constant factors of f */
2748 charsets_qfactor ( f,ord):=block( [ i,last],
2749 if charsets_class ( f, ord) = 0 then ( ( setify1([])))
2750 else if charsets_operatorp(f,"^") then (
2752 num( last / lcoeff ( last,ord) ))
2753 else if charsets_operatorp(f,"*") then (
2754 maplist(lambda([p],charsets_qfactor( p, ord)), f))
2755 else ( num( f / safeLcoeff(f,ord)))
2757 /* sequence of non-constant (multiple) factors of f */
2758 /* there is a problem with the last line. If qqfactor is called with
2759 a single factor, then this will not return a list. If this function
2760 fails, then the if "*" clause needs to be replaced by a double loop,
2761 which will flatten the list returned by qqfactor. */
2762 charsets_qqfactor ( nf,ord):=block( [temp, i,last,f:nf/numfactor(nf)],
2763 if charsets_class ( f, ord) = 0 then []
2764 else if charsets_operatorp(f,"^") then (
2766 makelist(num( last[i] / lcoeff ( last[i],ord) ), i, 1, part( f, 2)))
2767 else if charsets_operatorp(f,"*") then (
2769 for i:1 thru length(f) do (
2770 last:charsets_qqfactor( part( f, i), ord),
2771 if last # [] then temp:endcons(last,temp)),
2773 else (num( f / lcoeff ( f,ord) ))
2775 /* the following routines implement a heuristic procedure for poly factorization */
2776 /* over algebraic function fields by integer substitution and solving systems */
2777 /* of linear equations */
2778 /* the main routine */
2780 charsets_tefactor ( f,as,ord,var):=block(
2781 [ i,j,k,vf,nv,df,inf,ff,gg,ja,js,fs,ffs,hs,gs,sol,ci,dvar,tvar,mm,tt,yvar,das,last,secondLast],
2783 vf : ord[length ( ord) ],
2784 df : charsets_degree ( f, vf),
2785 if nv = 1 and length ( as) = 1 then (
2786 last:charsets_prem ( f, as[1], var[1]),
2788 last:factor ( last), secondLast:last,
2789 [ last:charsets_qqfactor ( last, [ vf ] ) ],
2790 if charsets_operatorp(secondLast, setify1([ "*", "^" ])) and max ( last:map(charsets_degree ( last[i], vf))) < df then (
2791 last:map(part( part( [ charsets_fcnormal ( [ as[1], last[i] ], ord, 2) ], 1), 2)),
2792 return ( charsets_prod ( map(last,charsets_newfactoras,as, ord)) )))),
2793 inf : lcoeff ( f, vf), secondLast:last,last:inf,
2794 for i : 1 thru nv do charsets_m[i] : 1,
2797 charsets_dasA : [ 1, -1, 2, -2, 3, -3, false ],
2798 charsets_dieA : random(20*nv)-10*nv,
2799 das : lambda ([], block(
2800 if charsets_dasA # [ false ] then (
2802 charsets_dasA : [ part(charsets_dasA, makelist(i,i,2,length ( charsets_dasA))) ],
2804 else ( charsets_dieA ()))),
2805 tvar : charsets_noterms ( nv, charsets_degree ( f, var) ),
2809 yvar : setify1([ _y1 ]),
2810 for mm : 1 while ci = setify1([]) and dvar < tvar do (
2811 dvar : charsets_noterms ( nv, mm),
2812 while (length ( js) < dvar) do (
2813 /* I am assuming that the following is a assignment */
2814 /* sol : map(var[i] = das ()), */
2815 for x in var do x:das(), sol:var,
2816 if subst(inf, sol) # 0 and charsets_isirr ( subst(as, sol), ord)
2818 js : [ (js), setify1([ sol ]) ],
2819 /* check this line carefully */
2820 ff : setify1(charsets_qfactor ( charsets_cfactor ( subst(f, ( sol)), subst(as, sol), ord), [ vf ] )),
2821 if max ( map(charsets_degree ( ff[i], vf))) = df
2828 coeffs ( expand ( % ^ mm), var, tt),
2831 /* where is _y and _y1 defined */
2832 gg : gg + sum ( _y [ % + i] * tt[i], i, 1, length ( tt) ),
2833 yvar : charsets_union ( yvar, setify1([ map(_y [ %% + i]) ]) ),
2836 for j : 1 thru length ( fs[1]) do (
2840 for i : 2 thru length ( fs) do (
2841 charsets_getclose ( fs[1][j], [ (fs[i]) ], ord, ja),
2844 if 1 < charsets_printlevel
2846 print("Heuristic tefactor failed")),
2847 return ( charsets_newfactorassub ( f, as, ord, 0) ))
2850 charsets_setdifference ( fs[i], setify1([ fs[i][ja] ]) ),
2853 fs : [ part(fs, makelist(i,i,1,i - 1)), % ])
2855 fs : [ part(fs, makelist(i,i,1,i - 1)), %, part(fs, makelist(i,i,i+ 1,length ( fs))) ]))),
2856 sol : setify1([ map(subst(gg, ( (js[k]))) - gs[k]) ]),
2857 sol : setify1([ solve ( sol, yvar) ]),
2858 if sol # setify1([])
2860 hs : charsets_union ( hs, setify1([ expand ( subst(gg, ( (sol)))) ]) ))),
2864 charsets_divideA ( ff, j, as, ord),
2868 ci : charsets_union ( ci, setify1([ j ]) ),
2869 if 1 < charsets_printlevel
2871 print("A factor found:",j)))),
2872 if ci = setify1([]) and mm <= 1 and _help # true and length ( ffs[1]) ^ length ( ffs)
2875 gs : charsets_getall ( ffs),
2876 for i : 1 thru length ( gs) while length ( ci) <= length ( fs[1]) do (
2877 sol : setify1([ map(subst(gg, ( (js[k]))) - gs[i][k]) ]),
2878 sol : setify1([ solve ( sol, yvar) ]),
2879 if 1 < charsets_printlevel and sol = setify1([])
2882 if sol # setify1([])
2884 sol : expand ( subst(gg, ( (sol)))),
2885 charsets_divideA ( ff, sol, as, ord),
2889 ci : charsets_union ( ci, setify1([ sol ]) ),
2890 if 1 < charsets_printlevel
2892 print("A non-trivial factor found:",j))))))),
2893 if ci # setify1([]) then (
2894 ci : charsets_union ( ci, setify1([ ff ]) ),
2895 charsets_prod ( map(ci,charsets_newfactoras,as, ord)))
2897 if 1 < charsets_printlevel
2899 print("Heuristic tefactor failed")),
2900 charsets_newfactorassub ( f, as, ord, 0))
2902 /* numbers of maximal terms in a poly of total degree d in n variables */
2904 charsets_noterms ( n,d):=block([ i,j],
2905 sum ( product ( n + j - 1, j, 1, i) / i!, i, 1, d) + 1
2907 /* check if an ascending set as is irreducible */
2909 charsets_isirr ( as,ord):=block( [ xa,fs,f,as1],
2910 if length ( as) = 1 then (
2911 xa : charsets_lvar ( as[1], ord),
2912 if xa = 0 then ( false)
2913 else if charsets_degree ( as[1], xa) = 1 then ( true)
2915 fs : setify1(charsets_qfactor ( factor ( as[1]), [ xa ] )),
2916 if length ( fs) = 1 then ( true) else ( false)))
2918 as1 : [ part(as, makelist(i,i,1,length ( as) - 1)) ],
2919 if not charsets_isirr ( as1, ord) then ( false)
2921 f : as[length ( as) ],
2922 xa : charsets_lvar ( f, ord),
2923 if xa = 0 then ( false)
2924 else if charsets_degree ( f, xa) = 1 then ( true)
2926 fs : setify1(charsets_qfactor(charsets_cfactor(f,as1,ord),[xa])),
2927 if length ( fs) = 1 then ( true) else ( false))))
2929 /* get all possible combinations (used for tefactor) */
2931 charsets_getall ( fs):=block(
2935 setify1([ map( [ fs[1][i] ] /* $ ( ( i = 1 .. length ( fs[1]) ))*/) ]))
2939 gs : setify1([ part(fs, makelist(i,i,1,nf - 1)) ]),
2940 gs : charsets_getall ( gs),
2941 setify1([ map(map( [ (gs[i]), fs[nf][j] ] /* $ ( ( j = 1 .. length ( fs[nf]) ))*/)/* $ ( ( i
2942 = 1 .. length ( gs) ))*/) ]))
2944 /* select a poly in fs closest to g */
2946 charsets_getclose ( g,fs,var,ja):=block(
2947 [ i,j,gs,hs,dg,nv,vv,jaa,jbb,ts,cv,rr,chs,df,last],
2948 if charsets_class ( g, var) = 0 then ( return ( FAIR)),
2949 if length ( fs) = 1 then ( ja : 1, return ( fs[1])),
2950 if length ( var) = 1 and _help # true then (
2953 dg : charsets_degree ( g, var[1]),
2954 for i : 1 thru length ( fs) do (
2955 if fs[i] = g or fs[i] = - g then ( ja : i, return ( fs[i]))
2956 else if charsets_degree ( fs[i], var[1]) = dg then (
2958 gs : [ (gs), fs[i] ])
2960 if length ( jaa) = 1 then ( ja : jaa[1], return ( gs[1])),
2963 cv : [ coeffs ( expand ( g), var[1], dg) ],
2964 for i : 1 thru length ( jaa) do (
2965 coeffs ( expand ( gs[i]), var[1], df),
2966 if setify1([ df ]) = setify1([ dg ]) then (
2967 jbb : [ (jbb), jaa[i] ],
2968 hs : [ (hs), gs[i] ])),
2969 if length ( jbb) = 1 then ( ja : jbb[1], return ( hs[1])),
2972 dg : [ map(sign, cv) ],
2973 for i : 1 thru length ( jbb) do (
2974 ts : [ coeff(expand ( hs[i]),[var[1]])],
2975 ts : [ map(sign, ts) ],
2976 if charsets_close ( ts, dg) = 0 then (
2977 jaa : [ (jaa), jbb[i] ],
2978 gs : [ (gs), hs[i] ])),
2979 if length ( gs) = 1 then ( ja : jaa[1], return ( gs[1])),
2982 for i : 1 thru length ( jbb) do (
2983 ts : [ coeff(expand ( hs[i]),[var[1]])],
2984 ts : [ map(sign ( ts[j])) ],
2985 if charsets_close ( ts, dg) = 1 then (
2986 jaa : [ (jaa), jbb[i] ],
2987 gs : [ (gs), hs[i] ])),
2988 if length ( gs) = 1 then (ja : jaa[1], return ( gs[1])),
2991 for i : 1 thru length ( jbb) do (
2992 ts : [ coeff(expand ( hs[i]),[var[1]])],
2993 ts : [ map(sign, ts) ],
2994 if charsets_close ( ts, dg) = 2 then (
2995 jaa : [ (jaa), jbb[i] ],
2996 gs : [ (gs), hs[i] ])),
2997 if length ( gs) = 1 then ( ja : jaa[1], return ( gs[1]))
2998 else ( return ( FAIL)))
3000 if _help # true then (
3005 dg : charsets_degree ( g, vv),
3006 for i : 1 thru length ( fs) do(
3007 if fs[i] = g or fs[i] = -g then ( ja : i, return ( fs[i]))
3008 else if charsets_degree ( fs[i], vv) = dg then (
3010 gs : [ (gs), fs[i] ])),
3011 if length ( jaa) = 1 then ( ja : jaa[1], return ( gs[1])),
3016 /* I think here is the calls to coeff with 3 args */
3017 cv : [ coeffs ( expand ( g), vv, dg) ],
3018 for i : 1 thru length ( gs) do(
3019 chs : [ (chs), [ coeffs ( expand ( gs[i]), vv, df) ] ],
3020 if setify1([ df ]) = setify1([ dg ]) then (
3021 jbb : [ (jbb), jaa[i] ],
3022 hs : [ (hs), gs[i] ])),
3023 if length ( jbb) = 1 then ( ja : jbb[1], return ( hs[1])),
3024 for i : 1 thru length ( [ dg ] ) do(
3025 ts : [ map(chs[j][i]/* $ ( ( j = 1 .. length ( chs) ))*/) ],
3026 charsets_getclose ( cv[i], ts, [ map(var[j]/* $ ( ( j = 1 .. nv - 1))*/) ], jbb),
3027 if % = FAIR then ( return ( FAIR))
3028 else if % # FAIL then ( ja : jaa[jbb], return ( hs[jbb]))))
3031 jaa : makelist(i, i, 1,length ( hs) )),
3034 print("Please help to choose one polynomial in the list",hs),
3035 print("which is closest to the polynomial",g),
3036 rr : readstat ("and enter the polynomial number in the list:" ),
3039 else ( ja : 1, return ( fs[1])))
3041 /* a subroutine for getclose */
3043 charsets_close ( ps,qs):=block(
3051 for i : 1 thru length ( ps) do
3058 /* division over an algebraic field with adjoining ascending set as */
3060 charsets_divideA ( ff,f,as,ord):=block(
3062 if charsets_class ( ff, ord) # charsets_class ( f, ord)
3066 last:sprem ( ff, f, charsets_lvar ( ff, ord), m, q),
3067 if charsets_premas (last, as, ord) # 0
3071 charsets_premas ( q, as, ord)
3073 /* factorize poly f over algebraic number field with minimal polys in as */
3074 /* -- Hu-Wang's method */
3076 charsets_factoras ( pf,pas,ord,[args]):=block(
3077 [df,r,s,ff,i,t,fact,gg,hh,fg,z,_ind,as,nas,f,vf,sol,con,m,n,mord,nord,last],
3078 if not polynomialp(pf,ord,
3079 lambda([x],integerp(x) or (not constantp(x) and lfreeof(ord,x)))) then (
3080 return(charsets_factoras(num(pf),pas,ord)/denom(pf))),
3081 /* args is being used as a flag, but there are always 3 or more args */
3082 if length(args) > 0 then args:true else args:false,
3083 nas : length ( pas),
3084 vf : charsets_lvar ( pf, ord),
3086 for i : 2 thru nas do (
3087 pas[i]:charsets_factoras(pas[i],makelist(pas[i],i,1,i-1),ord))),
3089 /* Not quite. Assuming that pas is a list, it assigns pas[2] as the value
3090 of `charsets/factoras`(pas[2],[pas[1]],ord). And then for i=3,
3091 it assigns pas[3] as the value of
3092 `charsets/factoras`(pas[3],[pas[1],pas[2]],ord).
3093 These values are stored in a "remember table", so the next time the
3094 procedure is called with those arguments the value will be taken from
3095 the table rather than being recomputed.
3097 last:makelist(charsets_lvar( pas[i], ord), i , 1 , nas),
3098 nord : cons( vf, last ),
3099 mord : endcons(vf, last),
3100 con : sum(charsets_degree ( pf, nord[i]),i,2,length(nord)),
3103 m : charsets_degree ( pas[1], nord[2]),
3104 n : charsets_degree ( pf, vf),
3105 if gcd ( m, n) = 1 then ( return ( pf)))),
3106 last:charsets_setdifference( listofvars( charsets_adjoin2( pf, pas)), setify1(nord)),
3107 if length ( last) = 1 and args = false then (
3108 /* here it is assumed that sets are implemented as lists */
3109 return ( charsets_tsfactor ( pf, pas, mord, last) )),
3114 for i : 1 thru length ( pas) do (
3115 df : charsets_degreel ( pas[i], ord),
3119 as : endcons(expand ( pas[i]),as))),
3120 z : charsets_lvar ( f, ord),
3121 df : charsets_degree ( f, z),
3123 else if r = 0 then ( f)
3125 if 1 < charsets_printlevel then (
3126 print("factoras: factorization over algebraic field -- degree ",
3127 charsets_degreel ( f, ord))),
3128 for s : 1 thru fix( (1/2) * df) while _ind = 0 do (
3129 for i : 1 thru s do block([g],
3130 last : makelist(concat(charsets_k,t),t,1,r),
3131 g:concat(charsets_g,i),
3132 g::charsets_summ( arraymake(charsets_g,cons(i,last))*product(
3133 charsets_lvar(as[t],ord)^concat(charsets_k,t),t,1,r),r)),
3134 for i : 1 thru df - s do block([h],
3135 last : makelist(concat(charsets_k,t),t,1,r),
3136 h:concat(charsets_h,i),
3137 h:: charsets_summ( arraymake(charsets_h,cons(i,last))*product(
3138 charsets_lvar(as[t],ord)^concat(charsets_k,t),t,1,r),r)),
3139 last:concat(charsets_g,0),
3141 last:concat(charsets_h,0),
3143 gg : sum( eval(concat(charsets_g,i))* z ^(s - i), i, 0, s),
3144 hh : sum( eval(concat(charsets_h,i))* z ^(df - s - i), i, 0, df - s),
3145 ff : f - lcoeff ( expand ( f), z) * expand ( gg * hh),
3146 ff : expand ( charsets_premas ( ff, as, ord) ),
3148 for i : 0 thru df - 1 do
3149 fact:charsets_union(charsets_coeff(as,setify1([coeff(ff,z,i)]),r,ord),fact),
3150 sol : [ charsets_solveps ( fact, charsets_getvars ( fact) ) ],
3151 if sol = [ fair ] then (
3152 if 1 < charsets_printlevel then (
3153 print("factoras changes to newfactoras")),
3154 charsets_das : [ -1, 1, -2, 2, -3, false ],
3155 charsets_con : true,
3156 return ( charsets_newfactorassub( pf, pas, ord) )),
3159 fg:subst(sol[1],gg)*charsets_factoras(num(subst(sol[1],hh)),as,ord),
3163 /* the following routine implements some heuristics for verifying the */
3164 /* irreducibilty of polynomials over algebraic function fields by */
3165 /* integer substitution */
3167 charsets_tsfactor ( f,as,ord,var):=block(
3168 [ i,vf,nv,df,_inf,ff,sol,das,secondLast,last],
3170 vf : ord[length ( ord) ],
3171 df : charsets_degree ( f, vf),
3172 if nv = 1 and length ( as) = 1 then (
3173 last:charsets_prem ( f, as[1], var[1]),
3175 last:factor ( last), secondLast:last/numfactor(last),
3176 last:charsets_qqfactor( last, [ vf ] ),
3177 if charsets_operatorp(secondLast, [ "*", "^" ]) and
3178 apply(max, map(lambda([x],charsets_degree(x,vf)),last)) < df then (
3180 second(charsets_fcnormal([as[1],last[i]],ord,2)),
3182 return(charsets_prod(map(lambda([x],charsets_factoras(x,as, ord)),
3184 _inf : lcoeff ( expand ( f), vf),
3185 /* das : rand ( -2 * nv .. 3 * nv + length ( ord)), check next line */
3186 sol : makelist(var[i] = i + 1,i, 1,nv),
3187 while (lratsubst(sol,_inf)=0 or not charsets_isirr(lratsubst(sol,as),ord)) do
3188 sol : makelist(var[i] = rand (5*nv +length(ord))- 2 * nv,i,1,nv),
3189 ff : setify1(charsets_qfactor(
3190 charsets_cfactor( lratsubst(sol,f), lratsubst(sol,as), ord), [ vf ] )),
3191 if apply(max,map(lambda([x],charsets_degree(x,vf)),ff)) = df then return(f),
3192 if 1 < charsets_printlevel then (
3193 print("Heuristic tsfactor failed")),
3194 charsets_factoras ( f, as, ord, 0)
3196 /* subroutine for factoras */
3197 /* I am not sure if I translated this one correctly */
3198 charsets_summ( ss,r):=block(
3201 m:arrayapply(charsets_m,[r])-1,
3204 _ind:concat(charsets_k,r),
3205 temp:temp + subst(i,_ind,ss)),
3209 for i:0 thru charsets_m[r-1] do (
3210 summ:charsets_summ( ss, r - 1),
3213 /* subroutine for factoras */
3215 charsets_coeff(as,ss,r,ord):=block([k,i,j,qs, temp],
3218 for j : r thru 1 step -1 do (
3219 for i : 1 thru length(qs) do (
3220 for k : 0 thru charsets_m[j] -1 do (
3221 temp : charsets_adjoin2(coeff(qs[i],charsets_lvar( as[j], ord),k),temp)))),
3222 charsets_setdifference( temp, setify1([0]))
3224 /* subroutine for factoras */
3226 charsets_getvars ( as):=block([ _ind,ind1,i],
3227 if charsets_operatorp(as, charsets_ListOrSet) then
3228 apply(charsets_union,map(charsets_getvars,as))
3231 ind1 : listofvars ( as),
3233 if subvarp(i) then (
3234 if part( i, 0) = charsets_g or part( i, 0) = charsets_h then (
3235 _ind : charsets_adjoin2(i, _ind))),
3238 /* find rational zeros of poly set ps */
3240 charsets_solveps ( ps,lst):=block(
3241 [ cs,ord,sol,j,phi,qs,qs1,n,factorset,last,temp,flag],
3242 if 1 < charsets_printlevel then
3243 print("solveps: trying rational solutions of equations:",
3244 length(ps),length(lst)),
3245 if 3 < charsets_printlevel then print(charsets_index( ps, lst)),
3246 ord : charsets_reorder(lst, charsets_degord, ps),
3248 ml2(cs,factorset, charsets_fqcharsetn( ps, ord, [setify1([]),setify1([])])),
3249 factorset : factorset[1],
3250 phi : setify1([ ps ]),
3252 for n : 1 while phi # setify1([]) do (
3253 if 6 < n + length( phi) or sol = setify1([FAIR]) then return( flag:FAIR),
3254 if sol # setify1([]) then return (false),
3256 cs : charsets_charseta ( phi[1], ord, charsets_wcharsetn),
3257 factorset : setify1([])),
3258 ml2(temp,qs1,charsets_solveasr( cs, ord)),
3259 sol : charsets_union(temp, sol),
3260 if n = 1 then (sol : charsets_verify ( sol, ps, ord)),
3261 qs : charsets_union ( charsets_factorps ( qs1), charsets_factorps ( factorset) ),
3262 last:charsets_qbasset ( qs, ord),
3263 qs : charsets_union(last, charsets_setdifference ( qs, setify1([ (last) ]) )),
3264 if qs # setify1([]) then (
3265 if 1 < length ( phi) then (
3266 phi : setify1([ part(phi, makelist(i,i,2,length ( phi))), map( [ (phi[1]), qs[j] ] /* $ ( ( j
3267 = 1 .. length ( qs) ))*/) ]))
3270 phi : setify1([ map( [ (phi[1]), qs[j] ] /* $ ( ( j
3271 = 1 .. length ( qs) ))*/) ])))
3274 if 1 < length ( phi) then (
3275 phi : setify1([ part(phi, makelist(i,i,2,length ( phi))) ]))
3277 else ( phi : setify1([])))),
3278 if flag # false then return(flag),
3279 if sol = setify1([]) then (
3283 /* subroutine for solveps */
3285 charsets_verify ( sol,ps,ord):=block( [ i,j,sss,last,retval],
3286 retval:charsets_setify([]),
3288 if setify1(simplify( subst(soli,ps))) = setify1([0]) then
3289 return( retval:setify1(soli))
3291 last:charsets_setify([]),
3292 for solij in soli do last:charsets_adjoin2(first(solij)- second(solij),last),
3293 sss : setify1(charsets_solveps( charsets_union ( ps,last), ord)),
3294 if sss # setify1([]) then return( retval:sss)),
3297 /* prepare a list of triangular forms from poly set ps */
3299 charsets_trisersub ( ps,ord):=block(
3300 [ qs,cs,iss,n,i,qhi,qsi,factorset,csno,ppi,qqi,_ind,mem,fset4],
3302 for i : 1 thru length ( ps) do(
3303 if length ( expand ( ps[i]) ) < 3 then (
3307 ml2( cs, factorset, charsets_fcharseta( ps, ord, charsets_charsetn)))
3309 ml2( cs, factorset, charsets_fcharseta( ps, ord, charsets_qcharsetn))),
3310 qhi : setify1([setify1(ps)]),
3315 for n : 0 while qhi # setify1([]) do (
3316 qhi : sort ( qhi, charsets_nopsord),
3318 ppi : charsets_select ( ppi, length ( qs) ),
3319 qqi : charsets_union(qqi,ppi[2]),
3320 if n = 0 then ( ppi : setify1([]))
3322 ppi : charsets_union( setify1(qs), setify1(ppi[1])),
3324 for i : 1 thru length ( ps) do(
3325 if length ( expand ( ps[i])) < 3 then ( _ind : 1,return(false))),
3327 cs:charsets_nopower(charsets_charseta( qs, ord, charsets_charsetn)),
3328 factorset : setify1([]))
3330 fset4: if (listp(qs) and (qs # []) and (listp(first(qs))))
3331 then first(qs) else qs,
3332 if (qs # mem) and (4 < charsets_degree (fset4[1], ord)) then (
3333 ml2(cs,factorset,charsets_fcharseta(qs,ord,charsets_qcharsetn)))
3335 if (length ( qs) - 3) < length ( ord) then (
3336 ml2(cs,factorset, charsets_fcharseta(qs,ord,charsets_wcharsetn)))
3338 cs : charsets_nopower (
3339 charsets_charseta ( qs, ord, charsets_wcharsetn)),
3340 factorset : setify1([]))))),
3342 if 1 < charsets_printlevel then (
3344 print("Characteristic set produced",csno,length(qhi),
3345 length(qsi),length (qs),cs)),
3346 if 0 < charsets_class ( cs, ord) then (
3347 iss : charsets_initialset ( cs[1], ord),
3348 if charsets_simpa ( iss, cs, ord) # 0 then (
3349 qsi : charsets_union([cs],qsi)),
3350 iss : charsets_union ( iss, charsets_factorps ( factorset)))
3351 else ( iss : charsets_factorps ( factorset)),
3352 iss : charsets_adjoina ( iss, qs, qqi),
3353 if 1 < length ( qhi) then ( qhi : charsets_union(setify1([iss]), rest(qhi)))
3356 if qsi = setify1([]) then ( [])
3357 else (sort ( charsets_contract ( qsi, ord, - 1), charsets_lenord))
3362 /* find zeros of ascending set as */
3364 charsets_solveas ( cs,ord):=block( [ _is,ss,sol,solm,i,j,k,temp],
3365 sol:map("[",sort(solve(cs[1],charsets_lvar(cs[1],ord)),ordergreatp)),
3366 if 1 < length ( cs) then (
3367 for i : 2 thru length ( cs) do (
3368 _is : charsets_initial ( cs[i], ord),
3370 for j : 1 thru length ( sol) do (
3371 ss : map("[",sort(solve(setify1([subst(sol[j],cs[i])]),
3372 charsets_lvar ( cs[i], ord)),ordergreatp)),
3373 for k : 1 thru length ( ss) do (
3374 temp:subst(ss[k],_is),
3375 temp:subst(sol[j],temp),
3377 solm : charsets_adjoin2(append(sol[j], ss[k]),solm)))),
3381 /* find rational zeros of ascending set cs */
3386 num(c)*num(q/lcoeff(q))
3389 charsets_solveasr ( cs,ord):=block([ _is,ss,ts,sol,solm,i,j,k],
3391 if 0 < charsets_class ( cs[1], ord) then (
3392 sol : setify1(charsets_solvel( cs[1], charsets_lvar( cs[1], ord))),
3393 if 1 < length ( cs) then (
3394 for i : 2 thru length ( cs) do
3395 if 1 <= length ( sol) then (
3396 _is : charsets_initial ( cs[i], ord),
3398 for j : 1 thru length ( sol) do
3399 if simplify( subst(flatten(sol[j]),_is)) = 0 then (
3400 ts : setify1(cons( _is, ts)))
3402 ss :setify1(charsets_solvel( subst(flatten(sol[j]),cs[i]),
3403 charsets_lvar( cs[i], ord))),
3405 solm : charsets_adjoin2(charsets_union(k, sol[j]),solm)),
3407 else ( return(false))))
3408 else ( sol : setify1([])),
3412 /* find rational zeros of polynomial f wrt x: subroutine for solveasr */
3414 charsets_solvel ( f,x):=block( [ g,i,sol],
3416 if length( listofvars ( f) ) = 1 then (
3417 g : charsets_getfactor( f, x),
3419 sol : charsets_union(solve ( setify1([ i ]), setify1([ x ]) ),sol))
3421 g : charsets_factorps( setify1([ num( f) ]) ),
3423 if charsets_degree ( i, x) = 1 then (
3424 sol : charsets_union(solve( setify1([ i ]), setify1([ x ])),sol))),
3427 /* find a list of distinct linear factors of univariate poly f */
3428 charsets_getfactor ( ff,x):=block( [ last,f,i],
3429 f: factor(ratsimp(ff/gcd(ff,diff(ff,x)))),
3430 if charsets_degree(f,x) = 1 then [f]
3433 for i in f do if charsets_degree(i,x) = 1 then last:charsets_adjoin2(i,last),
3437 charsets_getfactor ( f,x):=block( [ q,qs,j],
3438 q : charsets_getfact ( f, x),
3440 if charsets_operatorp(q,"*") then (
3441 for j : 1 thru length ( q) do
3442 if not integerp(part( q, j)) then (
3443 if charsets_operatorp(part( q, j),"^") then (
3444 qs : setify1([ qs, num( part( part( q, j), 1)
3445 / lcoeff ( part( part( q, j), 1)) ) ]))
3447 qs : setify1([ qs, num( part( q, j) / lcoeff( part( q, j)))]))))
3448 else if charsets_operatorp(q,"^") then (
3449 qs : setify1([ qs, num( part( q, 1) / lcoeff ( part( q, 1)) )]))
3451 if not integerp(q) then (
3452 qs : setify1([ num( q / lcoeff ( q) ), qs ]))),
3456 /* find the product of linear factors of univar poly f */
3458 charsets_getfact ( ff,x):=block([i,f,last],
3459 if charsets_degree ( ff, x) = 1 then return ( ff),
3460 f: factor(ratsimp(ff/gcd(ff,diff(ff,x)))),
3463 if charsets_degree(i,x) = 1 then last:charsets_adjoin2(i,last),
3466 /* irreducible decomposition of algebraic variety defined by ps */
3468 charsets_irrvardec ( ps,ord,medset,[args]):=block(
3469 [ phi,psi,i,j,mem,qq,qs],
3470 if length(args) > 0 then args:true else args:false,
3473 if 1 < charsets_printlevel then ( print("Variable order chosen:",ord)),
3474 if not args then psi : charsets_irrcharser ( ps, ord, medset)
3476 psi : charsets_exirrcharser ( [ ps, 1 ], ord, medset),
3477 if psi # [ [] ] then (
3482 psi : append(psi, i[1])
3483 else psi:endcons(i, psi),
3486 for i : 1 thru length ( psi) do (
3487 if length ( psi[i]) <= qq then phi : endcons(psi[i],phi)),
3488 break("phi before sort",phi),
3489 phi : sort ( phi, lambda ([ a,b ], is( length ( a) < length ( b)))),
3492 if phi # [ [] ] then (
3493 if length ( phi) = 1 and args = true then (
3494 return ( [ (ps) ] )),
3495 if 1 < charsets_printlevel then (
3496 print("ivd: ics finished at",time (),length ( phi))),
3497 for i : 1 thru length ( phi) do(
3498 if not member(i, mem) then (
3499 qs : charsets_primebasis ( phi[i], ord),
3500 if 1 < charsets_printlevel then (
3501 print("ivd: finite basis found:",length ( phi),i, qs)),
3502 for j : i + 1 thru length ( phi) do
3503 if not member(j, mem) and length ( phi[i]) # length ( phi[j])
3505 if charsets_remseta ( qs, phi[j], ord) = setify1([])
3507 mem : setify1([ j, (mem) ]))),
3508 psi : [ (psi), qs ])),
3509 (sort ( [ (psi) ], charsets_lenord)))
3512 /* prime basis of cs */
3514 charsets_primebasis ( cs,ord):=block(
3516 if length ( cs) = length ( ord)
3521 _is : charsets_initialset ( cs, ord)),
3522 charsets_saturbasis ( cs, _is, ord)
3524 /* basis of saturation of ps wrt js */
3526 charsets_saturbasis ( ps,js,ord):=block(
3528 if js # setify1([]) then (
3529 qs : [ (ps), makelist(charsets_z[j] * js[j] - 1,j,1,length ( js) ) ],
3530 /* is this just a partial reverse */
3531 zz : makelist(charsets_z[length ( js) - j + 1],j,1,length ( js)),
3532 gb : poly_reduced_grobner ( qs, [ (zz), reverse(ord) ]),
3534 for j : 1 thru length ( gb) do
3535 if charsets_setdifference ( setify1([ (zz) ]), listofvars ( gb[j]) )
3538 qs : [ gb[j], qs ]))
3542 /* primary decomposition of polynomial ideal generated by ps */
3545 charsets_pridealdec ( qs,ord,medset):=block(
3546 [ ps,phi,psi,fs,pi,ph,e,i,ss,S,j,gb,gb1,urd,vrd,f,gs,k,n,_ind,indb,con,sep,wtd,tc,tco,last],
3547 ps : charsets_setdifference ( setify1([ (charsets_expand ( qs)) ]), setify1([ 0 ]) ),
3548 ps : poly_reduced_grobner ( ps, charsets_reverse ( ord), lex),
3549 phi : [ [ ps, 1, 0, setify1([ 1 ]) ] ],
3552 for n : 1 while phi # [] do (
3554 phi : [ part(phi, makelist(i,i,2,length ( phi))) ], /* rest? */
3562 fs : poly_reduced_grobner ( fs, charsets_reverse ( ord), lex),
3563 if member(1, fs) then ( _ind : false)
3564 else if charsets_contain ( fs, ph, ord, plex) then (
3566 if _ind = true then (
3567 pi : [ charsets_irrvardec ( fs, ord, medset, 0, 0) ],
3568 if pi # [ [] ] then (
3570 if 1 < charsets_printlevel then (
3571 print("pid: ivd finished at",time (),e)),
3572 for i : 1 thru e do (
3578 ss : charsets_union ( ss, setify1([ charsets_takele ( charsets_setdifference ( setify1([ (pi[j]) ]), setify1([ (pi[i]) ]) ), pi[i], ord) ]) )),
3579 ss : charsets_prod ( charsets_factorps ( ss) ),
3580 gb : charsets_saturbasis ( fs, setify1([ ss ]), ord))
3583 gb : poly_reduced_grobner ( fs, charsets_reverse ( ord), lex)),
3584 urd : charsets_maxindset ( pi[i], ord),
3585 if urd = [] then ( f : 1)
3587 vrd : (charsets_setdifference ( setify1([ (ord) ]), setify1([ (urd) ]) )),
3588 gb1 : poly_reduced_grobner ( gb, [ vrd, (urd) ], lex),
3589 f : lcm ( map(part( grobner::leadmon ( gb1[j], [ vrd ] ), 1)/* $ ( ( j = 1 .. length ( gb1) ))*/))),
3590 f : charsets_prod ( charsets_factorps ( setify1([ f ]) ) ),
3591 gs : charsets_saturbasis ( gb, setify1([ f ]), ord),
3592 k : charsets_exponent ( gb, f, gs, ord),
3593 if 1 < charsets_printlevel then (
3594 print("pid: primary component found:",length ( psi) + 1,length ( phi),e,i),
3596 if psi = setify1([]) then (
3597 psi : setify1([ [ gs, pi[i] ] ]), ph : gs)
3599 charsets_union ( psi, setify1([ [ gs, pi[i] ] ]) ),
3602 ph : charsets_idealint ( ph, gs, ord),
3603 if charsets_contain ( ps, ph, ord, plex)
3604 then ( con : true, return(false)))),
3605 tco : charsets_idealint ( tco, charsets_saturbasisR ( gs, setify1([ sep
3606 * ss ]), ord), ord),
3607 if 0 < charsets_class ( f, ord) then (
3608 if charsets_class ( sep * ss, ord) = 0 then (
3609 charsets_union ( setify1([ (gb) ]), setify1([ f ^ k ]) ))
3611 charsets_saturbasis ( charsets_union ( setify1([ (gb) ]), setify1([ f
3612 ^ k ]) ), setify1([ sep * ss ]), ord)),
3613 indb : not charsets_contain ( %, charsets_idealintR ( ph, tc, ord), ord, plex),
3614 if indb = true then (
3615 indb : charsets_satisfy ( charsets_union ( setify1([ (gb) ]), setify1([ f
3616 ^ k ]) ), sep * ss, ord),
3618 phi : [ (phi), [ charsets_union ( setify1([ (gb) ]), setify1([ f
3619 ^ k ]) ), sep * ss, wtd + 2, tc ] ]))),
3620 S : charsets_union ( S, setify1([ ss ^ charsets_exponent ( fs, ss, gb, ord) ]) )),
3621 if con then return(false),
3622 S : charsets_union ( setify1([ (fs) ]), S),
3623 if not member(1, S) then (
3624 if charsets_class ( sep, ord) = 0 then S
3626 charsets_saturbasis ( S, setify1([ sep ]), ord)),
3627 not charsets_contain ( %, charsets_idealintR ( ph, tco, ord), ord, plex),
3629 phi : [ (phi), [ S, sep, wtd + 2, tco ] ]))),
3630 phi : sort ( phi, charsets_wtdorder))),
3631 if psi = setify1([]) or psi = setify1([ [ 1 ] ]) then ( [])
3633 (sort ( [ charsets_remred ( [ (charsets_setdifference ( psi, setify1([ [ 1 ] ]) )) ], ord) ], charsets_lenord)))
3635 /* weight ordering */
3637 charsets_wtdorder ( a,b):=block(
3645 /* radical ideal membership test - is zero(ps/g) empty? */
3647 charsets_satisfy ( ps,g,ord):=block(
3648 if charsets_class ( g, ord) = 0 then (
3650 else if member(g, ps) or member(g ^ 2, ps) or member(g ^ 3, ps) then (
3652 else if charsets_contain ( ps, setify1([ g ]), ord, plex) then (
3654 else if charsets_eicsTest ( [ ps, g ], ord, charsets_charsetn) = [] then (
3659 /* remove redundant poly sets from phi */
3661 charsets_remred ( phi,ord):=block(
3662 (charsets_remrsub ( charsets_reverse ( charsets_remrsub ( phi, ord) ), ord))
3664 /* main subroutine for remred */
3666 charsets_remrsub ( phi,ord):=block(
3670 for i : 1 thru length ( phi) do
3671 if not member(i, mem)
3673 for j : i + 1 thru length ( phi) do
3674 if not member(j, mem)
3676 if charsets_contain ( phi[j][1], phi[i][1], ord, plex)
3678 mem : setify1([ (mem), j ]))),
3679 ph : [ (ph), phi[i] ]),
3682 /* test: does ideal(ps) contain idealqs? */
3684 charsets_contain ( ps,qs,ord,pt):=block(
3686 if 1 < charsets_printlevel
3688 print("containment test starts at",time ())),
3689 X : charsets_reverse ( ord),
3691 if grobner::normalf ( q, ps, X, pt) # 0
3696 /* reverse a list */
3698 charsets_reverse ( ord):= reverse(ord)$
3700 /* take from qs an element which is not in ideal(gb) */
3702 charsets_takele ( gs,gb,ord):=block(
3704 X : charsets_reverse ( ord),
3705 ps : charsets_reverse ( sort ( [ (gs) ], charsets_nopsord) ),
3706 for i : 1 thru length ( ps) do
3707 if grobner::normalf ( ps[i], gb, X, plex) # 0
3710 error ("Check Here!")
3712 /* maximal independent set modulo gb */
3714 charsets_maxindset ( gb,ord):=block(
3715 [ j,x,g,_ind,u,urd],
3719 u : charsets_union ( urd, setify1([ x ]) ),
3721 if charsets_setdifference ( listofvars ( part( grobner::leadmon ( g, charsets_reverse ( ord), plex), 2)), u)
3731 /* compute the exponent */
3733 charsets_exponent ( ps,f,qs,ord):=block(
3738 print("Check PID exponent!",k)),
3739 if setify1([ (charsets_idealquo ( ps, f ^ k, ord)) ]) = setify1([ qs ])
3742 if 2 < charsets_printlevel
3744 print("pid: exponent found:",k)),
3747 /* ideal quotient */
3749 charsets_idealquo ( ps,f,ord):=block(
3751 if charsets_operatorp(f, charsets_ListOrSet)
3753 qs : charsets_idealquo ( ps, f[1], ord),
3756 [ part(f, makelist(i,i,2,length ( f))) ],
3757 qs : charsets_idealint ( qs, charsets_idealquo ( ps, %, ord), ord)),
3760 qs : charsets_idealint ( ps, f, ord),
3761 poly_reduced_grobner ( setify1([ map(simplify ( qs[j] / f) /* $ ( ( j = 1 .. length ( qs) ))*/) ]), charsets_reverse ( ord), lex))
3763 /* ideal charsets_intersection */
3765 charsets_idealint ( ps,f,ord):=block(
3767 if 1 < charsets_printlevel
3769 print("ideal charsets_intersection starts at",time ())),
3770 if charsets_operatorp(f, charsets_ListOrSet)
3772 qs : [ map(zz * ps[j]/* $ ( ( j = 1 .. length ( ps) ))*/), map(( ( 1 - zz))
3773 * f[j]/* $ ( ( j = 1 .. length ( f) ))*/) ])
3776 qs : [ map(zz * ps[j]/* $ ( ( j = 1 .. length ( ps) ))*/), ( ( 1 - zz)) * f ]),
3777 gb : poly_reduced_grobner ( qs, [ zz, map(ord[length ( ord) - j + 1]/* $ ( ( j = 1 .. length ( ord) ))*/) ], lex),
3779 for j : 1 thru length ( gb) do
3780 if charsets_setdifference ( setify1([ zz ]), listofvars ( gb[j]) ) = setify1([ zz ])
3782 qs : [ gb[j], qs ]),
3783 if 1 < charsets_printlevel
3785 print("ideal charsets_intersection finished at",time ())),
3788 /* ideal charsets_intersection - with remember */
3789 /* I think this should be memoized */
3790 charsets_idealintR ( ps,f,ord):=block(
3792 if 1 < charsets_printlevel
3794 print("ideal charsets_intersection starts at",time ())),
3795 if charsets_operatorp(f, charsets_ListOrSet)
3797 qs : [ map(zz * ps[j]/* $ ( ( j = 1 .. length ( ps) ))*/), map(( ( 1 - zz))
3798 * f[j]/* $ ( ( j = 1 .. length ( f) ))*/) ])
3801 qs : [ map(zz * ps[j]/* $ ( ( j = 1 .. length ( ps) ))*/), ( ( 1 - zz)) * f ]),
3802 gb : poly_reduced_grobner ( qs, [ zz, map(ord[length ( ord) - j + 1]/* $ ( ( j = 1 .. length ( ord) ))*/) ], lex),
3804 for j : 1 thru length ( gb) do
3805 if charsets_setdifference ( setify1([ zz ]), listofvars ( gb[j]) ) = setify1([ zz ])
3807 qs : [ gb[j], qs ]),
3808 if 1 < charsets_printlevel
3810 print("ideal charsets_intersection finished at",time ())),
3813 /* basis of the saturation of ideal(ps) wrt js */
3814 /* Another memoized function */
3815 charsets_saturbasisR ( ps,js,ord):=block(
3817 if js # setify1([]) then (
3818 qs : [ (ps), map(charsets_z[j] * js[j] - 1, j,1,length ( js) ) ],
3819 zz : makelist(charsets_z[ length ( js) - j + 1], j, 1,length ( js) ),
3820 gb : poly_reduced_grobner ( qs, [ (zz), map(ord[length ( ord)
3821 - j + 1]/* $ ( ( j = 1 .. length ( ord) ))*/) ], lex),
3823 for j : 1 thru length ( gb) do(
3824 if charsets_setdifference ( setify1([ (zz) ]), listofvars ( gb[j]) )
3827 qs : [ gb[j], qs ])))
3832 /* the extended irreducible char series of polyset ps */
3833 /* test: is zero(ps) empty? */
3835 charsets_eicsTest ( ps,ord,medset):=block(
3836 [ qs,cs,__is,iss,n,i,j,qhi,qsi,r,rr,factorset,mind,fset,_ind,ts,den,last],
3837 if charsets_operatorp(ps[1], charsets_ListOrSet) then (
3838 qhi : setify1([ ps ]))
3839 else ( qhi : setify1([ [ ps, 1 ] ])),
3840 if medset = charsets_basset then ( mind : true) else ( mind : false),
3842 if 1 < charsets_printlevel then (
3843 print("radical membership test starts at",time ())),
3844 for n : 0 while qhi # setify1([]) and qsi = setify1([]) do (
3848 last:apply(eval_string(concat("charsets_f", substring(medset,9,length ( medset) - 1))),[ qs, ord, [ setify1([]), listofvars ( qs) ], fset ]),
3849 ml2(cs,factorset, charsets_removecont ( last, ord)),
3850 factorset : charsets_union ( factorset, fset[1]))
3852 last:apply(eval_string(concat("charsets_", substring(medset,9,length ( medset) - 1))), [ qs, ord ]),
3853 ml2(cs,factorset, charsets_removecont ( last, ord))))
3856 cs : charsets_fcharseta ( [ qs ], ord, medset),
3857 factorset : part( cs[2], 2),
3858 ml2(cs,ts, charsets_removecont ( cs[1],ord)),
3859 factorset : charsets_union ( factorset, ts))
3861 last:charsets_charseta ( [ qs ], ord, medset),
3862 ml2(cs,factorset, charsets_removecont ( last, ord))),
3863 if 1 < charsets_printlevel then (
3864 print("characteristic set produced"),
3866 if 0 < charsets_class ( cs[1], ord) then (
3867 ml2(ts,den, charsets_irras ( cs, ord, _ind)),
3871 if not charsets_subset ( cs, qs) then (
3872 cs : charsets_charseta ( setify1([ cs, qs ]), ord, medset)),
3873 if 1 < charsets_printlevel then (
3874 print("characteristic set produced"),
3876 if 0 < charsets_class ( cs[1], ord) then (
3877 ml2(ts,den, charsets_irras ( cs, ord, _ind)),
3880 __is : charsets_union ( charsets_initialset ( cs, ord), charsets_factorps ( factorset) ),
3881 if length ( cs) = length ( ord) then (
3882 rr : charsets_nopower ( qhi[1][2]))
3884 rr : charsets_nopower ( charsets_prod ( setify1([ qhi[1][2], (__is) ]) ) )),
3885 last:charsets_premas ( rr, cs, ord),
3886 r : charsets_simp ( last, cs, ord),
3889 qsi : setify1([ cs, (qsi) ]))
3891 qsi : setify1([ [ cs, charsets_simpb ( r, rr) ], (qsi) ])))))
3893 __is : charsets_factorps ( factorset),
3897 __is : charsets_union ( charsets_initialset ( setify1([ part(cs, makelist(i,i,1,ts[2]
3898 - 1)) ]), ord), charsets_factorps ( factorset) ))
3900 __is : charsets_factorps ( factorset))))
3902 __is : charsets_factorps ( factorset),
3905 if length ( ord) <= length ( ps) + 1 then (
3907 iss : setify1([ iss, [ setify1([ i, qs ]), qhi[1][2] ] ]))
3909 for i : 1 thru length ( __is) do(
3910 if i = 1 then ( 1) else (
3911 product ( __is[j], j, 1, i - 1)),
3912 iss : setify1([ iss, [ setify1([ qs, __is[i] ]), %
3914 if ts[2] # 0 and ts[1] # setify1([]) then (
3916 if not charsets_subset ( cs, qs) then (
3917 charsets_charseta ( setify1([ cs, qs ]), ord, medset))
3921 if ts[2] = 1 then ( cs : qs)
3923 cs : setify1([ qs, part(cs, makelist(i,i,1,ts[2]
3926 iss : setify1([ iss, [ setify1([ cs, i ]), charsets_prod ( setify1([ den, qhi[1][2], (__is) ]) ) ] ]),
3927 if 0 < charsets_class ( den, ord) and ts[2] < charsets_class ( ts[1][1], ord) then (
3928 iss : setify1([ iss, [ setify1([ cs, den ]), qhi[1][2] ] ]))),
3929 if 1 < length ( qhi) then (
3930 qhi : setify1([ iss, part(qhi, makelist(i,i,2,length ( qhi))) ]))
3933 if qsi # setify1([])
3935 maplist(lambda([x],x),qsi))
3938 /* ordering wrt length */
3940 charsets_lenord ( a,b):=block(
3941 [len_a : charsets_length(a),
3942 len_b : charsets_length(b)],
3943 if len_b < len_a then ( true) else ( false)
3947 /* if elements are lists sort on the length of the first element */
3948 charsets_carorderp(a,b):=block([a1,b1],
3949 a1:if listp(a) then first(a) else a,
3950 b1:if listp(b) then first(b) else b,
3951 charsets_setorderp(a1,b1)
3954 charsets_complexityp(a,b):=block(
3955 [ca:second(complexity(a)),cb:second(complexity(b))],
3956 if ca < cb then true else (
3957 if ca > cb then false
3958 else ordergreatp(a,b))
3961 charsets_setorder_reversep(a,b):=
3962 if not mapatom(a) and not mapatom(b)
3964 if length(a) > length(b) then true
3965 else(if length(a) < length(b) then false else ordergreatp(a,b))
3967 ordergreatp (a, b) $
3969 charsets_setorderp(a,b):=
3970 if not mapatom(a) and not mapatom(b)
3972 if length(a) < length(b) then true
3973 else(if length(a) > length(b) then false else orderlessp(a,b))
3977 charsets_canonlt:charsets_setorderp$
3978 utma():=apply(untrace,trace)$
3979 tracesets():=trace(intersect, charsets_union, charsets_complement, charsets_setdifference,charsets_symmdifference,
3980 charsets_powerset, charsets_setify, charsets_subset, charsets_setp, charsets_subsetp, charsets_disjointp,charsets_canonlt)$
3983 charsets_mcharset, charsets_iniset, charsets_irrvardec,
3984 charsets_trisetc, charsets_simp, charsets_reordera, charsets_reorderb,
3985 charsets_fsubtriset, charsets_newfactoras,
3986 charsets_irras, charsets_fcharser, charsets_irrcharser,
3987 charsets_fcharseta, charsets_initialset,
3988 charsets_adjoina, charsets_verify, charsets_trisersub,
3990 charsets_fcharsetsub, charsets_fcnorm,charsets_trivial,
3991 charsets_fcnormal, charsets_fcharsetn,
3992 charsets_subtriset, charsets_qirrcharser,
3993 charsets_charser, charsets_charset,
3994 charsets_subtrisetc,
3995 charsets_exirrcharser, charsets_eics, charsets_gcdex, charsets_ics,
3996 charsets_charseta, charsets_remset, charsets_mecs, charsets_qbasset,
3997 charsets_qirras, charsets_index, charsets_solveas, charsets_adjoin3,
4000 charsets_fwcharsetn, charsets_reorder,
4001 charsets_solvel, charsets_ecs,
4003 charsets_fsubtrisetsub, charsets_wcharsetn,
4004 charsets_contractsub, charsets_union, charsets_summ,
4005 charsets_triser, charsets_select, charsets_triset, charsets_solveps,
4006 charsets_getfactor, charsets_mrank, charsets_qics,
4008 charsets_fqcharsetn, charsets_ivd, charsets_charseries,
4009 charsets_newfactorassub, charsets_wbasset, charsets_ftriset,
4010 charsets_coeff, charsets_measure, charsets_simpa,
4011 charsets_simpb, charsets_fexcharser,
4013 charsets_brank,charsets_degreel,charsets_deg0,charsets_degpsmax,
4014 charsets_degpsmin,charsets_degord,
4015 charsets_prem1,charsets_compress,
4016 charsets_lvar,charsets_nopower,
4017 charsets_prem,charsets_initialset1,
4018 charsets_class,charsets_removecont,
4019 charsets_subrank,charsets_factorps, charsets_movefactor,
4020 charsets_rank,charsets_removefactor,
4021 charsets_sort,charsets_initial, charsets_remseta,
4022 content,primpart,charsets_nopsord, charsets_deg1,
4023 charsets_unigcd, charsets_charsetn, charsets_basset, charsets_minus,
4024 charsets_gcd, charsets_getvars, charsets_pfactor,charsets_premas,
4026 charsets_movefactorps,
4030 charsets_isirr,charsets_qfactor,
4031 charsets_cfactorsub,
4032 charsets_remsetb,charsets_tsfactor,charsets_qqfactor,
4033 charsets_contract, charsets_factoras,
4034 charsets_ftrisetc, charsets_qcharsetn,
4035 charsets_trank, charsets_prod, charsets_linas,charsets_primebasis,
4036 charsets_excharser, charsets_getfact,charsets_expand,
4039 setequal,setequal_member
4099 charsets_fcharsetsub,
4109 charsets_fwcharsetn,
4110 charsets_fqcharsetn,
4113 charsets_movefactor,
4114 charsets_removefactor,
4115 charsets_removecont,
4117 charsets_fsubtriset,
4118 charsets_fsubtrisetsub,
4121 charsets_subtrisetc,
4122 charsets_initialset1,
4126 charsets_initialset,
4130 charsets_charseries,
4137 charsets_fexcharser,
4138 charsets_irrcharser,
4147 charsets_exirrcharser,
4153 charsets_contractsub,
4156 charsets_qirrcharser,
4158 charsets_cfactorsub,
4159 charsets_newfactoras,
4162 charsets_newfactorassub,
4164 charsets_fcharsetna,
4169 charsets_arrangesub,
4170 charsets_movefactorps,
4195 charsets_primebasis,
4196 charsets_saturbasis,
4197 charsets_pridealdec,
4210 charsets_saturbasisr,
4214 charsets_complexityp,
4215 charsets_setorder_reversep,
4216 charsets_setorderp)$