Use 1//2 instead of ((rat simp) 1 2)
[maxima.git] / share / algebra / charsets / charsets.maple
blob76615d82f2018b82d124325ead739a4cd88fb2ed
1 # -*- mode: maplev; -*-
2 # vim: syntax=maple
3 # CharSets Version 1.0 (December 1990)
4 # CharSets Version 1.1 (January 1992) for Maple V
5 # CharSets Version 1.2 (January 1994) for Maple V.2
6 # CharSets Version 2.0 (February 1996) for Maple V.3
8 #####################################################################
9 # #
10 # CHARACTERISTIC SETS PACKAGE #
11 # #
12 # Author: Dongming Wang #
13 # Laboratoire LEIBNIZ #
14 # Institut IMAG, 46, avenue Felix Viallet #
15 # 38031 Grenoble Cedex, France #
16 # E-mail: Dongming.Wang@imag.fr #
17 # #
18 # Date: February 1996 #
19 # #
20 # Copyright (C) 1990-1996 by Dongming Wang #
21 # #
22 # Copyright Notice: Permission is granted to use, copy or re- #
23 # distribute this package, provided that the title is #
24 # retained and the file is not altered. #
25 # #
26 #####################################################################
28 #===================================================================#
29 # This package is implemented for computing characteristic sets #
30 # of (multivariate) polynomial sets, decomposing polynomial sets #
31 # into ascending sets and irreducible ascending sets, decomposing #
32 # algebraic varieties into irreducible components, decomposing #
33 # polynomial ideals into primary components, factorizing #
34 # polynomials over algebraic extension fields and solving systems #
35 # of polynomial equations. It is based on the method of charac- #
36 # teristic sets introduced by J. F. Ritt and developed by Wu Wen- #
37 # tsun. The algorithms with variants implemented here are on the #
38 # basis of a generalization given by this author. Other modifica- #
39 # tions are also made. For references, see #
40 # Ritt J. F. Differential Algebra. AMS, 1950. #
41 # Wang D. M. Characteristic Sets and Zero Structure of Polynomial #
42 # Sets. Lecture Notes, RISC-LINZ, 1989. #
43 # Wu W. T. Basic Principles of Mechanical Theorem Proving in #
44 # Elementary Geometries. J. Sys. Sci. & Math. Scis. 4 (1984) #
45 # 207-235; J. Automated Reasoning 2 (1986) 221-252. #
46 #===================================================================#
48 # 1st change on May 29, 1991
49 # 2nd change on September 22, 1991
50 # 3rd change in December 1991
51 # 4th change in May 1992
52 # 5th change in October 1993
53 # 6th change in January 1994
54 # 7th change in April 1994
55 # 8th change in April 1995
56 # 9th change in August 1997 (for maxindset)
57 # 10th change in February 1998 (for class and lvar)
59 ##### Part 0. Definition of User Functions #####
61 charsets[charset] := proc() `charsets/charset`(args) end:
63 charsets[mcharset] := proc() `charsets/mcharset`(args) end:
65 charsets[charser] := proc() `charsets/charser`(args) end:
67 charsets[mcs] := proc() `charsets/mcs`(args) end:
69 charsets[ecs] := proc() `charsets/ecs`(args) end:
71 charsets[mecs] := proc() `charsets/mecs`(args) end:
73 charsets[ics] := proc() `charsets/ics`(args) end:
75 charsets[qics] := proc() `charsets/qics`(args) end:
77 charsets[eics] := proc() `charsets/eics`(args) end:
79 charsets[ivd] := proc() `charsets/ivd`(args) end:
81 charsets[pid] := proc() `charsets/pid`(args) end:
83 charsets[remset] := proc() `charsets/remset`(args) end:
85 charsets[cfactor] := proc() `charsets/cfactor`(args) end:
87 charsets[iniset] := proc() `charsets/iniset`(args) end:
89 charsets[csolve] := proc() `charsets/csolve`(args) end:
91 charsets[triser] := proc() `charsets/triser`(args) end:
93 # set of non-zero remainders of polys in ps wrt ascending set as
94 # user level function
95 `charsets/remset` :=
97 proc(ps,as,ord)
98 local ind,i;
99 if nargs <> 3 then ERROR(`wrong number of arguments`)
100 elif nops(ps) < 1 or nops(as) < 1 then ERROR(`no polynomials specified`)
101 elif nops(ord) < 1 then ERROR(`no indeterminates specified`)
102 elif not type(ord,list) then ERROR(ord,`must be a list`)
104 if member(false,map(type,ord,name)) then ERROR(`bad variable list`) fi;
105 ind := 0;
106 for i to nops(as) do
107 if `charsets/class`(as[i],ord) <= ind then
108 ERROR(
109 `second argument must be a non-contradictory (weak-, quasi-) ascend\
110 ing set`
112 else ind := `charsets/class`(as[i],ord)
115 if type(ps,{set,list}) then
116 if member(false,map(type,ps,polynom(polynom(rational),ord))) or
117 member(false,map(type,as,polynom(polynom(rational),ord))) then
118 ERROR(`input must be polynomials over Q in`,ord)
120 `charsets/remseta`(ps,as,ord)
121 else
122 if member(false,map(type,as,polynom(polynom(rational),ord))) then
123 ERROR(`input must be polynomials over Q in`,ord)
125 `charsets/premas`(ps,as,ord)
127 end:
129 # the char set of poly set ps: user function
130 `charsets/charset` :=
132 proc(ps,lst,medset,y)
133 local mset,ord,qs;
134 if nargs < 2 then ERROR(`too few arguments`)
135 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
136 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
137 elif 4 < nargs then ERROR(`too many arguments`)
139 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
140 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
141 ERROR(`input must be polynomials over Q in`,lst)
143 qs := {op(`charsets/expand`(ps))} minus {0};
144 if type(lst,list) then ord := lst
145 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
147 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
148 if 3 < nargs then y := ord fi;
149 if member(mset,{'charsetn','wcharsetn','qcharsetn','wbasset','qbasset',
150 'triset','trisetc','basset'}) then
151 `charsets/charseta`(qs,ord,`charsets/`.mset)
152 else
153 ERROR(`medial set must be one of ``basset``,``wbasset``, ``qbasset``,`.
154 ```charsetn``,``wcharsetn``,``qcharsetn``,``triset`` and ``trisetc```
157 end:
159 # modified from expand for lists
160 `charsets/expand` :=
162 proc(s)
163 local i;
164 if type(s,list) then ['expand(s[i])' $ ('i' = 1 .. nops(s))]
165 elif type(s,set) then {'expand(s[i])' $ ('i' = 1 .. nops(s))}
166 else expand(s)
168 end:
170 # the modified char set of poly set ps: user function
171 `charsets/mcharset` :=
173 proc(ps,lst,medset,y)
174 local mset,ord,qs;
175 if nargs < 2 then ERROR(`too few arguments`)
176 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
177 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
178 elif 4 < nargs then ERROR(`too many arguments`)
180 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
181 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
182 ERROR(`input must be polynomials over Q in`,lst)
184 qs := {op(`charsets/expand`(ps))} minus {0};
185 if type(lst,list) then ord := lst
186 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
188 if 3 < nargs then y := ord fi;
189 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
190 if member(mset,{'charsetn','wcharsetn','qcharsetn','wbasset','qbasset',
191 'triset','trisetc','basset'}) then
192 `charsets/fcharseta`(qs,ord,`charsets/`.mset)
193 else
194 ERROR(`medial set must be one of ``basset``,``wbasset``, ``qbasset``,`.
195 ```charsetn``,``wcharsetn``,``qcharsetn``,``triset`` and ``trisetc```
198 end:
200 # the set of all nonconstant factors of initials of polys in as: user function
201 `charsets/iniset` :=
203 proc(as,ord)
204 local ind,i;
205 ind := 0;
206 if nargs <> 2 then ERROR(`wrong number of arguments`)
207 elif nops(as) < 1 then ERROR(`no polynomials specified`)
208 elif nops(ord) < 1 then ERROR(`no indeterminates specified`)
209 elif not type(ord,list) then ERROR(ord,`must be a list`)
211 if member(false,map(type,ord,name)) then ERROR(`bad variable list`) fi;
212 if member(false,map(type,as,polynom(polynom(rational),ord))) then
213 ERROR(`input must be polynomials over Q in`,ord)
215 for i to nops(as) do
216 if `charsets/class`(as[i],ord) <= ind then
217 ERROR(
218 `first argument must be a non-contradictory (weak-, quasi-) ascending set`
220 else ind := `charsets/class`(as[i],ord)
223 `charsets/initialset`(`charsets/expand`(as),ord)
224 end:
226 # the char series of poly set ps: user function
227 `charsets/charser` :=
229 proc(ps,lst,medset,y)
230 local mset,ord,qs;
231 if nargs < 2 then ERROR(`too few arguments`)
232 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
233 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
234 elif 4 < nargs then ERROR(`too many arguments`)
236 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
237 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
238 ERROR(`input must be polynomials over Q in`,lst)
240 qs := {op(`charsets/expand`(ps))} minus {0};
241 if type(lst,list) then ord := lst
242 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
244 if 3 < nargs then y := ord fi;
245 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
246 if member(mset,{'charsetn','wcharsetn','wbasset','trisetc','basset'}) then
247 `charsets/charseries`(qs,ord,`charsets/`.mset)
248 else
249 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
250 ```charsetn``,``wcharsetn`` and ``trisetc```)
252 end:
254 # the char series of poly set ps -- allowing to remove factors
255 # user function
256 `charsets/mcs` :=
258 proc(ps,lst,medset,y)
259 local mset,ord,qs;
260 if nargs < 2 then ERROR(`too few arguments`)
261 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
262 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
263 elif 4 < nargs then ERROR(`too many arguments`)
265 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
266 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
267 ERROR(`input must be polynomials over Q in`,lst)
269 qs := {op(`charsets/expand`(ps))} minus {0};
270 if type(lst,list) then ord := lst
271 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
273 if 3 < nargs then y := ord fi;
274 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
275 if member(mset,{'charsetn','wcharsetn','wbasset','trisetc','basset'}) then
276 `charsets/fcharser`(qs,ord,`charsets/`.mset)
277 else
278 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
279 ```charsetn``,``wcharsetn`` and ``trisetc```)
281 end:
283 # the extended char series of poly set ps
284 # : user function
285 `charsets/ecs` :=
287 proc(ps,lst,medset,y)
288 local mset,ord,qs;
289 if nargs < 2 then ERROR(`too few arguments`)
290 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
291 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
292 elif 4 < nargs then ERROR(`too many arguments`)
294 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
295 if type(ps[1],list) then
296 if member(false,map(type,ps[1],polynom(polynom(rational),lst))) then
297 ERROR(`input must be polynomials over Q in`,lst)
299 elif member(false,map(type,ps,polynom(polynom(rational),lst))) then
300 ERROR(`input must be polynomials over Q in`,lst)
302 if type(ps[1],{set,list}) then
303 qs := [{op(`charsets/expand`(ps[1]))} minus {0},ps[2]]
304 else qs := {op(`charsets/expand`(ps))} minus {0}
306 if type(lst,list) then ord := lst
307 else
308 if type(ps[1],{set,list}) then
309 ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs[1])
310 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
313 if 3 < nargs then y := ord fi;
314 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
315 if member(mset,{'charsetn','wcharsetn','wbasset','trisetc','basset'}) then
316 `charsets/excharser`(qs,ord,`charsets/`.mset)
317 else
318 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
319 ```charsetn``,``wcharsetn`` and ``trisetc```)
321 end:
323 # the extended char series of poly set ps -- allowing to remove factors
324 # : user function
325 `charsets/mecs` :=
327 proc(ps,lst,medset,y)
328 local mset,ord,qs;
329 if nargs < 2 then ERROR(`too few arguments`)
330 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
331 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
332 elif 4 < nargs then ERROR(`too many arguments`)
334 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
335 if type(ps[1],list) then
336 if member(false,map(type,ps[1],polynom(polynom(rational),lst))) then
337 ERROR(`input must be polynomials over Q in`,lst)
339 elif member(false,map(type,ps,polynom(polynom(rational),lst))) then
340 ERROR(`input must be polynomials over Q in`,lst)
342 if type(ps[1],{set,list}) then
343 qs := [{op(`charsets/expand`(ps[1]))} minus {0},ps[2]]
344 else qs := {op(`charsets/expand`(ps))} minus {0}
346 if type(lst,list) then ord := lst
347 else
348 if type(ps[1],{set,list}) then
349 ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs[1])
350 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
353 if 3 < nargs then y := ord fi;
354 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
355 if member(mset,{'charsetn','wcharsetn','wbasset','trisetc','basset'}) then
356 `charsets/fexcharser`(qs,ord,`charsets/`.mset)
357 else
358 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
359 ```charsetn``,``wcharsetn`` and ``trisetc```)
361 end:
363 # the irreducible char series of poly set ps: user function
364 `charsets/ics` :=
366 proc(ps,lst,medset,y)
367 local mset,ord,qs;
368 if nargs < 2 then ERROR(`too few arguments`)
369 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
370 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
371 elif 4 < nargs then ERROR(`too many arguments`)
373 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
374 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
375 ERROR(`input must be polynomials over Q in`,lst)
377 qs := {op(`charsets/expand`(ps))} minus {0};
378 if type(lst,list) then ord := lst
379 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
381 if 3 < nargs then y := ord fi;
382 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
383 if member(mset,{'charsetn','trisetc','basset'}) then
384 `charsets/irrcharser`(qs,ord,`charsets/`.mset)
385 else
386 ERROR(
387 `medial set must be one of ``basset``,``charsetn```.` and ``trisetc```
390 end:
392 # the extended irreducible char series of poly set ps: user function
393 `charsets/eics` :=
395 proc(ps,lst,medset,y)
396 local mset,ord,qs;
397 if nargs < 2 then ERROR(`too few arguments`)
398 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
399 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
400 elif 4 < nargs then ERROR(`too many arguments`)
402 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
403 if type(ps[1],{set,list}) then
404 if member(false,map(type,ps[1],polynom(polynom(rational),lst))) then
405 ERROR(`input must be polynomials over Q in`,lst)
407 elif member(false,map(type,ps,polynom(polynom(rational),lst))) then
408 ERROR(`input must be polynomials over Q in`,lst)
410 if type(ps[1],{set,list}) then
411 qs := [{op(`charsets/expand`(ps[1]))} minus {0},ps[2]]
412 else qs := {op(`charsets/expand`(ps))} minus {0}
414 if type(lst,list) then ord := lst
415 else
416 if type(ps[1],{set,list}) then
417 ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs[1])
418 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
421 if 3 < nargs then y := ord fi;
422 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
423 if member(mset,{'charsetn','trisetc','basset'}) then
424 `charsets/exirrcharser`(`charsets/expand`(qs),ord,`charsets/`.mset)
425 else
426 ERROR(
427 `medial set must be one of ``basset``,`.```charsetn`` and ``trisetc```
430 end:
432 # the quasi-irreducible char series of poly set ps: user function
433 `charsets/qics` :=
435 proc(ps,lst,medset,y)
436 local mset,ord,qs;
437 if nargs < 2 then ERROR(`too few arguments`)
438 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
439 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
440 elif 4 < nargs then ERROR(`too many arguments`)
442 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
443 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
444 ERROR(`input must be polynomials over Q in`,lst)
446 qs := {op(`charsets/expand`(ps))} minus {0};
447 if type(lst,list) then ord := lst
448 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
450 if 3 < nargs then y := ord fi;
451 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
452 if member(mset,{'charsetn','wcharsetn','wbasset','trisetc','basset'}) then
453 `charsets/qirrcharser`(qs,ord,`charsets/`.mset)
454 else
455 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
456 ```charsetn``,``wcharsetn`` and ``trisetc```)
458 end:
460 # factorize poly f over algebraic number field with minimal polys in as
461 # wrt ord: user function
462 # used for linear transformation
463 `charsets/cfactor` :=
465 proc(f,as,ord)
466 local ind,inda,ff,i;
467 global `charsets/das`;
468 if nargs = 1 then RETURN(factor(f)) fi;
469 if nargs = 2 then ERROR(`inproper number of arguments`)
470 elif nops(as) < 1 then ERROR(`no polynomials specified`)
471 elif nops(ord) < 1 then ERROR(`no indeterminates specified`)
472 elif not type(ord,list) then ERROR(ord,`must be a list`)
473 elif 4 < nargs then ERROR(`too many arguments`)
475 if member(false,map(type,ord,name)) then ERROR(`bad variable list`) fi;
476 if member(false,map(type,as,polynom(polynom(rational),ord))) then
477 ERROR(`input must be polynomials over Q in`,ord)
479 ff := numer(f);
480 ind := 0;
481 for i to nops(as) do
482 inda := `charsets/class`(as[i],ord);
483 if inda <= ind then
484 ERROR(`second argument must be a non-contradictory ascending set`)
485 else ind := inda
488 if 1 < printlevel then
489 lprint(`Warning: be sure the ascending set is irreducible`)
491 if `charsets/class`(ff,ord) <= `charsets/class`(as[nops(as)],ord) then
492 factor(f)
493 else
494 sum('`charsets/degreel`(as[i],ord)','i' = 1 .. nops(as));
495 if `charsets/degreel`(ff,ord) < % then
496 `charsets/das` := [-1,1,-2,2,-3,false]
497 else `charsets/das` := [1,-1,2,-2,-3,false]
499 `charsets/cfactorsub`(factor(f),as,ord)
501 end:
503 # prepare a list of triangular forms from poly set ps: user function
504 `charsets/triser` :=
506 proc(ps,lst,y)
507 local i,ord,qs;
508 if nargs < 1 then ERROR(`too few arguments`)
509 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
510 elif 3 < nargs then ERROR(`too many arguments`)
511 elif nargs = 2 then
512 if nops(lst) < 1 then ERROR(`no indeterminates specified`) fi
514 if nargs = 2 then
515 if member(false,map(type,lst,name)) then ERROR(`bad variable list`)
518 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
519 ERROR(`input must be polynomials over Q in`,lst)
521 qs := {op(`charsets/expand`(ps))} minus {0};
522 if nargs < 2 then
523 ord := `charsets/reorder`(
524 [seq(op(indets(ps[i])),i = 1 .. nops(ps))],`charsets/degord`,qs)
525 elif type(lst,list) then ord := lst
526 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
528 if 2 < nargs then y := ord fi;
529 `charsets/trisersub`(qs,ord)
530 end:
532 # solve a set of poly eqs ps=0: user function
533 `charsets/csolve` :=
535 proc(ps,lst,y)
536 local i,ord,qsi,qs;
537 if nargs < 1 then ERROR(`too few arguments`)
538 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
539 elif 3 < nargs then ERROR(`too many arguments`)
540 elif nargs = 2 then
541 if nops(lst) < 1 then ERROR(`no indeterminates specified`) fi
543 if nargs = 2 then
544 if member(false,map(type,lst,name)) then ERROR(`bad variable list`)
547 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
548 ERROR(`input must be polynomials over Q in`,lst)
550 qs := {op(`charsets/expand`(ps))} minus {0};
551 if nargs < 2 then
552 ord := `charsets/reorder`(
553 [seq(op(indets(ps[i])),i = 1 .. nops(ps))],`charsets/degord`,qs)
554 elif type(lst,list) then ord := lst
555 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
557 if 2 < nargs then y := ord fi;
558 qsi := {`charsets/trisersub`(qs,ord)};
559 if qsi = {{}} then {}
560 else op({seq(`charsets/solveas`(qsi[i],ord),i = 1 .. nops(qsi))})
562 end:
564 # irreducible decomposition of algebraic variety defined by ps:
565 # user function
566 `charsets/ivd` :=
568 proc(ps,lst,medset,y)
569 local mset,ord,qs;
570 if nargs < 2 then ERROR(`too few arguments`)
571 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
572 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
573 elif 4 < nargs then ERROR(`too many arguments`)
575 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
576 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
577 ERROR(`input must be polynomials over Q in`,lst)
579 qs := {op(`charsets/expand`(ps))} minus {0};
580 if type(lst,list) then ord := lst
581 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
583 if 3 < nargs then y := ord fi;
584 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
585 if member(mset,{'charsetn','trisetc','basset'}) then
586 `charsets/irrvardec`(qs,ord,`charsets/`.mset)
587 else
588 ERROR(
589 `medial set must be one of ``basset``,`.```charsetn`` and ``trisetc```
592 end:
594 # primary decomposition of polynomial ideal generated by ps
595 # user function
596 `charsets/pid` :=
598 proc(ps,lst,medset,y)
599 local mset,ord,qs;
600 if nargs < 2 then ERROR(`too few arguments`)
601 elif nops(ps) < 1 then ERROR(`no polynomials specified`)
602 elif nops(lst) < 1 then ERROR(`no indeterminates specified`)
603 elif 4 < nargs then ERROR(`too many arguments`)
605 if member(false,map(type,lst,name)) then ERROR(`bad variable list`) fi;
606 if member(false,map(type,ps,polynom(polynom(rational),lst))) then
607 ERROR(`input must be polynomials over Q in`,lst)
609 qs := {op(`charsets/expand`(ps))} minus {0};
610 if type(lst,list) then ord := lst
611 else ord := `charsets/reorder`([op(lst)],`charsets/degord`,qs)
613 if 3 < nargs then y := ord fi;
614 if nargs < 3 then mset := 'charsetn' else mset := medset fi;
615 if member(mset,{'charsetn','trisetc','basset'}) then
616 `charsets/pridealdec`(qs,ord,`charsets/`.mset)
617 else
618 ERROR(
619 `medial set must be one of ``basset``,`.```charsetn`` and ``trisetc```
622 end:
624 ##### Part I. Routines for Computing Characteristic Sets #####
626 # the class of poly f wrt variable ordering ord
627 `charsets/class` := proc(f,ord)
628 local i;
629 options remember,system;
630 for i from nops(ord) by -1 to 1 do
631 if member(ord[i],indets(f)) then RETURN(i) fi
634 end:
636 # the leading variable of poly f wrt variable ordering ord
637 `charsets/lvar` :=
639 proc(f,ord)
640 local i;
641 options remember,system;
642 for i from nops(ord) by -1 to 1 do
643 if member(ord[i],indets(f)) then RETURN(ord[i]) fi
645 if 1 < printlevel then lprint(`Warning: lvar is called with constant`)
648 end:
650 # the index set of a poly (or a poly set f) wrt ord
651 `charsets/index` :=
653 proc(f,ord)
654 local i,g,ng;
655 if type(f,list) then
656 ['`charsets/index`(f[i],ord)' $ ('i' = 1 .. nops(f))]
657 elif type(f,set) then
658 {'`charsets/index`(f[i],ord)' $ ('i' = 1 .. nops(f))}
659 else
660 g := expand(f);
661 ng := `charsets/terms`(g);
662 if `charsets/class`(g,ord) = 0 then i := op(1,[op(indets(g)),O])
663 else i := `charsets/lvar`(g,ord)
665 g := degree(g,i);
666 `[`.ng.` `.i.` `.g.`]`
668 end:
670 # number of terms in g
671 `charsets/terms` := proc(g) if type(g,`+`) then nops(g) else 1 fi end:
673 # the initial of poly p wrt ord
674 `charsets/initial` :=
676 proc(p,ord)
677 local f;
678 options remember,system;
679 f := expand(p);
680 if `charsets/class`(f,ord) = 0 then 1
681 else lcoeff(f,`charsets/lvar`(f,ord)); numer(%/lcoeff(%))
683 end:
685 # modified rank of two polys: comparing further the rank
686 # of initials when f and g have same rank
687 `charsets/mrank` :=
689 proc(f,g,ord)
690 local cf,cg;
691 options remember,system;
692 cf := `charsets/class`(f,ord);
693 cg := `charsets/class`(g,ord);
694 if cf = 0 then true
695 elif cf < cg then true
696 elif cf = cg then
697 cf := `charsets/degreel`(f,ord);
698 cg := `charsets/degreel`(g,ord);
699 if cf < cg then true
700 elif cf = cg then
701 `charsets/mrank`(
702 `charsets/initial`(f,ord),`charsets/initial`(g,ord),ord)
703 else false
705 else false
707 end:
709 # modified rank of two polys: comparing further the rank of
710 # initials, the terms of initials and the terms of f and g
711 # when they are the same
712 `charsets/rank` :=
714 proc(f,g,ord)
715 local ind,find,cf,cg;
716 options remember,system;
717 find := `charsets/subrank`(f,g,ord,'ind');
718 if find and ind = 1 then
719 cf := nops(expand(`charsets/initial`(f,ord)));
720 cg := nops(expand(`charsets/initial`(g,ord)));
721 if cf < cg then true
722 elif cf = cg then
723 if nops(expand(f)) < nops(expand(g)) then true else false fi
724 else false
726 else find
728 end:
730 # subroutine for rank
731 `charsets/subrank` :=
733 proc(f,g,ord,ind)
734 local cf,cg;
735 options remember,system;
736 cf := `charsets/class`(f,ord);
737 cg := `charsets/class`(g,ord);
738 if cf = 0 then if cg = 0 then ind := 1 fi; true
739 elif cf < cg then true
740 elif cf = cg then
741 cf := `charsets/degreel`(f,ord);
742 cg := `charsets/degreel`(g,ord);
743 if cf < cg then true
744 elif cf = cg then
745 `charsets/subrank`(
746 `charsets/initial`(f,ord),`charsets/initial`(g,ord),ord,'ind')
747 else false
749 else false
751 end:
753 # the rank of two polys with same classes:
754 # used for computing triangular form
755 `charsets/trank` :=
757 proc(f,g,ord)
758 local cf,cg;
759 options remember,system;
760 cf := `charsets/degreel`(f,ord);
761 cg := `charsets/degreel`(g,ord);
762 if cf < cg then true
763 elif cf = cg then
764 `charsets/mrank`(
765 `charsets/initial`(f,ord),`charsets/initial`(g,ord),ord)
766 else false
768 end:
770 # modified pseudo division: I1^s1...Ir^sr*uu = q*vv + r,
771 # where I1, ..., I_r are all distinct factors of lcoeff(vv,x)
772 # and s1, ..., sr are chosen to be the smallest
773 `charsets/prem` :=
775 proc(uu,vv,x)
776 local r,v,dr,dv,l,t,lu,lv;
777 options remember,system;
778 if type(vv/x,integer) then subs(x = 0,uu)
779 else
780 r := expand(uu);
781 dr := degree(r,x);
782 v := expand(vv);
783 dv := degree(v,x);
784 if dv <= dr then l := coeff(v,x,dv); v := expand(v-l*x^dv)
785 else l := 1
787 if 1 < printlevel and 500 < nops(r)+nops(v) then
788 lprint(`pseudo-division:`,[nops(r),x,dr],[nops(v),x,dv])
790 while dv <= dr and r <> 0 do
791 gcd(l,coeff(r,x,dr),'lu','lv');
792 t := expand(x^(dr-dv)*v*lv);
793 if dr = 0 then r := 0 else r := subs(x^dr = 0,r) fi;
794 r := expand(lu*r)-t;
795 dr := degree(r,x)
799 end:
801 # pseudo remainder of poly f wrt ascending set as
802 `charsets/premas` :=
804 proc(f,as,ord)
805 local remd,i;
806 remd := f;
807 for i from nops(as) by -1 to 1 do
808 remd := `charsets/prem`(remd,as[i],`charsets/lvar`(as[i],ord))
810 if remd <> 0 then numer(remd/lcoeff(remd)) else 0 fi
811 end:
813 # set of non-zero remainders of polys in ps wrt ascending set as
814 `charsets/remseta` :=
816 proc(ps,as,ord)
817 local i;
818 {'`charsets/premas`(ps[i],as,ord)' $ ('i' = 1 .. nops(ps))} minus {0}
819 end:
821 # pseudo remainder of poly f wrt ascending set as -- version b
822 `charsets/premasb` :=
824 proc(f,as,ord)
825 local remd,i;
826 remd := f;
827 if 1 < nops(as) then
828 for i from nops(as) by -1 to 2 do
829 remd := `charsets/prem`(remd,as[i],`charsets/lvar`(as[i],ord))
832 if divide(remd,as[1]) then remd := 0
833 else remd := `charsets/prem`(remd,as[1],`charsets/lvar`(as[1],ord))
835 if remd <> 0 then numer(remd/lcoeff(remd)) else 0 fi
836 end:
838 # set of non-zero remainders of polys in ps wrt ascending set as -- version b
839 `charsets/remsetb` :=
841 proc(ps,as,ord)
842 local i;
843 {'`charsets/premasb`(ps[i],as,ord)' $ ('i' = 1 .. nops(ps))} minus {0}
844 end:
846 # reorder the list ord of variables wrt poly set ps
847 `charsets/reorder` :=
849 proc(ord,p,ps)
850 op(`charsets/reordera`(ord,ps));
851 [op(`charsets/reorderb`([op({op(ord)} minus {%})],p,ps)),%]
852 end:
854 # subroutine for reorder: first criterion
855 `charsets/reordera` :=
857 proc(ord,ps)
858 local qs,pp,orb,i;
859 if nops(ps) = 0 then ord
860 else
861 qs := {op(ps)};
862 orb := {op(ord)};
863 for i in orb do
864 pp := `charsets/deg0`(ps,i);
865 if nops(pp) = 1 then
866 RETURN(
867 [op(`charsets/reordera`([op(orb minus {i})],qs minus pp)),i]
873 end:
875 # subroutine for reorder -- modified from sort: second criterion
876 `charsets/reorderb` :=
878 proc(l,p,ps)
879 local n,tn,gap,i,j,temp,v;
880 n := nops(l);
881 tn := p;
882 for i to n do v[i-1] := l[i] od;
883 for gap from 4 while gap <= n do gap := 3*gap+1 od;
884 gap := iquo(gap,3);
885 while 0 < gap do
886 for i from gap to n-1 do
887 temp := v[i];
888 for j from i-gap by -gap to 0 do
889 if tn(v[j],temp,ps) then break fi; v[j+gap] := v[j]
891 v[j+gap] := temp
893 gap := iquo(gap,3)
895 ['eval(v[i],1)' $ ('i' = 0 .. n-1)]
896 end:
898 # determine the order between x and y wrt ps
899 `charsets/degord` :=
901 proc(x,y,ps)
902 if op(2,`charsets/degpsmax`(ps,y)) < op(2,`charsets/degpsmax`(ps,x)) then
903 true
904 elif op(2,`charsets/degpsmax`(ps,x)) < op(2,`charsets/degpsmax`(ps,y)) then
905 false
906 elif op(1,`charsets/degpsmax`(ps,y)) < op(1,`charsets/degpsmax`(ps,x)) then
907 true
908 elif op(1,`charsets/degpsmax`(ps,x)) < op(1,`charsets/degpsmax`(ps,y)) then
909 false
910 elif op(2,`charsets/degpsmin`(ps,x)) < op(2,`charsets/degpsmin`(ps,y)) then
911 true
912 elif op(2,`charsets/degpsmin`(ps,y)) < op(2,`charsets/degpsmin`(ps,x)) then
913 false
914 elif op(1,`charsets/degpsmin`(ps,y)) < op(1,`charsets/degpsmin`(ps,x)) then
915 true
916 elif op(1,`charsets/degpsmin`(ps,x)) < op(1,`charsets/degpsmin`(ps,y)) then
917 false
918 elif op(1,`charsets/deg1`(ps,y)) < op(1,`charsets/deg1`(ps,x)) then true
919 elif op(1,`charsets/deg1`(ps,x)) < op(1,`charsets/deg1`(ps,y)) then false
920 elif op(2,`charsets/deg1`(ps,y)) < op(2,`charsets/deg1`(ps,x)) then true
921 else false
923 end:
925 # the maximal degree of polys in qs wrt x
926 # and the number of polys having this degree
927 `charsets/degpsmax` :=
929 proc(qs,x)
930 local i,m,mm,ps;
931 options remember,system;
932 ps := expand(qs);
933 m := max('degree(ps[i],x)' $ ('i' = 1 .. nops(ps)));
934 mm := 0;
935 for i to nops(ps) do if degree(ps[i],x) = m then mm := mm+m fi od;
936 [mm,m]
937 end:
939 # the minimal non-zero degree of polys in qs wrt x
940 # and the number of polys having this degree
941 `charsets/degpsmin` :=
943 proc(qs,x)
944 local i,m,mm,ps;
945 options remember,system;
946 ps := expand(qs);
947 {'degree(ps[i],x)' $ ('i' = 1 .. nops(ps))} minus {0};
948 if % = {} then m := 0 else m := min(op(%)) fi;
949 mm := 0;
950 for i to nops(ps) do if degree(ps[i],x) = m then mm := mm+m fi od;
951 [mm,m]
952 end:
954 # determine if ps has one and only one poly involving x
955 `charsets/deg0` := proc(ps,x)
956 local i,ms;
957 ms := {};
958 for i in ps while nops(ms) < 2 do
959 if member(x,indets(i)) then ms := {i,op(ms)} fi
962 end:
964 # the minimal total degree of lcoeffs of polys in PS wrt x
965 # and the minimal number of terms of those lcoeffs
966 `charsets/deg1` :=
968 proc(PS,x)
969 local i,ps,qs,k;
970 options remember,system;
971 ps := expand(PS);
972 qs := {};
973 k := op(2,`charsets/degpsmin`(ps,x));
974 for i to nops(ps) do
975 if degree(ps[i],x) = k then qs := {op(qs),lcoeff(ps[i],x)} fi
977 [min('degree(qs[i],indets(qs[i]))' $ ('i' = 1 .. nops(qs))),
978 min('nops(expand(qs[i]))' $ ('i' = 1 .. nops(qs)))]
979 end:
981 # search an element with lowest rank in ps
982 # and assign the rest of polys to qs
983 `charsets/sort` :=
985 proc(ps,rank,ord,qs)
986 local l,i,qs1;
987 if nops(ps) = 1 then qs := []; ps[1]
988 else
989 l := ps[1];
990 qs1 := [];
991 for i from 2 to nops(ps) do
992 if rank(ps[i],l,ord) then qs1 := [l,op(qs1)]; l := ps[i]
993 else qs1 := [ps[i],op(qs1)]
996 qs := qs1;
999 end:
1001 # the difference of two lists
1002 `charsets/minus` := proc(ps,qs) [op({op(ps)} minus {op(qs)})] end:
1004 # the union of three lists
1005 `charsets/union` :=
1007 proc(ps1,ps2,ps3) [op(({op(ps1)} union {op(ps2)}) union {op(ps3)})] end:
1009 # the product of all elements in a list
1010 `charsets/prod` := proc(ps) local i; product('ps[i]','i' = 1 .. nops(ps)) end:
1012 `charsets/degree` := proc(f,x) degree(collect(f,x,normal),x) end:
1014 `charsets/degreel` :=
1016 proc(f,ord) expand(f); degree(%,`charsets/lvar`(%,ord)) end:
1018 # the basic set of poly set ps
1019 `charsets/basset` :=
1021 proc(ps,ord)
1022 local qs,qs1,i,b;
1023 if nops(ps) < 2 then ps
1024 else
1025 b := `charsets/sort`(ps,`charsets/rank`,ord,'qs1');
1026 qs := [];
1027 if 0 < `charsets/class`(b,ord) then
1028 for i in qs1 do
1029 if `charsets/brank`(i,b,ord) then qs := [i,op(qs)] fi
1031 else RETURN([b])
1033 [b,op(`charsets/basset`(qs,ord))]
1035 end:
1037 # the weak-basic set of poly set ps
1038 `charsets/wbasset` :=
1040 subs(`charsets/brank`=`charsets/wbrank`,
1041 `charsets/basset`=`charsets/wbasset`,
1042 op(`charsets/basset`)):
1044 # the quasi-basic set of poly set ps
1045 `charsets/qbasset` :=
1047 subs(`charsets/brank`=`charsets/qbrank`,
1048 `charsets/basset`=`charsets/qbasset`,
1049 op(`charsets/basset`)):
1051 # subroutines for basset, wbasset and qbasset
1052 `charsets/brank` :=
1054 proc(a,b,ord)
1055 if `charsets/degree`(a,`charsets/lvar`(b,ord)) < `charsets/degreel`(b,ord)
1056 then
1057 true
1058 else false
1060 end:
1062 `charsets/wbrank` :=
1064 proc(a,b,ord)
1065 if `charsets/class`(b,ord) < `charsets/class`(a,ord) and
1066 `charsets/brank`(`charsets/initial`(a,ord),b,ord) then
1067 true
1068 else false
1070 end:
1072 `charsets/qbrank` :=
1074 proc(a,b,ord)
1075 if `charsets/class`(b,ord) < `charsets/class`(a,ord) then true
1076 else false
1078 end:
1080 # the char set of poly set ps
1081 `charsets/charseta` :=
1083 proc(ps,ord,medset)
1084 local cs,rs,l,med;
1085 global `charsets/with`;
1086 if nops(ps) < 2 then [op(ps)]
1087 else
1088 if medset = `charsets/qcharsetn` then
1089 `charsets/with` := {};
1090 med := subs(`charsets/remseta` = `charsets/remsetaA`,
1091 `charsets/qcharsetn` = med,op(`charsets/qcharsetn`));
1092 cs := med(ps,ord)
1093 else cs := medset(ps,ord)
1095 if 0 < `charsets/class`(cs[1],ord) then
1096 if member(
1097 medset,{`charsets/wbasset`,`charsets/qbasset`,`charsets/basset`}
1098 ) then
1099 rs := `charsets/remseta`({op(ps)} minus {op(cs)},cs,ord)
1100 elif medset = `charsets/qcharsetn` and `charsets/checkwith`(
1101 `charsets/with`,`charsets/initialset1`(cs,ord)) then
1102 if 1 < printlevel then
1103 lprint(`Strategy for 0 remainder succeed`)
1105 RETURN(cs)
1106 else
1107 if medset = `charsets/qcharsetn` and 1 < printlevel then
1108 lprint(`Strategy for 0 remainder failed`)
1110 rs := `charsets/remsetb`({op(ps)} minus {op(cs)},cs,ord)
1112 else RETURN([1])
1114 if rs = {} then
1115 ['numer(cs[l]/lcoeff(expand(cs[l])))' $ ('l' = 1 .. nops(cs))]
1116 else `charsets/charseta`(`charsets/union`(rs,cs,ps),ord,medset)
1119 end:
1121 # the modified char set of poly set ps
1122 `charsets/fcharseta` :=
1124 proc(ps,ord,medset)
1125 local csf,fset;
1126 csf := `charsets/fcharsetsub`(
1127 `charsets/nopower`(ps),ord,medset,[{},indets(ps)],'fset');
1128 csf,`factors removed` = fset[1]
1129 end:
1131 # the main subroutine for fcharseta
1132 `charsets/fcharsetsub` :=
1134 proc(ps,ord,medset,fset1,fset)
1135 local cs,rs,l,fset3,fset2,ts,fmedset,med;
1136 global `charsets/with`;
1137 if nops(ps) < 2 then fset := fset1; [op(ps)]
1138 else
1139 if member(substring(medset,10 .. length(medset)),
1140 {'charsetn','wcharsetn','qcharsetn','triset','trisetc'}) then
1141 fmedset := `charsets/f`.(substring(medset,10 .. length(medset)));
1142 if fmedset = `charsets/fqcharsetn` then
1143 `charsets/with` := {};
1144 med := subs(`charsets/remseta` = `charsets/remsetaA`,
1145 `charsets/fqcharsetn` = med,op(`charsets/fqcharsetn`));
1146 cs := med(ps,ord,fset1,'fset2')
1147 else cs := fmedset(ps,ord,fset1,'fset2')
1149 if 2 < nops(indets(cs[1])) then
1150 cs := `charsets/removecont`(cs,ord,'ts');
1151 fset2 := [fset2[1] union ts,fset2[2]]
1153 if 0 < `charsets/class`(cs[1],ord) then
1154 if fmedset = `charsets/fqcharsetn` and `charsets/checkwith`(
1155 `charsets/with`,`charsets/initialset1`(cs,ord) union fset2[1]
1156 ) then
1157 if 1 < printlevel then
1158 lprint(`Strategy for 0 remainder succeed`)
1160 fset := fset2;
1161 RETURN(cs)
1162 else
1163 if medset = `charsets/qcharsetn` and 1 < printlevel then
1164 lprint(`Strategy for 0 remainder failed`)
1166 rs := `charsets/remsetb`({op(ps)} minus {op(cs)},cs,ord)
1168 else fset := fset2; RETURN([1])
1170 if rs = {} then
1171 fset := fset2;
1172 ['numer(cs[l]/lcoeff(expand(cs[l])))' $ ('l' = 1 .. nops(cs))]
1173 else
1174 `charsets/fcharsetsub`(
1175 `charsets/union`(rs,cs,ps),ord,medset,fset2,'fset')
1177 else
1178 cs := medset(ps,ord);
1179 fset2 := [fset1[1],fset1[2] union `charsets/initialset1`(cs,ord)];
1180 if 0 < `charsets/class`(cs[1],ord) then
1181 `charsets/remseta`({op(ps)} minus {op(cs)},cs,ord);
1182 rs := `charsets/removefactor`(%,ord,fset2,'fset3')
1183 else fset := fset2; RETURN([1])
1185 if rs = [] then
1186 fset := fset3;
1187 ['numer(cs[l]/lcoeff(expand(cs[l])))' $ ('l' = 1 .. nops(cs))]
1188 else
1189 `charsets/fcharsetsub`(
1190 `charsets/union`(rs,cs,ps),ord,medset,fset3,'fset')
1194 end:
1196 ### The following few routines implement a strategy for speeding-up
1197 ### the computation of charsets by remembering all appearing initials
1198 ### in the quasi-sense.
1199 `charsets/premA` :=
1201 proc(uu,vv,x)
1202 local r,v,dr,dv,l,t,lu,lv;
1203 global `charsets/with`;
1204 if type(vv/x,integer) then subs(x = 0,uu)
1205 else
1206 r := expand(uu);
1207 dr := degree(r,x);
1208 v := expand(vv);
1209 dv := degree(v,x);
1210 if dv <= dr then l := coeff(v,x,dv); v := expand(v-l*x^dv)
1211 else l := 1
1213 if 1 < printlevel and 500 < nops(r)+nops(v) then
1214 lprint(`pseudo-division:`,[nops(r),x,dr],[nops(v),x,dv])
1216 while dv <= dr and r <> 0 do
1217 gcd(l,coeff(r,x,dr),'lu','lv');
1218 t := expand(x^(dr-dv)*v*lv);
1219 if dr = 0 then r := 0 else r := subs(x^dr = 0,r) fi;
1220 r := expand(lu*r)-t;
1221 if not type(lu,rational) and type(`charsets/with`,set) then
1222 `charsets/with` := `charsets/with` union {lu}
1224 dr := degree(r,x)
1228 end:
1230 `charsets/remsetaA` :=
1232 proc(ps,as,ord)
1233 local i;
1234 {'`charsets/premasA`(ps[i],as,ord)' $ ('i' = 1 .. nops(ps))} minus {0}
1235 end:
1237 `charsets/premasA` :=
1239 proc(f,as,ord)
1240 local remd,i;
1241 remd := f;
1242 for i from nops(as) by -1 to 1 do
1243 remd := `charsets/premA`(remd,as[i],`charsets/lvar`(as[i],ord))
1245 if remd <> 0 then numer(remd/lcoeff(remd)) else 0 fi
1246 end:
1248 `charsets/checkwith` :=
1250 proc(ps1,ps2)
1251 local rs,i,j,r;
1252 rs := ps1 minus ps2;
1253 if rs = {} then true
1254 elif ps2 = {} then false
1255 else
1256 rs :=
1257 {'`charsets/pfactor`(convert(rs[i],sqrfree))' $ ('i' = 1 .. nops(rs))}
1259 for i to nops(rs) do
1260 r := rs[i];
1261 for j to nops(ps2) do
1262 gcd(r,ps2[j],'r'); if type(r,rational) then break fi
1264 if not type(r,rational) then RETURN(false) fi
1266 true
1268 end:
1270 # replace the power of factors of polys in as by 1 if any
1271 `charsets/nopower` :=
1273 proc(as)
1274 local i;
1275 if not type(as,{set,list}) then
1276 if type(as,`^`) then op(1,as)
1277 elif type(as,`*`) then
1278 product('`charsets/nopower`(op(i,as))','i' = 1 .. nops(as))
1279 else as
1281 else ['`charsets/nopower`(as[i])' $ ('i' = 1 .. nops(as))]
1283 end:
1285 # the nearly char set -- a medial set
1286 `charsets/charsetn` :=
1288 proc(ps,ord)
1289 local cs,rs;
1290 if nops(ps) < 2 then ps
1291 else
1292 cs := `charsets/basset`(ps,ord);
1293 if 0 < `charsets/class`(cs[1],ord) then
1294 rs := `charsets/remseta`(`charsets/minus`(ps,cs),cs,ord)
1295 else RETURN(cs)
1297 if rs = {} then cs else `charsets/charsetn`([op(rs),op(cs)],ord) fi
1299 end:
1301 # the nearly weak-char set -- a weak-medial set
1302 `charsets/wcharsetn` :=
1304 subs(`charsets/basset`=`charsets/wbasset`,
1305 `charsets/charsetn`=`charsets/wcharsetn`,
1306 op(`charsets/charsetn`)):
1308 # the nearly quasi-char set -- a quasi-medial set
1309 `charsets/qcharsetn` :=
1311 subs(`charsets/basset`=`charsets/qbasset`,
1312 `charsets/charsetn`=`charsets/qcharsetn`,
1313 op(`charsets/charsetn`)):
1315 # the modified nearly char set -- a modified medial set
1316 `charsets/fcharsetn` :=
1318 proc(ps,ord,fset1,fset)
1319 local cs,rs,fset2,fset3;
1320 if nops(ps) < 2 then fset := fset1; ps
1321 else
1322 cs := `charsets/basset`(ps,ord);
1323 fset2 := [fset1[1],fset1[2] union `charsets/initialset1`(cs,ord)];
1324 if 0 < `charsets/class`(cs[1],ord) then
1325 `charsets/remseta`(`charsets/minus`(ps,cs),cs,ord);
1326 rs := `charsets/removefactor`(%,ord,fset2,'fset3')
1327 else fset := fset2; RETURN(cs)
1329 if rs = [] then fset := fset3; cs
1330 else `charsets/fcharsetn`([op(rs),op(cs)],ord,fset3,'fset')
1333 end:
1335 # the modified nearly weak-char set -- a modified weak-medial set
1336 `charsets/fwcharsetn` :=
1338 subs(`charsets/basset`=`charsets/wbasset`,
1339 `charsets/fcharsetn`=`charsets/fwcharsetn`,
1340 op(`charsets/fcharsetn`)):
1342 # the modified nearly quasi-char set -- a modified quasi-medial set
1343 `charsets/fqcharsetn` :=
1345 subs(`charsets/basset`=`charsets/qbasset`,
1346 `charsets/fcharsetn`=`charsets/fqcharsetn`,
1347 op(`charsets/fcharsetn`)):
1349 # the triangular set of poly set ps -- a quasi-medial set
1350 `charsets/triset` :=
1352 proc(ps,ord)
1353 local i;
1354 global `charsets/@qs`;
1355 if nops(ps) < 2 then ps
1356 else
1357 for i from 0 to nops(ord) do `charsets/@qs`[i] := [] od;
1358 for i in ps do
1359 `charsets/@qs`[`charsets/class`(i,ord)] :=
1360 [op(`charsets/@qs`[`charsets/class`(i,ord)]),i]
1362 for i from nops(ord) by -1 to 1 do
1363 if `charsets/@qs`[0] = [] then `charsets/subtriset`(i,ord)
1364 else RETURN([1])
1367 if `charsets/@qs`[0] <> [] then [1]
1368 else ['op(`charsets/@qs`[i])' $ ('i' = 1 .. nops(ord))]
1371 end:
1373 # subroutine for triset
1374 `charsets/subtriset` :=
1376 proc(i,ord)
1377 local ss,ss1,j,p;
1378 global `charsets/@qs`;
1379 if 1 < nops(`charsets/@qs`[i]) then
1380 ss1 := `charsets/sort`(`charsets/@qs`[i],`charsets/trank`,ord,'ss');
1381 `charsets/@qs`[i] := [ss1];
1382 for j in ss do
1383 p := `charsets/prem`(j,ss1,ord[i]);
1384 if p <> 0 then
1385 `charsets/@qs`[`charsets/class`(p,ord)] := [
1386 op(`charsets/@qs`[`charsets/class`(p,ord)]),numer(p/lcoeff(p))
1390 `charsets/subtriset`(i,ord)
1392 end:
1394 # remove factor g from f until f has no factor g
1395 # if g is removed then assign true to ja
1396 `charsets/movefactor` :=
1398 proc(f,g,ord,ja)
1399 local fg;
1400 if not type(f,{set,list}) and not type(g,integer)
1401 and divide(f,g,'fg') then
1402 if 3 < nargs then
1403 if 0 < `charsets/class`(g,ord) then ja := true
1404 else ja := false
1407 `charsets/movefactor`(fg,g,ord)
1408 else if 3 < nargs then ja := false fi; f
1410 end:
1412 # remove possible factors in fset1[1] and fset1[2] from polys in ps
1413 # where fset1[1] contains all factors removed before
1414 # if any poly in fset1[2] is removed, it is added to fset1[1]
1415 # fset1 is assigned to fset at th end: of the procedure
1416 `charsets/removefactor` :=
1418 proc(ps,ord,fset1,fset)
1419 local k,rr,ja,fset2,fs,qs,rs,r;
1420 if not type(ps,{set,list}) then qs := {ps} else qs := ps fi;
1421 rs := {};
1422 fs := fset1;
1423 for r in qs do
1424 rr := r;
1425 fset2 := {};
1426 for k in fs[1] do rr := `charsets/movefactor`(rr,k,ord,'ja') od;
1427 for k in fs[2] do
1428 if rr <> k then
1429 rr := `charsets/movefactor`(rr,k,ord,'ja');
1430 if ja then fset2 := {numer(k/lcoeff(expand(k))),op(fset2)} fi
1433 fs := [fs[1] union fset2,fs[2] minus fset2];
1434 rs := {rr,op(rs)}
1436 rs := `charsets/nopower`(rs);
1437 fset := fs;
1438 if not type(ps,{set,list}) then rs[1] else rs fi
1439 end:
1441 # remove contents of all polys in ps wrt leading variables
1442 # the set of removed factors is assigned to ms
1443 `charsets/removecont` :=
1445 proc(ps,ord,ms)
1446 local qs,fs,i,cc,pp;
1447 if `charsets/class`(ps[1],ord) = 0 then if 2 < nargs then ms := {} fi; ps
1448 else
1449 qs := [];
1450 fs := {};
1451 for i to nops(ps) do
1452 cc := content(ps[i],`charsets/lvar`(ps[i],ord),'pp');
1453 if 0 < `charsets/class`(cc,ord) then fs := {cc,op(fs)} fi;
1454 qs := [op(qs),pp]
1456 if 2 < nargs then ms := fs fi;
1459 end:
1461 # the modified triangular set of poly set ps -- a modified quasi-medial set
1462 `charsets/ftriset` :=
1464 proc(ps,ord,fset1,fset)
1465 local i,fset2,var;
1466 global `charsets/@fact`,`charsets/@qs`;
1467 `charsets/@fact` := 1;
1468 if nops(ps) < 2 then fset := fset1; ps
1469 else
1470 fset2 := {};
1471 for i from 0 to nops(ord) do `charsets/@qs`[i] := [] od;
1472 for i in ps do
1473 `charsets/@qs`[`charsets/class`(i,ord)] :=
1474 [op(`charsets/@qs`[`charsets/class`(i,ord)]),i]
1476 var := indets(ps);
1477 for i from nops(ord) by -1 to 1 do
1478 if `charsets/@qs`[0] = [] then
1479 fset2 := fset2 union `charsets/fsubtriset`(i,ord,ps,var)
1480 else fset := [fset2,{}]; RETURN([1])
1483 if `charsets/@qs`[0] <> [] then fset := [fset2,{}]; [1]
1484 else
1485 fset := [fset2,{}];
1486 ['op(`charsets/@qs`[i])' $ ('i' = 1 .. nops(ord))]
1489 end:
1491 # subroutine for ftriset
1492 `charsets/fsubtriset` :=
1494 proc(i,ord,ps,var)
1495 local fset2,ss,ss1,j,k,l,p,pp,qq,ja;
1496 global `charsets/@qs`,`charsets/@fact`;
1497 if 1 < nops(`charsets/@qs`[i]) then
1498 ss1 := `charsets/sort`(`charsets/@qs`[i],`charsets/trank`,ord,'ss');
1499 `charsets/@qs`[i] := [ss1];
1500 fset2 := {};
1501 qq := {'numer(ps[l]/lcoeff(expand(ps[l])))' $ ('l' = 1 .. nops(ps))};
1502 for j in ss do
1503 pp := `charsets/prem`(j,ss1,ord[i]);
1504 if pp <> 0 then
1505 if pp <> `charsets/@fact` and
1506 `charsets/fsubtrisetsub`(var,`charsets/@fact`) and
1507 not member(`charsets/@fact`,qq) then
1508 p := `charsets/movefactor`(pp,`charsets/@fact`,ord,'ja');
1509 if ja then
1510 fset2 := {op(fset2),numer(
1511 `charsets/@fact`/lcoeff(expand(`charsets/@fact`)))}
1513 else p := pp
1515 for k in var do
1516 if p <> k and not member(k,qq) then
1517 p := `charsets/movefactor`(p,k,ord,'ja');
1518 if ja then fset2 := {op(fset2),k} fi
1521 `charsets/@qs`[`charsets/class`(p,ord)] := [
1522 op(`charsets/@qs`[`charsets/class`(p,ord)]),
1523 `charsets/nopower`(numer(p/lcoeff(p)))]
1526 `charsets/initial`(ss1,ord);
1527 `charsets/@fact` := numer(%/lcoeff(expand(%)));
1528 fset2 union `charsets/fsubtriset`(i,ord,ps,var)
1529 else {}
1531 end:
1533 # subroutine for fsubtriset
1534 `charsets/fsubtrisetsub` :=
1536 proc(aa,bb)
1537 local i;
1538 for i to nops(aa) do if subs(aa[i] = 0,bb) = 0 then RETURN(false) fi od;
1539 true
1540 end:
1542 # reduce a triangular set into an ascending set
1543 `charsets/trisetc` :=
1545 proc(ps,ord)
1546 local ind,cs;
1547 global `charsets/@cs`;
1548 `charsets/@cs` := `charsets/triset`(ps,ord);
1549 cs := `charsets/subtrisetc`(ord,{},'ind');
1550 if ind = 0 then `charsets/charsetn`([op(ps),op(cs)],ord) else cs fi
1551 end:
1553 # reduce a triangular set into an ascending set with factors moved
1554 `charsets/ftrisetc` :=
1556 proc(ps,ord,fset1,fset)
1557 local i,ind,cs,fs;
1558 global `charsets/@cs`;
1559 `charsets/@cs` := `charsets/ftriset`(ps,ord,fset1,'fs');
1560 fset := fs;
1561 if fs[1] <> {} then
1562 {'op(`charsets/pfactor`(fs[1][i]))' $ ('i' = 1 .. nops(fs[1]))}
1563 else {}
1565 cs := `charsets/subtrisetc`(ord,%,'ind');
1566 if ind = 0 then `charsets/fcharsetn`([op(ps),op(cs)],ord,fset1,'fset')
1567 else cs
1569 end:
1571 # subroutine for ftrisetc
1572 `charsets/subtrisetc` :=
1574 proc(ord,var,ind)
1575 local r,i,j,cs;
1576 global `charsets/@cs`;
1577 if nops(`charsets/@cs`) = 0 then cs := []
1578 else cs := [`charsets/@cs`[1]]
1580 if 1 < nops(`charsets/@cs`) then
1581 for i from 2 to nops(`charsets/@cs`) do
1582 r := `charsets/premas`(`charsets/@cs`[i],cs,ord);
1584 `charsets/class`(r,ord) <> `charsets/class`(`charsets/@cs`[i],ord)
1585 then
1586 ind := 0;
1587 if r <> 0 then
1588 cs := [op(cs),`charsets/nopower`(numer(r/lcoeff(r)))]
1590 break
1591 else
1592 for j in var do r := `charsets/movefactor`(r,j,ord) od;
1593 cs := [op(cs),`charsets/nopower`(numer(r/lcoeff(r)))];
1594 if `charsets/class`(r,ord) <>
1595 `charsets/class`(`charsets/@cs`[i],ord) then
1596 ind := 0; break
1602 end:
1604 # the set of nonconstant initials of as
1605 # with certain repeated factors cancelled
1606 `charsets/initialset1` :=
1608 proc(as,ord)
1609 local i,is,iss;
1610 is := {};
1611 for i in as do
1612 `charsets/initial`(i,ord);
1613 if 0 < `charsets/class`(%,ord) then
1614 is := {`charsets/pfactor`(%),op(is)}
1617 is := `charsets/compress`(is,ord);
1618 iss := {};
1619 for i in is do
1620 if 0 < `charsets/class`(i,ord) then iss := {i,op(iss)} fi
1623 end:
1625 # compress some repeated factors
1626 `charsets/compress` :=
1628 proc(ps,ord)
1629 local is,is1,i,j,ss;
1630 is := ps;
1631 if 1 < nops(is) then
1632 is1 := [];
1633 for i to nops(is)-1 do
1634 ss := is[i];
1635 for j from i+1 to nops(is) do
1636 ss := `charsets/movefactor`(ss,is[j],ord)
1638 if 0 < `charsets/class`(ss,ord) then
1639 is1 := [`charsets/pfactor`(ss),op(is1)]
1642 is1 := [is[nops(is)],op(is1)];
1643 is := {};
1644 if 1 < nops(is1) then
1645 for i to nops(is1)-1 do
1646 ss := is1[i];
1647 for j from i+1 to nops(is1) do
1648 ss := `charsets/movefactor`(ss,is1[j],ord)
1650 if 0 < `charsets/class`(ss,ord) then
1651 is := {op(is),`charsets/pfactor`(ss)}
1654 {op(is),is1[nops(is1)]}
1655 else {op(is1)}
1657 else {op(is)}
1659 end:
1661 # the sequence of distinct factors of f
1662 `charsets/pfactor` :=
1664 proc(f)
1665 local i;
1666 if type(f,integer) then op({})
1667 elif type(f,`^`) then op(1,f); numer(%/lcoeff(%))
1668 elif type(f,`*`) then
1669 '`charsets/pfactor`(op(i,f))' $ ('i' = 1 .. nops(f))
1670 else numer(f/lcoeff(expand(f)))
1672 end:
1674 # the sequence of factors of f
1675 `charsets/sfactor` :=
1677 proc(f)
1678 local i;
1679 if type(f,integer) then op({})
1680 elif type(f,`^`) then
1681 op(1,f); 'numer(%/lcoeff(%))' $ ('i' = 1 .. op(2,f))
1682 elif type(f,`*`) then
1683 '`charsets/sfactor`(op(i,f))' $ ('i' = 1 .. nops(f))
1684 else numer(f/lcoeff(f))
1686 end:
1688 # the set of all nonconstant factors of initials of polys in as
1689 `charsets/initialset` :=
1691 proc(as,ord)
1692 local i,is,iss;
1693 is := {};
1694 for i in as do
1695 `charsets/initial`(i,ord);
1696 if 0 < `charsets/class`(%,ord) then is := {%,op(is)} fi
1698 is := `charsets/factorps`(is);
1699 iss := {};
1700 for i in is do
1701 if 0 < `charsets/class`(i,ord) then iss := {i,op(iss)} fi
1704 end:
1706 # all irreducible nonconstant factors of a set of polynomials
1707 `charsets/factorps` :=
1709 proc(ps)
1710 local qs,i,j,q;
1711 qs := {};
1712 for i in ps do
1713 q := factor(i);
1714 if type(q,`*`) then
1715 for j to nops(q) do
1716 if not type(op(j,q),integer) then
1717 if type(op(j,q),`^`) then
1718 qs :=
1719 {op(qs),numer(op(1,op(j,q))/lcoeff(op(1,op(j,q))))}
1720 else qs := {op(qs),numer(op(j,q)/lcoeff(op(j,q)))}
1724 elif type(q,`^`) then qs := {op(qs),numer(op(1,q)/lcoeff(op(1,q)))}
1725 else if not type(q,integer) then qs := {op(qs),numer(q/lcoeff(q))} fi
1729 end:
1731 ##### Part II. Routines for Various Decompositions and Others #####
1733 # the char series of poly set ps
1734 `charsets/charseries` :=
1736 proc(ps,ord,medset)
1737 local qs,cs,iss,n,qsi,qhi,csno,ppi,qqi;
1738 if type(ps[1],{set,list}) then qhi := {op(ps)} else qhi := {{op(ps)}} fi;
1739 qsi := {};
1740 csno := 0;
1741 ppi := {};
1742 qqi := {};
1743 for n from 0 while qhi <> {} do
1744 qhi := sort([op(qhi)],`charsets/nopsord`);
1745 qs := qhi[1];
1746 ppi := `charsets/select`(ppi,nops(qs));
1747 qqi := {op(ppi[2]),op(qqi)};
1748 if n = 0 then ppi := {} else ppi := {qs,op(ppi[1])} fi;
1749 cs := `charsets/charseta`([op(qs)],ord,medset);
1750 if 1 < printlevel then
1751 csno := csno+1;
1752 lprint(
1753 `Characteristic set produced`,csno,nops(qhi),nops(qsi),nops(qs)
1755 print(cs)
1757 if 0 < `charsets/class`(cs[1],ord) then
1758 iss := `charsets/initialset`(cs,ord);
1759 if `charsets/simpa`(iss,cs,ord) <> 0 then qsi := {cs,op(qsi)} fi;
1760 iss := `charsets/adjoin`(iss,qs,qqi)
1761 else iss := {}
1763 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
1764 else qhi := iss
1767 if qsi = {} then []
1768 else op(sort(`charsets/contract`(qsi,ord,0),`charsets/lenord`))
1770 end:
1772 # the char series of poly set ps -- allowing to remove factors
1773 `charsets/fcharser` :=
1775 proc(ps,ord,medset)
1776 local qs,cs,iss,n,qhi,qsi,factorset,csno,ppi,qqi;
1777 if type(ps[1],{set,list}) then qhi := {op(ps)} else qhi := {{op(ps)}} fi;
1778 qsi := {};
1779 csno := 0;
1780 ppi := {};
1781 qqi := {};
1782 for n from 0 while qhi <> {} do
1783 qhi := sort([op(qhi)],`charsets/nopsord`);
1784 qs := qhi[1];
1785 ppi := `charsets/select`(ppi,nops(qs));
1786 qqi := {op(ppi[2]),op(qqi)};
1787 if n = 0 then ppi := {} else ppi := {qs,op(ppi[1])} fi;
1788 if nops(qs)-3 < nops(ord) then
1789 cs := `charsets/fcharseta`([op(qs)],ord,medset);
1790 factorset := op(2,cs[2]);
1791 cs := cs[1]
1792 else
1793 `charsets/charseta`([op(qs)],ord,medset);
1794 cs := `charsets/removecont`(%,ord,'factorset')
1796 if 1 < printlevel then
1797 csno := csno+1;
1798 lprint(
1799 `Characteristic set produced`,csno,nops(qhi),nops(qsi),nops(qs)
1801 print(cs)
1803 if 0 < `charsets/class`(cs[1],ord) then
1804 iss := `charsets/initialset`(cs,ord);
1805 if `charsets/simpa`(iss,cs,ord) <> 0 then qsi := {cs,op(qsi)} fi;
1806 iss := iss union `charsets/factorps`(factorset)
1807 else iss := `charsets/factorps`(factorset)
1809 iss := `charsets/adjoin`(iss,qs,qqi);
1810 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
1811 else qhi := iss
1814 if qsi = {} then []
1815 else op(sort(`charsets/contract`(qsi,ord,0),`charsets/lenord`))
1817 end:
1819 # the extended char series of poly set ps
1820 `charsets/excharser` :=
1822 proc(ps,ord,medset)
1823 local qs,cs,is,iss,i,j,qsi,qhi,r,rr;
1824 if type(ps[1],{set,list}) then qhi := {ps} else qhi := {[ps,1]} fi;
1825 qsi := {};
1826 while qhi <> {} do
1827 qs := qhi[1][1];
1828 cs := `charsets/charseta`([op(qs)],ord,medset);
1829 if 1 < printlevel then
1830 lprint(`Characteristic set produced`); print(cs)
1832 if 0 < `charsets/class`(cs[1],ord) then
1833 is := `charsets/initialset`(cs,ord);
1834 rr := `charsets/nopower`(`charsets/prod`({op(is),qhi[1][2]}));
1835 `charsets/premas`(rr,cs,ord);
1836 r := `charsets/simp`(%,cs,ord);
1837 if r <> 0 then
1838 if r = 1 then qsi := {cs,op(qsi)}
1839 else qsi := {op(qsi),[cs,`charsets/simpb`(r,rr)]}
1842 else is := []
1844 iss := {};
1845 if nops(ord) <= nops(ps)+1 then
1846 for i in is do iss := {op(iss),[{op(qs),i},qhi[1][2]]} od
1847 else
1848 for i to nops(is) do
1849 if i = 1 then 1 else product('is[j]','j' = 1 .. i-1) fi;
1850 iss := {op(iss),[{op(qs),is[i]},%*qhi[1][2]]}
1853 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
1854 else qhi := iss
1857 if qsi = {} then [] else op(sort([op(qsi)],`charsets/lenord`)) fi
1858 end:
1860 # simplify r to rr so that Zero(cs/r) = Zero(cs/rr) holds still
1861 `charsets/simp` :=
1863 proc(r,cs,ord)
1864 local rr,i,fs,j,ind;
1865 if r = 0 then 0
1866 else
1867 fs := {`charsets/pfactor`(r)};
1868 rr := 1;
1869 for i in fs do
1870 if 0 < `charsets/class`(i,ord) then
1871 ind := 0;
1872 for j in cs do
1873 subs(i = 0,j);
1874 if % = 0 then
1875 if `charsets/class`(`charsets/movefactor`(j,i,ord),ord)
1876 = 0 then
1877 ind := -1; break
1879 elif `charsets/class`(%,ord) = 0 then ind := 1; break
1882 if ind = 0 then rr := rr*i elif ind = -1 then break fi
1885 if ind = -1 then 0 else rr fi
1887 end:
1889 # check whether Zero(cs/fs) is empty
1890 `charsets/simpa` :=
1892 proc(fs,cs,ord)
1893 local i,j,ds;
1894 if nops(cs) = 1 then 1
1895 else
1896 ds := [op(1 .. nops(cs)-1,cs)];
1897 for i in fs do
1898 for j in ds do
1899 if subs(i = 0,j) = 0 then
1900 if `charsets/class`(`charsets/movefactor`(j,i,ord),ord) = 0
1901 then
1902 RETURN(0)
1909 end:
1911 # the simpler one of a and b
1912 `charsets/simpb` :=
1914 proc(a,b)
1915 if `charsets/measure`(a) < `charsets/measure`(b) then a else b fi
1916 end:
1918 # the measure of complexity of a according to number of terms
1919 `charsets/measure` :=
1921 proc(a)
1922 local i;
1923 if type(a,`^`) then nops(op(1,a))
1924 elif type(a,`*`) then
1925 sum('`charsets/measure`(op(i,a))','i' = 1 .. nops(a))
1926 else nops(a)
1928 end:
1930 # the extended char series of poly set ps -- allowing to remove factors
1931 `charsets/fexcharser` :=
1933 proc(ps,ord,medset)
1934 local qs,cs,is,iss,n,i,j,qhi,qsi,r,rr,factorset;
1935 if type(ps[1],{set,list}) then qhi := {ps} else qhi := {[ps,1]} fi;
1936 qsi := {};
1937 for n from 0 while qhi <> {} do
1938 qs := qhi[1][1];
1939 if n = 0 then
1940 cs := `charsets/fcharseta`([op(qs)],ord,medset);
1941 factorset := op(2,cs[2]);
1942 cs := cs[1]
1943 else
1944 `charsets/charseta`([op(qs)],ord,medset);
1945 cs := `charsets/removecont`(%,ord,'factorset')
1947 if 1 < printlevel then
1948 lprint(`Characteristic set produced`); print(cs)
1950 if 0 < `charsets/class`(cs[1],ord) then
1951 is :=
1952 `charsets/initialset`(cs,ord) union `charsets/factorps`(factorset)
1954 rr := `charsets/nopower`(`charsets/prod`({op(is),qhi[1][2]}));
1955 `charsets/premas`(rr,cs,ord);
1956 r := `charsets/simp`(%,cs,ord);
1957 if r <> 0 then
1958 if r = 1 then qsi := {cs,op(qsi)}
1959 else qsi := {op(qsi),[cs,`charsets/simpb`(r,rr)]}
1962 else is := `charsets/factorps`(factorset)
1964 iss := {};
1965 if nops(ord) <= nops(ps)+1 then
1966 for i in is do iss := {op(iss),[{op(qs),i},qhi[1][2]]} od
1967 else
1968 for i to nops(is) do
1969 if i = 1 then 1 else product('is[j]','j' = 1 .. i-1) fi;
1970 iss := {op(iss),[{op(qs),is[i]},%*qhi[1][2]]}
1973 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
1974 else qhi := iss
1977 if qsi = {} then [] else op(sort([op(qsi)],`charsets/lenord`)) fi
1978 end:
1980 # the irreducible char series of poly set ps
1981 # using new factorization method if m=1, Hu-Wang's method if m=-1
1982 # and normalized char set if m=0
1983 `charsets/irrcharser` :=
1985 proc(ps,ord,medset,m)
1986 local qs,cs,cst,is,iss,n,ts,qsi,qhi,pi,factorset,ppi,qqi,csno,ind,fset,mind;
1987 options remember;
1988 if nargs = 3 then ind := 1 else ind := m fi;
1989 if type(ps[1],{set,list}) then qhi := {op(ps)} else qhi := {ps} fi;
1990 qsi := {};
1991 pi := {};
1992 csno := 0;
1993 ppi := {};
1994 qqi := {};
1995 if medset = `charsets/basset` then mind := true else mind := false fi;
1996 for n from 0 while qhi <> {} do
1997 qhi := sort([op(qhi)],`charsets/nopsord`);
1998 qs := qhi[1];
1999 ppi := `charsets/select`(ppi,nops(qs));
2000 qqi := {op(qqi),op(ppi[2])};
2001 if n = 0 then ppi := {} else ppi := {qs,op(ppi[1])} fi;
2002 if nops(qs)-3 < nops(ord) then
2003 if not mind then
2004 cs := `charsets/f`.(substring(medset,10 .. length(medset)))(
2005 qs,ord,[{},indets(qs)],'fset');
2006 if 2 < nops(indets(cs[1])) then
2007 cs := `charsets/removecont`(cs,ord,'factorset');
2008 factorset := factorset union fset[1]
2009 else factorset := fset[1]
2011 else
2012 cs := `charsets/fcharseta`(qs,ord,medset);
2013 factorset := op(2,cs[2]);
2014 cs := cs[1];
2015 if 1 < printlevel and ind = 1 then
2016 csno := csno+1;
2017 lprint(`Characteristic set produced`,csno,nops(qhi),
2018 nops(qsi),nops(qs));
2019 print(cs)
2022 if ind = 0 then
2023 cs := [`charsets/fcnormal`(cs,ord,2)];
2024 if 1 < nops(cs) then factorset := factorset union op(2,cs[2])
2026 cs := cs[1]
2028 if mind and 2 < nops(indets(cs[1])) then
2029 cs := `charsets/removecont`(cs,ord,'ts');
2030 factorset := factorset union ts
2032 elif mind then
2033 cs := `charsets/removecont`(
2034 `charsets/charseta`([op(qs)],ord,medset),ord,'factorset')
2035 else
2036 cs := `charsets/removecont`(medset([op(qs)],ord),ord,'factorset')
2038 if 0 < `charsets/class`(cs[1],ord) then
2039 ts := `charsets/irras`(cs,ord,ind);
2040 if ts[2] = 0 then
2041 if not mind then
2042 if not `charsets/subset`(cs,qs) then
2043 cs := `charsets/charseta`({op(qs),op(cs)},ord,medset)
2045 if 1 < printlevel and ind = 1 then
2046 csno := csno+1;
2047 lprint(`Characteristic set produced`,csno,nops(qhi),
2048 nops(qsi),nops(qs));
2049 print(cs)
2052 if not member(cs,pi) then
2053 pi := {cs,op(pi)};
2054 if 0 < `charsets/class`(cs[1],ord) then
2055 ts := `charsets/irras`(cs,ord,ind);
2056 if ts[2] = 0 then
2057 qsi := {cs,op(qsi)};
2058 if nops(cs) = nops(ord) then
2059 is := `charsets/factorps`(factorset)
2060 else
2061 is := `charsets/initialset`(cs,ord) union
2062 `charsets/factorps`(factorset)
2064 iss := `charsets/adjoin`(is,qs,qqi)
2066 else
2067 iss := `charsets/adjoin`(
2068 `charsets/factorps`(factorset),qs,qqi)
2070 else
2071 iss :=
2072 `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2075 if ts[2] <> 0 then
2076 is := `charsets/factorps`(factorset);
2077 if 1 < ts[2] then
2078 cst := [op(1 .. ts[2]-1,cs)];
2079 is := is union `charsets/initialset`(cst,ord);
2080 iss := `charsets/adjoin`(is,qs,qqi) union
2081 `charsets/adjoinb`(ts[1],qs,qqi,cst)
2082 else iss := `charsets/adjoin`(is union ts[1],qs,qqi)
2085 else iss := `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2087 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
2088 else qhi := iss
2091 if qsi = {} then []
2092 else op(sort(`charsets/contract`(qsi,ord,1),`charsets/lenord`))
2094 end:
2096 # test whether ps is a subset or sublist of qs
2097 `charsets/subset` :=
2099 proc(ps,qs)
2100 local p;
2101 for p in ps do if not member(p,qs) then RETURN(false) fi od; true
2102 end:
2104 # subroutine for irrcharser, qirrcharser and others
2105 `charsets/adjoinb` :=
2107 proc(is,qs,qh,cs)
2108 local iss,i,j,ind,qhi,itt;
2109 iss := {};
2110 qhi := qh minus {qs};
2111 if is <> {} then
2112 for i in is do
2113 itt := {i,op(qs),op(cs)};
2114 ind := 0;
2115 if 0 < nops(qhi) then
2116 for j in qhi while ind = 0 do
2117 if `charsets/subset`(j,itt) then ind := 1 fi
2120 if ind = 0 then iss := {op(iss),itt} fi
2124 end:
2126 # examine the irreducibility of as for irrcharser
2127 `charsets/irras` :=
2129 proc(as,ord,inda,den)
2130 local ind,i,j,p,qs,n,fs,ja,dd;
2131 options remember,system;
2132 ind := 1;
2133 ja := 0;
2134 dd := 1;
2135 for i to nops(as) do
2136 p := factor(as[i]);
2137 fs := `charsets/dfactors`(p);
2138 qs := {};
2139 for j to nops(fs) do
2140 if 0 < `charsets/class`(fs[j],ord) then qs := {op(qs),fs[j]} fi
2142 `charsets/lvar`(p,ord);
2143 if `charsets/degree`(qs[1],%) < `charsets/degree`(p,%) then
2144 ja := 1; ind := 0; break
2147 if ind = 1 and 1 < nops(as) then
2148 for n while n < nops(as) and `charsets/degreel`(as[n],ord) = 1 do
2151 if n < nops(as) then
2152 qs := `charsets/irrassub`(as,n,ord,inda,'ja','dd')
2153 else ja := 0
2156 if 3 < nargs then den := dd fi;
2157 [qs,ja]
2158 end:
2160 # subroutine for irras
2161 `charsets/irrassub` :=
2163 proc(as,n,ord,ind,ja,den)
2164 local m,qs,i,vv,dd;
2165 global `charsets/das`;
2166 for m from n+1 while m <= nops(as) and `charsets/degreel`(as[m],ord) = 1
2170 dd := 1;
2171 if m <= nops(as) then
2172 vv := `charsets/lvar`(as[m],ord);
2173 if ind = -1 then
2174 qs := `charsets/factoras`(as[m],['as[i]' $ ('i' = 1 .. m-1)],ord)
2175 else
2176 qs := `charsets/cfactor`(as[m],['as[i]' $ ('i' = 1 .. m-1)],ord);
2177 dd := denom(qs);
2178 qs := {`charsets/qfactor`(numer(qs),ord)}
2180 if max('`charsets/degree`(qs[i],vv)' $ ('i' = 1 .. nops(qs))) =
2181 `charsets/degree`(as[m],vv) then
2182 qs := `charsets/irrassub`(as,m,ord,ind,'ja','dd')
2183 else ja := m
2185 else ja := 0
2187 if 5 < nargs then den := dd fi;
2189 end:
2191 # collect distinct nonconstant factors of a polynomial q
2192 `charsets/dfactors` :=
2194 proc(q)
2195 local qs,j;
2196 if type(q,`*`) then
2197 qs := {};
2198 for j to nops(q) do
2199 if not type(op(j,q),integer) then
2200 if type(op(j,q),`^`) then
2201 qs := {op(qs),numer(op(1,op(j,q))/lcoeff(op(1,op(j,q))))}
2202 else qs := {op(qs),numer(op(j,q)/lcoeff(op(j,q)))}
2206 elif type(q,`^`) then qs := {numer(op(1,q)/lcoeff(op(1,q)))}
2207 else if not type(q,integer) then qs := {numer(q/lcoeff(q))} fi
2210 end:
2212 # normalize ascending set cs wrt ord
2213 `charsets/fcnorm` := proc(cs,ord,m)
2214 local as,i;
2215 as := [cs[1]];
2216 for i from 2 to nops(cs) do
2217 as := `charsets/fcnormal`([op(as),cs[i]],ord,m);
2218 if 1 < nops([as]) then RETURN(cs) fi
2221 end:
2223 # normalize the last pol in an ascending set cs wrt ord
2224 `charsets/fcnormal` :=
2226 proc(cs,ord,m)
2227 local n,ini,i,j,ggg,gg,ff,ccs,dd,cd,fs,nt;
2228 n := nops(cs);
2229 if n < 2 then cs
2230 else
2231 dd := cs[n];
2232 nt := nops(expand(dd));
2233 for i from n-1 by -1 to 1 do
2234 ini := `charsets/initial`(dd,ord);
2235 if 0 < `charsets/degree`(ini,`charsets/lvar`(cs[i],ord)) then
2236 ggg := `charsets/gcdex`(cs[i],ini,`charsets/lvar`(cs[i],ord));
2237 gg := ggg[3];
2238 if 0 < `charsets/degree`(gg,`charsets/lvar`(cs[i],ord)) then
2239 ff := cs[i];
2240 gg := {`charsets/pfactor`(gg)};
2241 cd := {};
2242 for j to nops(gg) do
2243 if `charsets/class`(gg[j],ord) =
2244 `charsets/class`(cs[i],ord) then
2245 ff := `charsets/nopower`(
2246 `charsets/movefactor`(ff,gg[j],ord));
2247 cd := {op(cd),gg[j]}
2250 if `charsets/class`(ff,ord) = 0 then ccs := [[1]]
2251 else
2252 ccs := [`charsets/fcnormal`(subs(cs[i] = ff,cs),ord,m)]
2254 if nops(ccs) = 1 then
2255 RETURN(ccs[1],`common divisors` = cd)
2256 else
2257 RETURN(
2258 ccs[1],`common divisors` = {op(cd),op(op(2,ccs[2]))}
2261 else
2262 dd :=
2263 `charsets/prem`(dd*ggg[2],cs[i],`charsets/lvar`(cs[i],ord))
2265 dd :=
2266 `charsets/movefactor`(dd,`charsets/initial`(cs[i],ord),ord)
2268 dd := `charsets/nopower`(dd);
2269 if 4*m*nt < nops(expand(dd)) then RETURN(cs) fi
2273 ccs := [op(1 .. n-1,cs)];
2274 fs := {`charsets/pfactor`(content(dd,`charsets/lvar`(dd,ord),'dd'))};
2275 gg := {};
2276 for i to nops(fs) do
2277 if 0 < `charsets/class`(fs[i],ord) then gg := {op(gg),fs[i]} fi
2279 gg := `charsets/prod`(gg);
2280 ini := `charsets/initialset`(ccs,ord);
2281 for i to nops(ini) do gg := `charsets/movefactor`(gg,ini[i],ord) od;
2282 dd := `charsets/nopower`(gg)*dd;
2283 gg := [`charsets/pfactor`(numer(dd/lcoeff(expand(dd))))];
2284 dd := 1;
2285 for i to nops(gg) do
2286 if 0 < `charsets/class`(gg[i],ord) then dd := dd*gg[i] fi
2288 if m*nt < nops(expand(dd)) then
2289 if 1 < printlevel then
2290 lprint(`normalization fails:`,nt,nops(expand(dd)))
2293 else [op(ccs),dd]
2296 end:
2298 # the modified gcdex for fcnormal
2299 `charsets/gcdex` :=
2301 proc(A,B,x)
2302 local m,pm,cc,cd,c,c1,c2,d,d1,d2,r,r1,r2,q,II;
2303 options remember,system;
2304 if A = 0 then RETURN([0,1,B]) fi;
2305 if B = 0 then RETURN([1,0,A]) fi;
2306 cc := content(A,x,c);
2307 cd := content(B,x,d);
2308 II := readlib(`gcd/degrees`)(expand(c),expand(d),{x},'c','d');
2309 pm := 1;
2310 c1 := 1;
2311 c2 := 0;
2312 d1 := 0;
2313 d2 := 1;
2314 while d <> 0 do
2315 r := prem(c,d,x,'m','q');
2316 divide(r,pm,'r');
2317 divide(m*c1-q*d1,pm,'r1');
2318 divide(c2*m-q*d2,pm,'r2');
2319 c := d;
2320 c1 := d1;
2321 c2 := d2;
2322 d := r;
2323 d1 := r1;
2324 d2 := r2;
2325 pm := m
2327 subs(II,[c1*cd,c2*cc,c*cc*cd])
2328 end:
2330 # the extended irreducible char series of poly set ps
2331 `charsets/exirrcharser` :=
2333 proc(ps,ord,medset)
2334 local qs,cs,is,iss,n,i,j,qhi,qsi,r,rr,factorset,mind,fset,ind,ts,den;
2335 if type(ps[1],{set,list}) then qhi := {ps} else qhi := {[ps,1]} fi;
2336 if medset = `charsets/basset` then mind := true else mind := false fi;
2337 qsi := {};
2338 for n from 0 while qhi <> {} do
2339 qs := qhi[1][1];
2340 if not mind then
2341 if n < 20 then
2342 `charsets/f`.(substring(medset,10 .. length(medset)))(
2343 qs,ord,[{},indets(qs)],'fset');
2344 cs := `charsets/removecont`(%,ord,'factorset');
2345 factorset := factorset union fset[1]
2346 else
2347 `charsets/`.(substring(medset,10 .. length(medset)))(qs,ord);
2348 cs := `charsets/removecont`(%,ord,'factorset')
2350 else
2351 if n < 20 then
2352 cs := `charsets/fcharseta`([op(qs)],ord,medset);
2353 factorset := op(2,cs[2]);
2354 cs := `charsets/removecont`(cs[1],ord,'ts');
2355 factorset := factorset union ts
2356 else
2357 `charsets/charseta`([op(qs)],ord,medset);
2358 cs := `charsets/removecont`(%,ord,'factorset')
2360 if 1 < printlevel then
2361 lprint(`Characteristic set produced`); print(cs)
2364 if 0 < `charsets/class`(cs[1],ord) then
2365 ts := `charsets/irras`(cs,ord,ind,'den');
2366 if ts[2] = 0 then
2367 if not mind then
2368 if not `charsets/subset`(cs,qs) then
2369 cs := `charsets/charseta`({op(qs),op(cs)},ord,medset)
2371 if 1 < printlevel then
2372 lprint(`Characteristic set produced`); print(cs)
2375 if 0 < `charsets/class`(cs[1],ord) then
2376 ts := `charsets/irras`(cs,ord,ind,'den');
2377 if ts[2] = 0 then
2378 is := `charsets/initialset`(cs,ord) union
2379 `charsets/factorps`(factorset);
2380 if nops(cs) = nops(ord) then
2381 rr := `charsets/nopower`(qhi[1][2])
2382 else
2383 rr := `charsets/nopower`(
2384 `charsets/prod`({op(is),qhi[1][2]}))
2386 `charsets/premas`(rr,cs,ord);
2387 r := `charsets/simp`(%,cs,ord);
2388 if r <> 0 then
2389 if r = 1 then qsi := {cs,op(qsi)}
2390 else qsi := {op(qsi),[cs,`charsets/simpb`(r,rr)]}
2394 else is := `charsets/factorps`(factorset); ts := [1,0]
2397 if ts[2] <> 0 then
2398 if 1 < ts[2] then
2399 is := `charsets/initialset`({op(1 .. ts[2]-1,cs)},ord)
2400 union `charsets/factorps`(factorset)
2401 else is := `charsets/factorps`(factorset)
2404 else is := `charsets/factorps`(factorset); ts := [1,0]
2406 iss := {};
2407 if nops(ord) <= nops(ps)+1 then
2408 for i in is do iss := {op(iss),[{op(qs),i},qhi[1][2]]} od
2409 else
2410 for i to nops(is) do
2411 if i = 1 then 1 else product('is[j]','j' = 1 .. i-1) fi;
2412 iss := {op(iss),[{op(qs),is[i]},%*qhi[1][2]]}
2415 if ts[2] <> 0 and ts[1] <> {} then
2416 if not mind then
2417 if not `charsets/subset`(cs,qs) then
2418 `charsets/charseta`({op(qs),op(cs)},ord,medset)
2419 else cs
2421 if % <> cs then
2422 if ts[2] = 1 then cs := qs
2423 else cs := {op(qs),op(1 .. ts[2]-1,cs)}
2427 for i in ts[1] do
2428 iss :=
2429 {op(iss),[{i,op(cs)},`charsets/prod`({op(is),qhi[1][2],den})]}
2431 if 0 < `charsets/class`(den,ord) and
2432 ts[2] < `charsets/class`(ts[1][1],ord) then
2433 iss := {op(iss),[{op(cs),den},qhi[1][2]]}
2436 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
2437 else qhi := iss
2440 if qsi = {} then [] else op(sort([op(qsi)],`charsets/lenord`)) fi
2441 end:
2443 # subroutine for irrcharser, qirrcharser and others
2444 `charsets/select` :=
2446 proc(ppi,n)
2447 local i,pp,qq;
2448 pp := {};
2449 qq := {};
2450 for i in ppi do
2451 if n <= nops(i) then qq := {i,op(qq)} else pp := {i,op(pp)} fi
2453 [pp,qq]
2454 end:
2456 # subroutine for irrcharser, qirrcharser and others
2457 `charsets/adjoin` :=
2459 proc(is,qs,qh)
2460 local iss,i,j,ind,qhi,itt;
2461 iss := {};
2462 qhi := qh minus {qs};
2463 if is <> {} then
2464 for i in is do
2465 itt := {i,op(qs)};
2466 ind := 0;
2467 if 0 < nops(qhi) then
2468 for j in qhi while ind = 0 do
2469 if `charsets/subset`(j,itt) then ind := 1 fi
2472 if ind = 0 then iss := {op(iss),itt} fi
2476 end:
2478 # subroutine for trisersub
2479 `charsets/adjoina` :=
2481 proc(is,qs,qh)
2482 local iss,i,j,ind,qhi,itt;
2483 iss := {};
2484 qhi := qh minus {qs};
2485 if is <> {} then
2486 for i in is do
2487 itt := {i,op(qs)};
2488 ind := 0;
2489 if 0 < nops(qhi) then
2490 for j in qhi while ind = 0 do
2491 if `charsets/subset`(j,itt) then ind := 1 fi
2494 if ind = 0 then iss := {op(iss),[i,op(qs)]} fi
2498 end:
2500 # subroutine for irrcharser, qirrcharser and others
2501 `charsets/nopsord` := proc(a,b)
2502 options remember,system;
2503 if nops(b) < nops(a) then true else false fi
2504 end:
2506 # remove some redundant ascending sets in cs
2507 # irr=1 for irrcharser, irr=2 for qirrcharser, irr=-1 for trisersub
2508 # and irr=0 for others
2509 `charsets/contract` :=
2511 proc(cs,ord,irr)
2512 local i,j,mem,ts;
2513 mem := {};
2514 ts := {};
2515 if nops(cs) < 2 then [op(cs)]
2516 else
2517 for i to nops(cs)-1 do
2518 if not member(i,mem) then
2519 for j from i+1 to nops(cs) do
2520 if not member(j,mem) then
2521 if `charsets/linas`(cs[j],ord,irr) and
2522 `charsets/contractsub`(cs[i],cs[j],ord) then
2523 ts := {cs[j],op(ts)}; mem := {j,op(mem)}
2524 else
2525 if `charsets/linas`(cs[i],ord,irr) and
2526 `charsets/contractsub`(cs[j],cs[i],ord) then
2527 ts := {cs[i],op(ts)}
2534 [op({op(cs)} minus ts)]
2536 end:
2538 # check whether all polys in cs1 have remainders 0 wrt cs2
2539 # but none of their initials does: subroutine for contract
2540 `charsets/contractsub` :=
2542 proc(cs1,cs2,ord)
2543 local i,is;
2544 for i in cs1 do
2545 if `charsets/premas`(i,cs2,ord) <> 0 then RETURN(false) fi
2547 is := `charsets/initialset1`(cs1,ord);
2548 for i in is do
2549 if `charsets/premas`(i,cs2,ord) = 0 then RETURN(false) fi
2551 true
2552 end:
2554 # check the irreducibility of as: subroutine for contract
2555 `charsets/linas` :=
2557 proc(as,ord,irr)
2558 local i,j,n,m;
2559 if irr = 1 then true
2560 elif irr = 2 then
2561 if 1 < nops(as) then
2562 for n while n < nops(as) and `charsets/degreel`(as[n],ord) = 1 do
2565 if n < nops(as) then
2566 for m from n+1 while
2567 m <= nops(as) and `charsets/degreel`(as[m],ord) = 1 do
2570 if m <= nops(as) then RETURN(false) fi
2573 true
2574 else
2575 for i in as do
2576 if 1 < `charsets/degreel`(i,ord) then RETURN(false) fi
2578 if irr = 0 or nops(as) < 2 then true
2579 else
2580 for i from 2 to nops(as) do
2581 for j to i do
2582 if has(
2583 `charsets/initial`(as[i],ord),`charsets/lvar`(as[j],ord)
2584 ) then
2585 RETURN(false)
2589 true
2592 end:
2594 # the quasi-irreducible char series of poly set ps
2595 `charsets/qirrcharser` :=
2597 proc(ps,ord,medset)
2598 local qs,cs,is,iss,n,ts,qsi,qhi,pi,factorset,ppi,qqi,csno,fset,mind;
2599 if type(ps[1],{set,list}) then qhi := {op(ps)} else qhi := {ps} fi;
2600 qsi := {};
2601 pi := {};
2602 csno := 0;
2603 ppi := {};
2604 qqi := {};
2605 if medset <> `charsets/basset` and medset <> `charsets/wbasset` then
2606 mind := true
2607 else mind := false
2609 for n from 0 while qhi <> {} do
2610 qhi := sort([op(qhi)],`charsets/nopsord`);
2611 qs := qhi[1];
2612 ppi := `charsets/select`(ppi,nops(qs));
2613 qqi := {op(qqi),op(ppi[2])};
2614 if n = 0 then ppi := {} else ppi := {qs,op(ppi[1])} fi;
2615 if nops(qs)-3 < nops(ord) then
2616 if mind then
2617 cs := `charsets/f`.(substring(medset,10 .. length(medset)))(
2618 qs,ord,[{},indets(qs)],'fset');
2619 if 2 < nops(indets(cs[1])) then
2620 cs := `charsets/removecont`(cs,ord,'factorset');
2621 factorset := factorset union fset[1]
2622 else factorset := fset[1]
2624 else
2625 cs := `charsets/fcharseta`(qs,ord,medset);
2626 factorset := op(2,cs[2]);
2627 if 1 < printlevel then
2628 csno := csno+1;
2629 lprint(`Characteristic set produced`,csno,nops(qhi),
2630 nops(qsi),nops(qs));
2631 print(cs[1])
2633 cs := `charsets/removecont`(cs[1],ord,'ts');
2634 factorset := factorset union ts
2636 elif not mind and 2 < nops(indets(cs[1])) then
2637 cs := `charsets/removecont`(
2638 `charsets/charseta`([op(qs)],ord,medset),ord,'factorset')
2639 else
2640 cs := `charsets/removecont`(medset([op(qs)],ord),ord,'factorset')
2642 if 0 < `charsets/class`(cs[1],ord) then
2643 ts := `charsets/qirras`(cs,ord);
2644 if ts[2] = 0 then
2645 if mind then
2646 if not `charsets/subset`(cs,qs) then
2647 cs := `charsets/charseta`({op(qs),op(cs)},ord,medset)
2649 if 1 < printlevel then
2650 csno := csno+1;
2651 lprint(`Characteristic set produced`,csno,nops(qhi),
2652 nops(qsi),nops(qs));
2653 print(cs)
2656 if not member(cs,pi) then
2657 pi := {cs,op(pi)};
2658 if 0 < `charsets/class`(cs[1],ord) then
2659 ts := `charsets/qirras`(cs,ord);
2660 if ts[2] = 0 then
2661 qsi := {cs,op(qsi)};
2662 if nops(cs) = nops(ord) then
2663 is := `charsets/factorps`(factorset)
2664 else
2665 is := `charsets/initialset`(cs,ord) union
2666 `charsets/factorps`(factorset)
2668 iss := `charsets/adjoin`(is,qs,qqi)
2670 else
2671 iss := `charsets/adjoin`(
2672 `charsets/factorps`(factorset),qs,qqi)
2674 else
2675 iss :=
2676 `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2679 if ts[2] <> 0 then
2680 is := `charsets/factorps`(factorset) union ts[1];
2681 if 1 < ts[2] then
2682 is :=
2683 is union `charsets/initialset`([op(1 .. ts[2]-1,cs)],ord)
2685 iss := `charsets/adjoin`(is,qs,qqi)
2687 else iss := `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2689 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
2690 else qhi := iss
2693 if qsi = {} then []
2694 else op(sort(`charsets/contract`(qsi,ord,2),`charsets/lenord`))
2696 end:
2698 # examine the irreducibility of as for qirrcharser
2699 `charsets/qirras` :=
2701 proc(as,ord)
2702 local ind,i,j,p,qs,fs,n,m,ja;
2703 options remember,system;
2704 qs := [];
2705 ind := 1;
2706 ja := 0;
2707 for i to nops(as) do
2708 p := factor(as[i]);
2709 fs := `charsets/dfactors`(p);
2710 qs := {};
2711 for j to nops(fs) do
2712 if 0 < `charsets/class`(fs[j],ord) then qs := {op(qs),fs[j]} fi
2714 `charsets/lvar`(p,ord);
2715 if `charsets/degree`(qs[1],%) < `charsets/degree`(p,%) then
2716 ja := 1; ind := 0; break
2719 if ind = 1 and 1 < nops(as) then
2720 for n while n < nops(as) and `charsets/degreel`(as[n],ord) = 1 do
2723 if n < nops(as) then
2724 for m from n+1 while
2725 m <= nops(as) and `charsets/degreel`(as[m],ord) = 1 do
2728 if m <= nops(as) then
2729 lprint(
2730 `Warning: factorization over algebraic field required for ics`
2735 [qs,ja]
2736 end:
2738 # subroutine for `charsets/cfactor`
2739 `charsets/cfactorsub` :=
2741 proc(f,as,ord)
2742 local ind,i,ff,fn,ffn,lind;
2743 ff := numer(f);
2744 if type(ff,`^`) then ind := map(`charsets/newfactoras`,ff,as,ord)
2745 elif type(ff,`*`) then
2746 fn := {op(ff)};
2747 ind := 1;
2748 for i to nops(fn) do
2749 if type(fn[i],`^`) then
2750 ind := ind*map(`charsets/newfactoras`,fn[i],as,ord)
2751 else ind := ind*`charsets/newfactoras`(fn[i],as,ord)
2754 else ind := `charsets/newfactoras`(ff,as,ord)
2756 lind :=
2757 lcoeff(ff,`charsets/lvar`(ff,ord))/lcoeff(ind,`charsets/lvar`(ind,ord))
2759 for i from nops(as) by -1 to 1 do
2760 `charsets/premB`(numer(lind),as[i],`charsets/lvar`(as[i],ord),'fn');
2761 `charsets/premB`(denom(lind),as[i],`charsets/lvar`(as[i],ord),'ffn');
2762 lind := %%*ffn/%/fn
2764 ind*lind;
2765 if type(%,{`*`,`^`}) then simplify(%/denom(f)) else f fi
2766 end:
2768 `charsets/cfactor_switch` := false:
2770 # factorize poly f over algebraic number field with minimal polys in as
2771 # -- a new method of Wang
2772 # first factorize pf over smaller fields
2773 `charsets/newfactoras` :=
2775 proc(f,as,ord)
2776 local pf,pas,aas,con,vf,va,i,fn;
2777 global `charsets/con`,`charsets/cfactor_switch`;
2778 vf := `charsets/lvar`(f,ord);
2779 if `charsets/class`(vf,ord) <= `charsets/class`(as[nops(as)],ord) then
2780 RETURN(f)
2781 elif `charsets/degree`(f,vf) = 1 then RETURN(f)
2783 aas := [];
2784 con := 2;
2785 for i to nops(as) do
2786 `charsets/degreel`(as[i],ord);
2787 if 1 < % then con := con,%; aas := [op(aas),expand(as[i])] fi
2789 if aas = [] then RETURN(f) fi;
2790 va := `charsets/lvar`(aas[1],ord);
2791 if nops(aas) = 1 and `charsets/degree`(f,va) = 0 then
2792 `charsets/trivial`(f,aas[1],vf,va,'fn');
2793 if type(%,{`*`,`^`}) then
2794 RETURN(map(`charsets/newfactoras`,%,as,ord)/fn)
2797 pas := `charsets/fcnorm`(aas,ord,1);
2798 `charsets/fcnormal`([op(pas),f],ord,1);
2799 if 1 < nops([%]) then pf := f else pf := %[nops(%)] fi;
2800 if `charsets/cfactor_switch` and 1 < nops(pas) then
2801 fn := `charsets/cfactor`(pf,[pas[nops(pas)]],ord);
2802 if max(op(map(degree,[op(numer(fn))],vf))) < degree(pf,vf) then
2803 RETURN(`charsets/cfactorsub`(numer(fn),pas,ord)/denom(fn))
2804 else
2805 fn := `charsets/cfactor`(pf,[op(1 .. nops(pas)-1,pas)],ord);
2806 if max(op(map(degree,[op(numer(fn))],vf))) < degree(pf,vf) then
2807 RETURN(`charsets/cfactorsub`(numer(fn),pas,ord)/denom(fn))
2811 if {con,`charsets/degreel`(pf,ord)} = {2} and nops(pas) < 3 then
2812 `charsets/factoras`(pf,pas,ord)
2813 else
2814 if 1 < printlevel then
2815 lprint(`newfactoras: factorization over algebraic field: degree`,
2816 `charsets/degreel`(pf,ord),terms,nops(pf))
2818 `charsets/con` := true;
2819 `charsets/newfactorassub`(pf,pas,ord)
2821 end:
2823 # test for a trivial case --- can it be extended?
2824 # a trivial case
2825 `charsets/trivial` :=
2827 proc(ff,aa,vf,va,fn)
2828 local f,a,da,df,ss,i;
2829 f := expand(ff);
2830 a := expand(aa);
2831 da := degree(a,va);
2832 df := degree(f,vf);
2833 if numer(f/lcoeff(f)) = subs(va = vf,numer(a/lcoeff(a))) and 2 < nops(f)
2834 then
2835 fn := 1;
2836 ss := [coeff(f,vf,da)];
2837 for i from df-1 by -1 to 0 do
2838 ss := [ss[1]*va+coeff(f,vf,i),op(ss)]
2840 sum('ss[i+1]*vf^(i-1)','i' = 1 .. df);
2841 RETURN((vf-va)*%)
2843 sum('`charsets/_z`^(da-i)*va^i*coeff(a,va,i)','i' = 0 .. da);
2844 sum('`charsets/_z`^(df-i)*vf^i*coeff(f,vf,i)','i' = 0 .. df);
2845 `charsets/premB`(%,%%,`charsets/_z`,'fn');
2846 if `charsets/degree`(%,`charsets/_z`) = 0 then factor(%) else f fi
2847 end:
2849 # modified pseudo-divison with multiplied initial factor as fn
2850 `charsets/premB` :=
2852 proc(uu,vv,x,fn)
2853 local r,v,dr,dv,l,t,lu,lv,gn;
2854 if type(vv/x,integer) then fn := 1; subs(x = 0,uu)
2855 else
2856 gn := 1;
2857 r := expand(uu);
2858 dr := degree(r,x);
2859 v := expand(vv);
2860 dv := degree(v,x);
2861 if dv <= dr then l := coeff(v,x,dv); v := expand(v-l*x^dv)
2862 else l := 1
2864 if 1 < printlevel and 500 < nops(r)+nops(v) then
2865 lprint(`pseudo-division:`,[nops(r),x,dr],[nops(v),x,dv])
2867 while dv <= dr and r <> 0 do
2868 gcd(l,coeff(r,x,dr),'lu','lv');
2869 t := expand(x^(dr-dv)*v*lv);
2870 if dr = 0 then r := 0 else r := subs(x^dr = 0,r) fi;
2871 r := expand(lu*r)-t;
2872 gn := gn*lu;
2873 dr := degree(r,x)
2875 fn := gn;
2878 end:
2880 # main subroutine for newfactoras
2881 # considerably modified and improved in December 1991
2882 `charsets/newfactorassub` :=
2884 proc(f,as,ord)
2885 local nord,mord,cs,ccs,ccs1,cr,i,con,ff,fff,nas,vf,die,der,ci,fs,m,n,inda,indb,
2886 is,CS,fmedset,ncs,cc,bb;
2887 global `charsets/with`,`charsets/das`,`charsets/con`;
2888 options remember;
2889 nas := nops(as);
2890 vf := `charsets/lvar`(f,ord);
2891 if 1 < nas then
2892 for i from 2 to nas do
2893 `charsets/newfactorassub`(as[i],[op(1 .. i-1,as)],ord) := as[i]
2896 '`charsets/lvar`(as[i],ord)' $ ('i' = 1 .. nas);
2897 nord := [vf,%];
2898 mord := [%%,vf];
2899 con := 0;
2900 for i from 2 to nops(nord) do
2901 con := con+`charsets/degree`(f,nord[i])
2903 if con = 0 then
2904 if nas = 1 then
2905 m := `charsets/degree`(as[1],nord[2]);
2906 n := `charsets/degree`(f,vf);
2907 if igcd(m,n) = 1 then RETURN(f) fi
2910 indets({f,op(as)}) minus {op(nord)};
2911 if nops(%) = 1 and nargs = 3 then
2912 RETURN(`charsets/tefactor`(f,as,mord,[op(%)]))
2914 indb := true;
2915 ci := [];
2916 cr := [];
2917 fff := f;
2919 if indb then
2920 if con <> 0 and `charsets/con` then der := 0; ff := f; con := 0
2921 else
2922 if `charsets/das` <> [false] then
2923 die := `charsets/das`[1];
2924 `charsets/das` :=
2925 [op(2 .. nops(`charsets/das`),`charsets/das`)]
2926 else die := `charsets/die`()
2928 der := sum('(i-die-2)*nord[i]','i' = 2 .. nops(nord));
2929 ff := expand(subs(vf = der+vf,f))
2931 `charsets/con` := false;
2932 `charsets/with` := {};
2933 if 1 < printlevel then
2934 lprint(`Characteristic set computation:`,
2935 `charsets/index`([op(as),ff],nord))
2937 fmedset := subs(`charsets/remseta` = `charsets/remsetaA`,
2938 `charsets/fqcharsetn` = fmedset,op(`charsets/fqcharsetn`));
2939 is:=nord[nops(nord)];
2940 if nops(as) = 1 and degree(as[1],is) > 5 and degree(ff,is) > 5
2941 and nops(indets(as) union indets(ff)) = 2 then
2942 ccs := factor(resultant(ff,as[1],is));
2943 if type(ccs,`+`) then RETURN(f)
2944 elif degree(as[1],is) < degree(ff,is) then
2945 ccs := [ccs,as[1]]
2946 else
2947 ccs := [ccs,ff]
2949 fs := [{},{}]
2950 else
2951 ccs := fmedset([op(as),ff],nord,[{},{}],'fs')
2953 is := `charsets/initialset`(ccs,nord);
2954 fs := `charsets/factorps`(`charsets/movefactorps`(fs[1],is,nord));
2955 cs := {`charsets/qfactor`(
2956 factor(`charsets/movefactorps`(ccs[1],is union fs,ord)),nord)}
2958 if not indb or cs = {} then
2959 `charsets/with` := {};
2960 if fs = {} then bb := is[1]; is := is minus {is[1]}
2961 else bb := fs[1]; fs := fs minus {fs[1]}
2963 ccs :=
2964 subs(`charsets/remseta` = `charsets/remsetaA`,`charsets/charsetn`)
2965 ([op(as),ff,bb],nord);
2966 is := `charsets/initialset`(ccs,nord);
2967 cs := {`charsets/qfactor`(
2968 factor(`charsets/movefactorps`(ccs[1],is union fs,ord)),nord)};
2969 indb := true
2971 if cs <> {} then
2972 if `charsets/checkwith`(`charsets/with`,is union fs) then
2973 inda := true
2974 else inda := false
2976 if `charsets/linearas`(ccs,nord) or 1 < nops(cs) then
2977 if nops(cs) = 1 then
2978 if inda then ccs1 := [cs[1],op(2 .. nops(ccs),ccs)]
2979 else
2980 ccs1 := `charsets/charseta`(
2981 [op(as),ff,cs[1],op(2 .. nops(ccs),ccs)],nord,
2982 `charsets/charsetn`)
2984 while `charsets/class`(ccs1[1],nord) = 0 do
2985 if fs = {} then bb := is[1]; is := is minus {is[1]}
2986 else bb := fs[1]; fs := fs minus {fs[1]}
2988 ccs1 := `charsets/charseta`(
2989 [op(as),ff,bb],nord,`charsets/charsetn`)
2991 if ccs1 <> ccs then
2992 ccs := ccs1;
2993 cs := [`charsets/qfactor`(factor(ccs[1]),nord)]
2996 if nops(cs) = 1 then
2997 if `charsets/linearas`(ccs,nord) then
2998 cc :=
2999 `charsets/algcd`(f,subs(vf = vf-der,ccs[1]),as,mord)
3001 if 0 < `charsets/degree`(cc,vf) then
3002 cs := [`charsets/arrange`(is union fs,vf)];
3003 if 1 < printlevel then
3004 lprint(`A non-trivial factor found:`,cc)
3006 if nops(cs) = 0 then ci := [fff]; fff := 1
3007 else
3008 fff := `charsets/divide`(fff,cc,as,mord);
3009 ci := [cc]
3011 CS := subs(vf = vf-der,cs);
3012 for i to nops(CS) do
3013 if 2 < printlevel then
3014 lprint(`Algebraic GCD:`,nops(CS),i)
3016 cc :=
3017 `charsets/algcd`(fff,expand(CS[i]),as,mord)
3019 if 0 < `charsets/degree`(cc,vf) then
3020 fff := `charsets/divide`(fff,cc,as,mord);
3021 if 1 < printlevel then
3022 lprint(`A non-trivial factor found:`,cc
3025 if `charsets/degree`(cc,vf) = 1 then
3026 ci := [op(ci),cc]
3027 else cr := [op(cr),cc]
3031 break
3032 else indb := false
3035 else
3036 ncs := nops(cs);
3037 cs := [`charsets/arrange`(cs,vf),
3038 `charsets/arrange`(is union fs,vf)];
3039 CS := subs(vf = vf-der,cs);
3040 for i to nops(CS) do
3041 if 2 < printlevel then
3042 lprint(`Algebraic GCD:`,nops(CS),i)
3044 cc := `charsets/algcd`(fff,expand(CS[i]),as,mord);
3045 if 0 < `charsets/degree`(cc,vf) then
3046 fff := `charsets/divide`(fff,cc,as,mord);
3047 if 1 < printlevel then
3048 lprint(`A non-trivial factor found:`,cc)
3050 if `charsets/degree`(cc,vf) = 1 then
3051 ci := [op(ci),cc]
3052 else
3053 if i <= ncs then
3054 con := op(2 .. nops(ccs),ccs);
3055 if inda and not `charsets/vanish`(cs[i],is)
3056 then
3057 con := [cs[i],con]
3058 else
3059 con := `charsets/charseta`(
3060 {op(as),con,ff,cs[i]},nord,
3061 `charsets/charsetn`)
3063 if con[1] = cs[i] and
3064 `charsets/linearas`(con,nord) then
3065 ci := [op(ci),cc]
3066 else cr := [op(cr),cc]
3068 else cr := [op(cr),cc]
3073 if 0 < nops(ci) or 1 < nops(cr) or nops(cr) = 1 and
3074 `charsets/degree`(numer(cr[1]),vf) <
3075 `charsets/degree`(f,vf) then
3076 break
3082 `charsets/degree`(fff,vf);
3083 if 1 < % then cr := [op(cr),fff] elif % = 1 then ci := [op(ci),fff] fi;
3084 if nops(ci) = 0 then
3085 `charsets/prod`(
3086 ['`charsets/newfactorassub`(cr[i],as,ord)' $ ('i' = 1 .. nops(cr))]
3088 elif nops(cr) = 0 then product('ci[i]','i' = 1 .. nops(ci))
3089 else
3090 product('ci[i]','i' = 1 .. nops(ci))*`charsets/prod`(
3091 ['`charsets/newfactorassub`(cr[i],as,ord)' $ ('i' = 1 .. nops(cr))]
3094 end:
3096 # compute the GCD of f and g over the algebraic field having
3097 # adjoining asc set as
3098 `charsets/algcd` :=
3100 proc(f,g,as,mord)
3101 local nas,fs;
3102 nas := nops(as)+1;
3103 if `charsets/degree`(f,mord[nas]) = 0 or `charsets/degree`(g,mord[nas]) = 0
3104 then
3105 RETURN(1)
3107 if 1 < printlevel then
3108 lprint(`GCD computation over algebraic field:`,
3109 `charsets/index`([f,g],mord),op(`charsets/index`(as,mord)))
3111 op(1,[`charsets/fcnormal`(
3112 `charsets/fcharsetnA`(as,[f,g],mord,[{},{}],'fs'),mord,2)]);
3113 if nops(%) = nas then %[nas] else 1 fi
3114 end:
3116 # subroutine for algcd
3117 `charsets/fcharsetnA` :=
3119 proc(as,ps,ord,fset1,fset)
3120 local cs,rs,fset2,fset3,nas;
3121 nas := nops(as)+1;
3122 cs := [op(as),op(`charsets/basset`(ps,ord))];
3123 fset2 := [fset1[1],fset1[2] union `charsets/initialset1`(cs,ord)];
3124 if 0 < `charsets/degree`(cs[nas],ord[nas]) then
3125 rs := `charsets/remseta`(`charsets/minus`(ps,cs),cs,ord);
3126 rs := `charsets/removefactor`(rs,ord,fset2,'fset3')
3127 else fset := fset2; RETURN([1])
3129 if rs = [] then fset := fset3; cs
3130 else `charsets/fcharsetnA`(as,[op(rs),cs[nas]],ord,fset3,'fset')
3132 end:
3134 # compute the GCD of f and g over the algebraic field having
3135 # adjoining asc set as -- using Maple's built-in function
3136 # Malgcd is sometimes faster than algcd and is not used
3137 `charsets/Malgcd` :=
3139 proc(f,g,as,mord)
3140 local nas,i;
3141 nas := nops(as);
3142 [f,g];
3143 for i from nas by -1 to 1 do subs(mord[i] = RootOf(as[i],mord[i]),%) od;
3144 evala(Gcd(op(%)));
3145 for i to nas do subs(RootOf(as[i],mord[i]) = mord[i],%) od;
3147 end:
3149 # division over an algebraic field with adjoining ascending set as
3150 `charsets/divide` :=
3152 proc(ff,f,as,ord)
3153 local m,q;
3154 sprem(ff,f,`charsets/lvar`(ff,ord),'m','q'); `charsets/premas`(q,as,ord)
3155 end:
3157 # check if an ascending set is quasilinear
3159 `charsets/linearas` :=
3161 proc(cs,ord)
3162 local i;
3163 if nops(cs) = 1 then true
3164 else
3165 for i from 2 to nops(cs) do
3166 if 1 < `charsets/degreel`(cs[i],ord) then RETURN(false) fi
3168 true
3170 end:
3172 # order a set ps of polys according their degrees in x
3173 `charsets/arrange` :=
3175 proc(ps,x) `charsets/reorderb`([op(ps)],`charsets/arrangesub`,x); op(%) end:
3177 # subroutine for arrange
3178 `charsets/arrangesub` :=
3180 proc(f,g,x)
3181 if `charsets/degree`(f,x) < `charsets/degree`(g,x) then true
3182 else false
3184 end:
3186 # random generator for linear transformation
3187 `charsets/die` := rand(3 .. 8):
3189 # remove polys in ps as factors from f
3190 `charsets/movefactorps` :=
3192 proc(f,ps,ord)
3193 local p,ff,i;
3194 if not type(f,{set,list}) then
3195 ff := f; for p in ps do ff := `charsets/movefactor`(ff,p,ord) od; ff
3196 else {'`charsets/movefactorps`(f[i],ps,ord)' $ ('i' = 1 .. nops(f))}
3198 end:
3200 # check if q vansihes one poly in ps
3201 `charsets/vanish` :=
3203 proc(q,ps)
3204 local p;
3205 for p in ps do if divide(q,p) then RETURN(true) fi od; false
3206 end:
3208 # sequence of non-constant factors of f
3209 `charsets/qfactor` :=
3211 proc(f,ord)
3212 local i;
3213 if `charsets/class`(f,ord) = 0 then op({})
3214 elif type(f,`^`) then op(1,f); numer(%/lcoeff(%))
3215 elif type(f,`*`) then
3216 '`charsets/qfactor`(op(i,f),ord)' $ ('i' = 1 .. nops(f))
3217 else numer(f/lcoeff(f))
3219 end:
3221 # sequence of non-constant (multiple) factors of f
3222 `charsets/qqfactor` :=
3224 proc(f,ord)
3225 local i;
3226 if `charsets/class`(f,ord) = 0 then op({})
3227 elif type(f,`^`) then
3228 op(1,f); 'numer(%/lcoeff(%))' $ ('i' = 1 .. op(2,f))
3229 elif type(f,`*`) then
3230 '`charsets/qqfactor`(op(i,f),ord)' $ ('i' = 1 .. nops(f))
3231 else numer(f/lcoeff(f))
3233 end:
3235 # the following routines implement a heuristic procedure for poly factorizati
3237 # over algebraic function fields by integer substitution and solving systems
3238 # of linear equations
3239 # the main routine
3240 `charsets/tefactor` :=
3242 proc(f,as,ord,var)
3243 local
3244 i,j,k,vf,nv,df,inf,ff,gg,ja,js,fs,ffs,hs,gs,sol,ci,dvar,tvar,mm,tt,yvar,das
3246 global `charsets/das`,`charsets/dasA`,`charsets/dieA`;
3247 nv := nops(var);
3248 vf := ord[nops(ord)];
3249 df := `charsets/degree`(f,vf);
3250 if nv = 1 and nops(as) = 1 then
3251 `charsets/prem`(f,as[1],var[1]);
3252 if % <> f then
3253 factor(%);
3254 [`charsets/qqfactor`(%,[vf])];
3255 if type(%%,{`*`,`^`}) and
3256 max('`charsets/degree`(%[i],vf)' $ ('i' = 1 .. nops(%))) < df
3257 then
3258 ['op(2,op(1,[`charsets/fcnormal`([as[1],%[i]],ord,2)]))' $
3259 ('i' = 1 .. nops(%))];
3260 RETURN(`charsets/prod`(map(`charsets/newfactoras`,%,as,ord)))
3264 inf := lcoeff(f,vf);
3265 for i to nv do `charsets/@m`.i := 1 od;
3266 js := [];
3267 fs := [];
3268 `charsets/dasA` := [1,-1,2,-2,3,-3,false];
3269 `charsets/dieA` := rand(-10*nv .. 10*nv);
3270 das :=
3271 proc()
3272 global `charsets/dasA`,`charsets/dieA`;
3273 if `charsets/dasA` <> [false] then
3274 `charsets/dasA`[1];
3275 `charsets/dasA` := [op(2 .. nops(`charsets/dasA`),`charsets/dasA`)]
3278 else `charsets/dieA`()
3280 end:
3282 tvar := `charsets/noterms`(nv,`charsets/degree`(f,var));
3283 dvar := 0;
3284 ci := {};
3285 gg := _y1;
3286 yvar := {_y1};
3287 for mm while ci = {} and dvar < tvar do
3288 dvar := `charsets/noterms`(nv,mm);
3289 while nops(js) < dvar do
3290 sol := 'var[i] = das()' $ ('i' = 1 .. nv);
3291 if subs(sol,inf) <> 0 and `charsets/isirr`(subs(sol,as),ord) then
3292 js := [op(js),{sol}];
3293 ff := {`charsets/qfactor`(
3294 `charsets/cfactor`(subs(sol,f),subs(sol,as),ord),[vf])};
3296 max('`charsets/degree`(ff[i],vf)' $ ('i' = 1 .. nops(ff))) = df
3297 then
3298 RETURN(f)
3299 else fs := [op(fs),ff]
3303 sum('var[i]','i' = 1 .. nops(var));
3304 coeffs(expand(%^mm),var,'tt');
3305 tt := [tt];
3306 nops(gg);
3307 gg := gg+sum('_y.(%+i)*tt[i]','i' = 1 .. nops(tt));
3308 yvar := yvar union {'_y.(%%+i)' $ ('i' = 1 .. nops(tt))};
3309 hs := {};
3310 ffs := fs;
3311 for j to nops(fs[1]) do
3312 gs := [fs[1][j]];
3313 if 1 < nops(fs) then
3314 for i from 2 to nops(fs) do
3315 `charsets/getclose`(fs[1][j],[op(fs[i])],ord,'ja');
3316 if % = FAIR then
3317 if 1 < printlevel then
3318 lprint(`Heuristic tefactor failed`)
3320 RETURN(`charsets/newfactorassub`(f,as,ord,0))
3321 else gs := [op(gs),%]
3323 fs[i] minus {fs[i][ja]};
3324 if i = nops(fs) then fs := [op(1 .. i-1,fs),%]
3325 else fs := [op(1 .. i-1,fs),%,op(i+1 .. nops(fs),fs)]
3329 sol := {'subs(op(js[k]),gg)-gs[k]' $ ('k' = 1 .. nops(js))};
3330 sol := {solve(sol,yvar)};
3331 if sol <> {} then hs := hs union {expand(subs(op(sol),gg))} fi
3333 fs := ffs;
3334 ff := f;
3335 for j in hs do
3336 `charsets/divideA`(ff,j,as,ord);
3337 if % <> false then
3338 ff := %;
3339 ci := ci union {j};
3340 if 1 < printlevel then lprint(`A factor found:`,j) fi
3344 ci = {} and mm <= 1 and _help <> true and nops(ffs[1])^nops(ffs) <= 128
3345 then
3346 gs := `charsets/getall`(ffs);
3347 for i to nops(gs) while nops(ci) <= nops(fs[1]) do
3348 sol := {'subs(op(js[k]),gg)-gs[i][k]' $ ('k' = 1 .. nops(js))};
3349 sol := {solve(sol,yvar)};
3350 if 1 < printlevel and sol = {} then lprint(sol,yvar) fi;
3351 if sol <> {} then
3352 sol := expand(subs(op(sol),gg));
3353 `charsets/divideA`(ff,sol,as,ord);
3354 if % <> false then
3355 ff := %;
3356 ci := ci union {sol};
3357 if 1 < printlevel then
3358 lprint(`A non-trivial factor found:`,j)
3365 if ci <> {} then
3366 ci := ci union {ff};
3367 `charsets/prod`(map(`charsets/newfactoras`,ci,as,ord))
3368 else
3369 if 1 < printlevel then lprint(`Heuristic tefactor failed`) fi;
3370 `charsets/newfactorassub`(f,as,ord,0)
3372 end:
3374 # numbers of maximal terms in a poly of total degree d in n variables
3375 `charsets/noterms` :=
3377 proc(n,d)
3378 local i,j;
3379 sum('product('n+j-1','j' = 1 .. i)/i!','i' = 1 .. d)+1
3380 end:
3382 # check if an ascending set as is irreducible
3383 `charsets/isirr` :=
3385 proc(as,ord)
3386 local xa,fs,f,as1;
3387 if nops(as) = 1 then
3388 xa := `charsets/lvar`(as[1],ord);
3389 if xa = 0 then false
3390 elif `charsets/degree`(as[1],xa) = 1 then true
3391 else
3392 fs := {`charsets/qfactor`(factor(as[1]),[xa])};
3393 if nops(fs) = 1 then true else false fi
3395 else
3396 as1 := [op(1 .. nops(as)-1,as)];
3397 if not `charsets/isirr`(as1,ord) then false
3398 else
3399 f := as[nops(as)];
3400 xa := `charsets/lvar`(f,ord);
3401 if xa = 0 then false
3402 elif `charsets/degree`(f,xa) = 1 then true
3403 else
3404 fs := {`charsets/qfactor`(`charsets/cfactor`(f,as1,ord),[xa])};
3405 if nops(fs) = 1 then true else false fi
3409 end:
3411 # get all possible combinations (used for tefactor)
3412 `charsets/getall` :=
3414 proc(fs)
3415 local gs,i,j,nf;
3416 if nops(fs) = 1 then {'[fs[1][i]]' $ ('i' = 1 .. nops(fs[1]))}
3417 else
3418 nf := nops(fs);
3419 gs := {op(1 .. nf-1,fs)};
3420 gs := `charsets/getall`(gs);
3421 {''[op(gs[i]),fs[nf][j]]' $ ('j' = 1 .. nops(fs[nf]))' $
3422 ('i' = 1 .. nops(gs))}
3424 end:
3426 # select a poly in fs closest to g
3427 `charsets/getclose` :=
3429 proc(g,fs,var,ja)
3430 local i,j,gs,hs,dg,nv,vv,jaa,jbb,ts,cv,rr,chs,df;
3431 if `charsets/class`(g,var) = 0 then RETURN(FAIR) fi;
3432 if nops(fs) = 1 then ja := 1; RETURN(fs[1]) fi;
3433 if nops(var) = 1 and _help <> true then
3434 gs := [];
3435 jaa := [];
3436 dg := `charsets/degree`(g,var[1]);
3437 for i to nops(fs) do
3438 if fs[i] = g or fs[i] = -g then ja := i; RETURN(fs[i])
3439 elif `charsets/degree`(fs[i],var[1]) = dg then
3440 jaa := [op(jaa),i]; gs := [op(gs),fs[i]]
3443 if nops(jaa) = 1 then ja := jaa[1]; RETURN(gs[1]) fi;
3444 hs := [];
3445 jbb := [];
3446 cv := [coeffs(expand(g),var[1],'dg')];
3447 for i to nops(jaa) do
3448 coeffs(expand(gs[i]),var[1],'df');
3449 if {df} = {dg} then jbb := [op(jbb),jaa[i]]; hs := [op(hs),gs[i]]
3452 if nops(jbb) = 1 then ja := jbb[1]; RETURN(hs[1]) fi;
3453 gs := [];
3454 jaa := [];
3455 dg := ['sign(cv[j])' $ ('j' = 1 .. nops(cv))];
3456 for i to nops(jbb) do
3457 ts := [coeffs(expand(hs[i]),var[1])];
3458 ts := ['sign(ts[j])' $ ('j' = 1 .. nops(ts))];
3459 if `charsets/close`(ts,dg) = 0 then
3460 jaa := [op(jaa),jbb[i]]; gs := [op(gs),hs[i]]
3463 if nops(gs) = 1 then ja := jaa[1]; RETURN(gs[1]) fi;
3464 gs := [];
3465 jaa := [];
3466 for i to nops(jbb) do
3467 ts := [coeffs(expand(hs[i]),var[1])];
3468 ts := ['sign(ts[j])' $ ('j' = 1 .. nops(ts))];
3469 if `charsets/close`(ts,dg) = 1 then
3470 jaa := [op(jaa),jbb[i]]; gs := [op(gs),hs[i]]
3473 if nops(gs) = 1 then ja := jaa[1]; RETURN(gs[1]) fi;
3474 gs := [];
3475 jaa := [];
3476 for i to nops(jbb) do
3477 ts := [coeffs(expand(hs[i]),var[1])];
3478 ts := ['sign(ts[j])' $ ('j' = 1 .. nops(ts))];
3479 if `charsets/close`(ts,dg) = 2 then
3480 jaa := [op(jaa),jbb[i]]; gs := [op(gs),hs[i]]
3483 if nops(gs) = 1 then ja := jaa[1]; RETURN(gs[1]) else RETURN(FAIL) fi
3484 else
3485 if _help <> true then
3486 nv := nops(var);
3487 vv := var[nv];
3488 gs := [];
3489 jaa := [];
3490 dg := `charsets/degree`(g,vv);
3491 for i to nops(fs) do
3492 if fs[i] = g or fs[i] = -g then ja := i; RETURN(fs[i])
3493 elif `charsets/degree`(fs[i],vv) = dg then
3494 jaa := [op(jaa),i]; gs := [op(gs),fs[i]]
3497 if nops(jaa) = 1 then ja := jaa[1]; RETURN(gs[1]) fi;
3498 hs := [];
3499 jbb := [];
3500 hs := [];
3501 chs := [];
3502 cv := [coeffs(expand(g),vv,'dg')];
3503 for i to nops(gs) do
3504 chs := [op(chs),[coeffs(expand(gs[i]),vv,'df')]];
3505 if {df} = {dg} then
3506 jbb := [op(jbb),jaa[i]]; hs := [op(hs),gs[i]]
3509 if nops(jbb) = 1 then ja := jbb[1]; RETURN(hs[1]) fi;
3510 for i to nops([dg]) do
3511 ts := ['chs[j][i]' $ ('j' = 1 .. nops(chs))];
3512 `charsets/getclose`(
3513 cv[i],ts,['var[j]' $ ('j' = 1 .. nv-1)],'jbb');
3514 if % = FAIR then RETURN(FAIR)
3515 elif % <> FAIL then ja := jaa[jbb]; RETURN(hs[jbb])
3518 else hs := fs; jaa := ['i' $ ('i' = 1 .. nops(hs))]
3520 if hs <> [] then
3521 RETURN(FAIR);
3522 lprint(` `);
3523 lprint(`Please help to choose one polynomial in the list`);
3524 print(hs);
3525 lprint(`which is closest to the polynomial`);
3526 print(g);
3527 rr := readstat(`and enter the polynomial number in the list: `);
3528 ja := jaa[rr];
3529 RETURN(hs[rr])
3530 else ja := 1; RETURN(fs[1])
3533 end:
3535 # a subroutine for getclose
3536 `charsets/close` :=
3538 proc(ps,qs)
3539 local i,m;
3540 if ps = qs then 0
3541 else
3542 m := 0;
3543 for i to nops(ps) do if ps[i] <> qs[i] then m := m+1 fi od;
3546 end:
3548 # division over an algebraic field with adjoining ascending set as
3549 `charsets/divideA` :=
3551 proc(ff,f,as,ord)
3552 local m,q;
3553 if `charsets/class`(ff,ord) <> `charsets/class`(f,ord) then RETURN(false)
3555 sprem(ff,f,`charsets/lvar`(ff,ord),'m','q');
3556 if `charsets/premas`(%,as,ord) <> 0 then RETURN(false) fi;
3557 `charsets/premas`(q,as,ord)
3558 end:
3560 # factorize poly f over algebraic number field with minimal polys in as
3561 # -- Hu-Wang's method
3562 `charsets/factoras` :=
3564 proc(pf,pas,ord)
3565 local df,r,s,ff,i,t,fact,gg,hh,fg,z,ind,as,nas,f,vf,sol,con,m,n,mord,nord;
3566 global `charsets/das`,`charsets/con`;
3567 options remember;
3568 nas := nops(pas);
3569 vf := `charsets/lvar`(pf,ord);
3570 if 1 < nas then
3571 for i from 2 to nas do
3572 `charsets/factoras`(pas[i],[op(1 .. i-1,pas)],ord) := pas[i]
3575 '`charsets/lvar`(pas[i],ord)' $ ('i' = 1 .. nas);
3576 nord := [vf,%];
3577 mord := [%%,vf];
3578 con := 0;
3579 for i from 2 to nops(nord) do
3580 con := con+`charsets/degree`(pf,nord[i])
3582 if con = 0 then
3583 if nas = 1 then
3584 m := `charsets/degree`(pas[1],nord[2]);
3585 n := `charsets/degree`(pf,vf);
3586 if igcd(m,n) = 1 then RETURN(pf) fi
3589 indets({pf,op(pas)}) minus {op(nord)};
3590 if nops(%) = 1 and nargs = 3 then
3591 RETURN(`charsets/tsfactor`(pf,pas,mord,[op(%)]))
3593 ind := 0;
3594 as := [];
3595 r := 0;
3596 f := expand(pf);
3597 for i to nops(pas) do
3598 df := `charsets/degreel`(pas[i],ord);
3599 if 1 < df then
3600 r := r+1; `charsets/@m`.r := df; as := [op(as),expand(pas[i])]
3603 z := `charsets/lvar`(f,ord);
3604 df := `charsets/degree`(f,z);
3605 if df = 1 then f
3606 elif r = 0 then f
3607 else
3608 if 1 < printlevel then
3609 lprint(`factoras: factorization over algebraic field -- degree `,
3610 `charsets/degreel`(f,ord))
3612 for s to trunc(1/2*df) while ind = 0 do
3613 for i to s do
3614 `charsets/g`.i := `charsets/summ`(
3615 `charsets/@g`[i,'`charsets/@k`.t' $ ('t' = 1 .. r)]*product
3616 ('`charsets/lvar`(as[t],ord)^`charsets/@k`.t','t' = 1 .. r)
3619 for i to df-s do
3620 `charsets/h`.i := `charsets/summ`(
3621 `charsets/@h`[i,'`charsets/@k`.t' $ ('t' = 1 .. r)]*product
3622 ('`charsets/lvar`(as[t],ord)^`charsets/@k`.t','t' = 1 .. r)
3625 `charsets/g`.0 := 1;
3626 `charsets/h`.0 := 1;
3627 gg := sum('`charsets/g`.i*z^(s-i)','i' = 0 .. s);
3628 hh := sum('`charsets/h`.i*z^(df-s-i)','i' = 0 .. df-s);
3629 ff := f-lcoeff(expand(f),z)*expand(gg*hh);
3630 ff := expand(`charsets/premas`(ff,as,ord));
3631 fact := {};
3632 for i from 0 to df-1 do
3633 fact :=
3634 {op(fact),op(`charsets/coeff`(as,{coeff(ff,z,i)},r,ord))}
3636 sol := [`charsets/solveps`(fact,`charsets/getvars`(fact))];
3637 if sol = [FAIR] then
3638 if 1 < printlevel then
3639 lprint(`factoras changes to newfactoras`)
3641 `charsets/das` := [-1,1,-2,2,-3,false];
3642 `charsets/con` := true;
3643 RETURN(`charsets/newfactorassub`(pf,pas,ord))
3645 fg := f;
3646 if sol <> [] then
3647 fg := subs(sol[1],gg)*
3648 `charsets/factoras`(numer(subs(sol[1],hh)),as,ord);
3649 ind := 1
3652 numer(fg)
3654 end:
3656 # the following routine implements some heuristics for verifying the
3657 # irreducibilty of polynomials over algebraic function fields by
3658 # integer substitution
3659 `charsets/tsfactor` :=
3661 proc(f,as,ord,var)
3662 local i,vf,nv,df,inf,ff,sol,das;
3663 nv := nops(var);
3664 vf := ord[nops(ord)];
3665 df := `charsets/degree`(f,vf);
3666 if nv = 1 and nops(as) = 1 then
3667 `charsets/prem`(f,as[1],var[1]);
3668 if % <> f then
3669 factor(%);
3670 [`charsets/qqfactor`(%,[vf])];
3671 if type(%%,{`*`,`^`}) and
3672 max('`charsets/degree`(%[i],vf)' $ ('i' = 1 .. nops(%))) < df
3673 then
3674 ['op(2,op(1,[`charsets/fcnormal`([as[1],%[i]],ord,2)]))' $
3675 ('i' = 1 .. nops(%))];
3676 RETURN(`charsets/prod`(map(`charsets/factoras`,%,as,ord)))
3680 inf := lcoeff(expand(f),vf);
3681 das := rand(-2*nv .. 3*nv+nops(ord));
3682 sol := 'var[i] = i+1' $ ('i' = 1 .. nv);
3683 while subs(sol,inf) = 0 or not `charsets/isirr`(subs(sol,as),ord) do
3684 sol := 'var[i] = das()' $ ('i' = 1 .. nv)
3686 ff :=
3687 {`charsets/qfactor`(`charsets/cfactor`(subs(sol,f),subs(sol,as),ord),[vf])}
3689 if max('`charsets/degree`(ff[i],vf)' $ ('i' = 1 .. nops(ff))) = df then
3690 RETURN(f)
3692 if 1 < printlevel then lprint(`Heuristic tsfactor failed`) fi;
3693 `charsets/factoras`(f,as,ord,0)
3694 end:
3696 # subroutine for factoras
3697 `charsets/summ` :=
3699 proc(ss,r)
3700 if r = 1 then sum(ss,`charsets/@k`.r = 0 .. `charsets/@m`.r-1)
3701 else
3702 sum(`charsets/summ`(ss,r-1),`charsets/@k`.r = 0 .. `charsets/@m`.r-1)
3704 end:
3706 # subroutine for factoras
3707 `charsets/coeff` :=
3709 proc(as,ss,r,ord)
3710 local k,i,j,qs;
3711 qs := ss;
3712 for j from r by -1 to 1 do
3713 qs := {''coeff(qs[i],`charsets/lvar`(as[j],ord),k)' $
3714 ('k' = 0 .. `charsets/@m`.j-1)' $ ('i' = 1 .. nops(qs))}
3716 qs minus {0}
3717 end:
3719 # subroutine for factoras
3720 `charsets/getvars` :=
3722 proc(as)
3723 local ind,ind1,i;
3724 if type(as,{set,list}) then
3725 {'op(`charsets/getvars`(as[i]))' $ ('i' = 1 .. nops(as))}
3726 else
3727 ind := {};
3728 ind1 := indets(as);
3729 for i in ind1 do
3730 if type(i,indexed) then
3731 if op(0,i) = `charsets/@g` or op(0,i) = `charsets/@h` then
3732 ind := {op(ind),i}
3738 end:
3740 # find rational zeros of poly set ps
3741 `charsets/solveps` :=
3743 proc(ps,lst)
3744 local cs,ord,sol,j,phi,qs,qs1,n,factorset;
3745 options remember;
3746 if 1 < printlevel then
3747 lprint(
3748 `solveps: trying rational solutions of equations:`,nops(ps),nops(lst)
3751 if 3 < printlevel then lprint(op(`charsets/index`([op(ps)],[op(lst)])))
3753 ord := `charsets/reorder`([op(lst)],`charsets/degord`,ps);
3754 sol := {};
3755 cs := `charsets/fqcharsetn`(ps,ord,[{},{}],'factorset');
3756 factorset := factorset[1];
3757 phi := {ps};
3758 for n while phi <> {} do
3759 if 6 < n+nops(phi) or sol = {FAIR} then RETURN(FAIR) fi;
3760 if sol <> {} then break fi;
3761 if 1 < n then
3762 cs := `charsets/charseta`(phi[1],ord,`charsets/`.wcharsetn);
3763 factorset := {}
3765 sol := {op(sol),`charsets/solveasr`(cs,ord,'qs1')};
3766 if n = 1 then sol := `charsets/verify`(sol,ps,ord) fi;
3767 qs := `charsets/factorps`(qs1) union `charsets/factorps`(factorset);
3768 `charsets/qbasset`(qs,ord);
3769 qs := [op(%),op(qs minus {op(%)})];
3770 if qs <> {} then
3771 if 1 < nops(phi) then
3772 phi := {op(2 .. nops(phi),phi),
3773 '[op(phi[1]),qs[j]]' $ ('j' = 1 .. nops(qs))}
3774 else phi := {'[op(phi[1]),qs[j]]' $ ('j' = 1 .. nops(qs))}
3776 else
3777 if 1 < nops(phi) then phi := {op(2 .. nops(phi),phi)}
3778 else phi := {}
3782 if sol = {} then op({}) else op(sol) fi
3783 end:
3785 # subroutine for solveps
3786 `charsets/verify` :=
3788 proc(sol,ps,ord)
3789 local i,j,sss;
3790 for i to nops(sol) do
3791 if simplify(subs(sol[i],ps)) = {0} then RETURN({sol[i]})
3792 else
3793 {'op(1,sol[i][j])-op(2,sol[i][j])' $ ('j' = 1 .. nops(sol[i]))};
3794 sss := {`charsets/solveps`(ps union %,ord)};
3795 if sss <> {} then RETURN(sss) fi
3799 end:
3801 # prepare a list of triangular forms from poly set ps
3802 `charsets/trisersub` :=
3804 proc(ps,ord)
3805 local qs,cs,iss,n,i,qhi,qsi,factorset,csno,ppi,qqi,ind,mem;
3806 options remember;
3807 ind := 0;
3808 for i to nops(ps) do
3809 if nops(expand(ps[i])) < 3 then ind := 1; break fi
3811 if ind = 1 then
3812 cs := `charsets/fcharseta`([op(ps)],ord,`charsets/`.charsetn)
3813 else cs := `charsets/fcharseta`([op(ps)],ord,`charsets/`.qcharsetn)
3815 factorset := op(2,cs[2]);
3816 cs := cs[1];
3817 qhi := {{op(ps)}};
3818 qsi := {};
3819 csno := 0;
3820 ppi := {};
3821 qqi := {};
3822 for n from 0 while qhi <> {} do
3823 qhi := sort([op(qhi)],`charsets/nopsord`);
3824 qs := qhi[1];
3825 ppi := `charsets/select`(ppi,nops(qs));
3826 qqi := {op(qqi),op(ppi[2])};
3827 if n = 0 then ppi := {}
3828 else
3829 ppi := {qs,op(ppi[1])};
3830 ind := 0;
3831 for i to nops(ps) do
3832 if nops(expand(ps[i])) < 3 then ind := 1; break fi
3834 if ind = 1 then
3835 cs := `charsets/nopower`(
3836 `charsets/charseta`(qs,ord,`charsets/`.charsetn));
3837 factorset := {}
3838 elif qs <> mem and 4 < `charsets/degree`(qs[1],ord) then
3839 cs := `charsets/fcharseta`(qs,ord,`charsets/`.qcharsetn);
3840 factorset := op(2,cs[2]);
3841 cs := cs[1]
3842 elif nops(qs)-3 < nops(ord) then
3843 cs := `charsets/fcharseta`(qs,ord,`charsets/`.wcharsetn);
3844 factorset := op(2,cs[2]);
3845 cs := cs[1]
3846 else
3847 cs := `charsets/nopower`(
3848 `charsets/charseta`(qs,ord,`charsets/`.wcharsetn));
3849 factorset := {}
3852 mem := qs;
3853 if 1 < printlevel then
3854 csno := csno+1;
3855 lprint(
3856 `Characteristic set produced`,csno,nops(qhi),nops(qsi),nops(qs)
3858 print(cs)
3860 if 0 < `charsets/class`(cs[1],ord) then
3861 iss := `charsets/initialset`(cs,ord);
3862 if `charsets/simpa`(iss,cs,ord) <> 0 then qsi := {cs,op(qsi)} fi;
3863 iss := iss union `charsets/factorps`(factorset)
3864 else iss := `charsets/factorps`(factorset)
3866 iss := `charsets/adjoina`(iss,qs,qqi);
3867 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
3868 else qhi := iss
3871 if qsi = {} then []
3872 else op(sort(`charsets/contract`(qsi,ord,-1),`charsets/lenord`))
3874 end:
3876 # find zeros of ascending set as
3877 `charsets/solveas` :=
3879 proc(cs,ord)
3880 local is,ss,sol,solm,i,j,k;
3881 sol := {solve({cs[1]},{`charsets/lvar`(cs[1],ord)})};
3882 if 1 < nops(cs) then
3883 for i from 2 to nops(cs) do
3884 is := `charsets/initial`(cs[i],ord);
3885 solm := {};
3886 for j to nops(sol) do
3887 ss :=
3888 {solve({subs(sol[j],cs[i])},{`charsets/lvar`(cs[i],ord)})};
3889 for k to nops(ss) do
3890 if subs(op(sol[j]),ss[k],is) <> 0 then
3891 solm := {op(solm),{op(sol[j]),op(ss[k])}}
3895 sol := solm
3898 op(sol)
3899 end:
3901 # find rational zeros of ascending set cs
3902 `charsets/solveasr` :=
3904 proc(cs,ord,qs)
3905 local is,ss,ts,sol,solm,i,j,k;
3906 ts := {};
3907 if 0 < `charsets/class`(cs[1],ord) then
3908 sol := {`charsets/solvel`(cs[1],`charsets/lvar`(cs[1],ord))};
3909 if 1 < nops(cs) then
3910 for i from 2 to nops(cs) do
3911 if 1 <= nops(sol) then
3912 is := `charsets/initial`(cs[i],ord);
3913 solm := {};
3914 for j to nops(sol) do
3915 if simplify(subs(op(sol[j]),is)) = 0 then
3916 ts := {is,op(ts)}
3917 else
3918 ss := {`charsets/solvel`(
3919 subs(sol[j],cs[i]),`charsets/lvar`(cs[i],ord))}
3921 solm := {op(solm),
3922 '{op(sol[j]),op(ss[k])}' $ ('k' = 1 .. nops(ss))
3926 sol := solm
3927 else break
3931 else sol := {}
3933 if 2 < nargs then qs := ts fi;
3934 op(sol)
3935 end:
3937 # find rational zeros of polynomial f wrt x: subroutine for solveasr
3938 `charsets/solvel` := proc(f,x)
3939 local g,i,sol;
3940 sol := {};
3941 if nops(indets(f)) = 1 then
3942 g := `charsets/getfactor`(f,x);
3943 for i in g do sol := {op(sol),solve({i},{x})} od
3944 else
3945 g := `charsets/factorps`({numer(f)});
3946 for i in g do
3947 if `charsets/degree`(i,x) = 1 then
3948 sol := {op(sol),solve({i},{x})}
3952 op(sol)
3953 end:
3955 # find a list of distinct linear factors of univariate poly f
3956 `charsets/getfactor` :=
3958 proc(f,x)
3959 local q,qs,j;
3960 q := `charsets/getfact`(f,x);
3961 qs := {};
3962 if type(q,`*`) then
3963 for j to nops(q) do
3964 if not type(op(j,q),integer) then
3965 if type(op(j,q),`^`) then
3966 qs := {op(qs),numer(op(1,op(j,q))/lcoeff(op(1,op(j,q))))}
3967 else qs := {op(qs),numer(op(j,q)/lcoeff(op(j,q)))}
3971 elif type(q,`^`) then qs := {op(qs),numer(op(1,q)/lcoeff(op(1,q)))}
3972 else if not type(q,integer) then qs := {numer(q/lcoeff(q)),op(qs)} fi
3974 [op(qs)]
3975 end:
3977 # find the product of linear factors of univar poly f using `factor/linfacts`
3978 `charsets/getfact` :=
3980 proc(ff,x)
3981 local i,f;
3982 if `charsets/degree`(ff,x) = 1 then RETURN(ff) fi;
3983 f := convert(ff,`sqrfree/sqrfree`,x);
3984 if type(f,`^`) then
3985 readlib(factor);
3986 readlib(`factor/polynom`);
3987 readlib(`factor/unifactor`);
3988 readlib(`factor/linfacts`)(expand(op(1,f)),x)
3989 elif type(f,`*`) then
3990 {'`charsets/getfact`(op(i,f),x)' $ ('i' = 1 .. nops(f))};
3991 product(op(i,%),i = 1 .. nops(%))
3992 else
3993 readlib(factor);
3994 readlib(`factor/polynom`);
3995 readlib(`factor/unifactor`);
3996 readlib(`factor/linfacts`)(expand(numer(f)),x)
3998 end:
4000 # irreducible decomposition of algebraic variety defined by ps
4001 `charsets/irrvardec` :=
4003 proc(ps,ord,medset)
4004 local phi,psi,i,j,mem,qq,qs;
4005 qq := nops(ps);
4006 mem := {};
4007 if 1 < printlevel and nargs < 3 then lprint(`Variable order chosen:`,ord)
4009 if nargs <> 4 then psi := [`charsets/irrcharser`(ps,ord,medset)]
4010 else
4011 psi := [`charsets/exirrcharser`([ps,1],ord,medset)];
4012 if psi <> [[]] then
4013 phi := psi;
4014 psi := op([]);
4015 for i in phi do
4016 if type(i[1],list) then psi := psi,i[1] else psi := psi,i fi
4018 psi := [psi]
4021 phi := [];
4022 for i to nops(psi) do
4023 if nops(psi[i]) <= qq then phi := [op(phi),psi[i]] fi
4025 phi := sort(phi,proc(a,b) if nops(a) < nops(b) then true else false fi end)
4027 psi := [];
4028 if phi <> [[]] then
4029 if nops(phi) = 1 and nargs <= 4 then RETURN([op(ps)]) fi;
4030 if 1 < printlevel then
4031 lprint(`ivd: ics finished at`,time(),nops(phi))
4033 for i to nops(phi) do
4034 if not member(i,mem) then
4035 qs := `charsets/primebasis`(phi[i],ord);
4036 if 1 < printlevel then
4037 lprint(`ivd: finite basis found:`,nops(phi),i); print(qs)
4039 for j from i+1 to nops(phi) do
4040 if not member(j,mem) and nops(phi[i]) <> nops(phi[j]) then
4041 if `charsets/remseta`(qs,phi[j],ord) = {} then
4042 mem := {j,op(mem)}
4046 psi := [op(psi),qs]
4049 op(sort([op(psi)],`charsets/lenord`))
4050 else []
4052 end:
4054 # prime basis of cs
4055 `charsets/primebasis` := proc(cs,ord)
4056 local is;
4057 if nops(cs) = nops(ord) then is := {}
4058 else is := `charsets/initialset`(cs,ord)
4060 `charsets/saturbasis`(cs,is,ord)
4061 end:
4063 # basis of saturation of ps wrt js
4064 `charsets/saturbasis` :=
4066 proc(ps,js,ord)
4067 local qs,gb,zz,j;
4068 if js <> {} then
4069 qs := [op(ps),'`charsets/@z`.j*js[j]-1' $ ('j' = 1 .. nops(js))];
4070 zz := ['`charsets/@z`.(nops(js)-j+1)' $ ('j' = 1 .. nops(js))];
4071 gb := grobner['gbasis'](
4072 qs,[op(zz),'ord[nops(ord)-j+1]' $ ('j' = 1 .. nops(ord))],'plex');
4073 qs := [];
4074 for j to nops(gb) do
4075 if {op(zz)} minus indets(gb[j]) = {op(zz)} then
4076 qs := [gb[j],op(qs)]
4079 else qs := ps
4082 end:
4084 # primary decomposition of polynomial ideal generated by ps
4085 # November 1995
4086 `charsets/pridealdec` :=
4088 proc(qs,ord,medset)
4089 local
4090 ps,phi,psi,fs,pi,ph,e,i,ss,S,j,gb,gb1,urd,vrd,f,gs,k,n,ind,indb,con,sep,
4091 wtd,tc,tco;
4092 ps := {op(`charsets/expand`(qs))} minus {0};
4093 ps := grobner['gbasis'](ps,`charsets/reverse`(ord),'plex');
4094 phi := [[ps,1,0,{1}]];
4095 psi := {};
4096 con := false;
4097 for n while phi <> [] do
4098 fs := phi[1];
4099 phi := [op(2 .. nops(phi),phi)];
4100 sep := fs[2];
4101 wtd := fs[3];
4102 tco := fs[4];
4103 tc := tco;
4104 fs := fs[1];
4105 ind := true;
4106 if 1 < n then
4107 fs := grobner['gbasis'](fs,`charsets/reverse`(ord),'plex');
4108 if member(1,fs) then ind := false
4109 elif `charsets/contain`(fs,ph,ord,'plex') then ind := false
4112 if ind then
4113 pi := [`charsets/irrvardec`(fs,ord,medset,0,0)];
4114 if pi <> [[]] then
4115 e := nops(pi);
4116 if 1 < printlevel then
4117 lprint(`pid: ivd finished at`,time(),e)
4119 for i to e do
4120 ss := {};
4121 S := {};
4122 if 1 < e then
4123 for j to e do
4124 if j <> i then
4125 ss := ss union {`charsets/takele`(
4126 {op(pi[j])} minus {op(pi[i])},pi[i],ord)}
4129 ss := `charsets/prod`(`charsets/factorps`(ss));
4130 gb := `charsets/saturbasis`(fs,{ss},ord)
4131 else
4132 ss := 1;
4133 gb :=
4134 grobner['gbasis'](fs,`charsets/reverse`(ord),'plex')
4136 urd := `charsets/maxindset`(pi[i],ord);
4137 if urd = [] then f := 1 else
4138 vrd := op({op(ord)} minus {op(urd)});
4139 gb1 := grobner['gbasis'](gb,[vrd,op(urd)],'plex');
4140 f := lcm('op(1,grobner['leadmon'](gb1[j],[vrd]))' $
4141 ('j' = 1 .. nops(gb1)))
4143 f := `charsets/prod`(`charsets/factorps`({f}));
4144 gs := `charsets/saturbasis`(gb,{f},ord);
4145 k := `charsets/exponent`(gb,f,gs,ord);
4146 if 1 < printlevel then
4147 lprint(`pid: primary component found:`,nops(psi)+1,
4148 nops(phi),e,i);
4149 print(gs)
4151 if psi = {} then psi := {[gs,pi[i]]}; ph := gs
4152 else
4153 psi union {[gs,pi[i]]};
4154 if % <> psi then
4155 psi := %;
4156 ph := `charsets/idealint`(ph,gs,ord);
4157 if `charsets/contain`(ps,ph,ord,'plex') then
4158 con := true; break
4162 tco := `charsets/idealint`(
4163 tco,`charsets/saturbasisR`(gs,{sep*ss},ord),ord);
4164 if 0 < `charsets/class`(f,ord) then
4165 if `charsets/class`(sep*ss,ord) = 0 then
4166 {op(gb)} union {f^k}
4167 else
4168 `charsets/saturbasis`(
4169 {op(gb)} union {f^k},{sep*ss},ord)
4171 indb := not `charsets/contain`(
4172 %,`charsets/idealintR`(ph,tc,ord),ord,'plex');
4173 if indb then
4174 indb :=
4175 `charsets/satisfy`({op(gb)} union {f^k},sep*ss,ord)
4177 if indb then
4178 phi := [
4179 op(phi),[{op(gb)} union {f^k},sep*ss,wtd+2,tc]
4184 S := S union {ss^`charsets/exponent`(fs,ss,gb,ord)}
4186 if con then break fi;
4187 S := {op(fs)} union S;
4188 if not member(1,S) then
4189 if `charsets/class`(sep,ord) = 0 then S
4190 else `charsets/saturbasis`(S,{sep},ord)
4192 not `charsets/contain`(
4193 %,`charsets/idealintR`(ph,tco,ord),ord,'plex');
4194 if % then phi := [op(phi),[S,sep,wtd+2,tco]] fi
4197 phi := sort(phi,`charsets/wtdorder`)
4200 if psi = {} or psi = {[1]} then []
4201 else
4203 sort([`charsets/remred`([op(psi minus {[1]})],ord)],`charsets/lenord`)
4206 end:
4208 # weight ordering
4209 `charsets/wtdorder` := proc(a,b) if a[3] < b[3] then true else false fi end:
4211 # radical ideal membership test - is zero(ps/g) empty?
4212 `charsets/satisfy` :=
4214 proc(ps,g,ord)
4215 if `charsets/class`(g,ord) = 0 then true
4216 elif member(g,ps) or member(g^2,ps) or member(g^3,ps) then false
4217 elif `charsets/contain`(ps,{g},ord,'plex') then false
4218 elif `charsets/eicsTest`([ps,g],ord,`charsets/charsetn`) = [] then false
4219 else true
4221 end:
4224 # remove redundant poly sets from phi
4225 `charsets/remred` :=
4227 proc(phi,ord)
4228 op(`charsets/remrsub`(`charsets/reverse`(`charsets/remrsub`(phi,ord)),ord))
4229 end:
4231 # main subroutine for remred
4232 `charsets/remrsub` :=
4234 proc(phi,ord)
4235 local ph,mem,i,j;
4236 ph := [];
4237 mem := {};
4238 for i to nops(phi) do
4239 if not member(i,mem) then
4240 for j from i+1 to nops(phi) do
4241 if not member(j,mem) then
4242 if `charsets/contain`(phi[j][1],phi[i][1],ord,'plex') then
4243 mem := {op(mem),j}
4247 ph := [op(ph),phi[i]]
4251 end:
4253 # test: does ideal(ps) contain ideal(qs)?
4254 `charsets/contain` :=
4256 proc(ps,qs,ord,pt)
4257 local X,q;
4258 if 1 < printlevel then lprint(`containment test starts at`,time()) fi;
4259 X := `charsets/reverse`(ord);
4260 for q in qs do
4261 if grobner['normalf'](q,ps,X,pt) <> 0 then RETURN(false) fi
4263 true
4264 end:
4266 # reverse a list
4267 `charsets/reverse` :=
4269 proc(ord) local j; ['ord[nops(ord)-j+1]' $ ('j' = 1 .. nops(ord))] end:
4271 # take from qs an element which is not in ideal(gb)
4272 `charsets/takele` :=
4274 proc(gs,gb,ord)
4275 local X,ps,i;
4276 X := `charsets/reverse`(ord);
4277 ps := `charsets/reverse`(sort([op(gs)],`charsets/nopsord`));
4278 for i to nops(ps) do
4279 if grobner['normalf'](ps[i],gb,X,'plex') <> 0 then RETURN(ps[i]) fi
4281 ERROR(`Check Here!`)
4282 end:
4284 # maximal independent set modulo gb
4285 `charsets/maxindset` :=
4287 proc(gb,ord)
4288 local j,x,g,ind,u,urd;
4289 urd := {};
4290 for x in ord do
4291 ind := true;
4292 u := urd union {x};
4293 for g in gb do
4294 if indets(op(2,grobner['leadmon'](g,
4295 `charsets/reverse`(ord),'plex'))) minus u = {}
4296 then ind := false; break fi
4298 if ind then urd := u fi
4300 [op(urd)]
4301 end:
4303 # compute the exponent
4304 `charsets/exponent` :=
4306 proc(ps,f,qs,ord)
4307 local k;
4308 for k do
4309 if 50 < k then lprint(`Check PID exponent!`,k) fi;
4310 if {op(`charsets/idealquo`(ps,f^k,ord))} = {op(qs)} then break fi
4312 if 2 < printlevel then lprint(`pid: exponent found:`,k) fi;
4314 end:
4316 # ideal quotient
4317 `charsets/idealquo` :=
4319 proc(ps,f,ord)
4320 local qs,j;
4321 if type(f,{set,list}) then
4322 qs := `charsets/idealquo`(ps,f[1],ord);
4323 if 1 < nops(f) then
4324 [op(2 .. nops(f),f)];
4325 qs := `charsets/idealint`(qs,`charsets/idealquo`(ps,%,ord),ord)
4328 else
4329 qs := `charsets/idealint`(ps,f,ord);
4330 grobner['gbasis']({'simplify(qs[j]/f)' $ ('j' = 1 .. nops(qs))},
4331 `charsets/reverse`(ord),'plex')
4333 end:
4335 # ideal intersection
4336 `charsets/idealint` :=
4338 proc(ps,f,ord)
4339 local qs,gb,zz,j;
4340 if 1 < printlevel then lprint(`ideal intersection starts at`,time()) fi;
4341 if type(f,{set,list}) then
4342 qs := [
4343 'zz*ps[j]' $ ('j' = 1 .. nops(ps)),'(1-zz)*f[j]' $ ('j' = 1 .. nops(f))
4345 else qs := ['zz*ps[j]' $ ('j' = 1 .. nops(ps)),(1-zz)*f]
4347 gb := grobner['gbasis'](
4348 qs,[zz,'ord[nops(ord)-j+1]' $ ('j' = 1 .. nops(ord))],'plex');
4349 qs := [];
4350 for j to nops(gb) do
4351 if {zz} minus indets(gb[j]) = {zz} then qs := [gb[j],op(qs)] fi
4353 if 1 < printlevel then lprint(`ideal intersection finished at`,time())
4356 end:
4358 # ideal intersection - with remember
4359 `charsets/idealintR` :=
4361 proc(ps,f,ord)
4362 local qs,gb,zz,j;
4363 options remember;
4364 if 1 < printlevel then lprint(`ideal intersection starts at`,time()) fi;
4365 if type(f,{set,list}) then
4366 qs := [
4367 'zz*ps[j]' $ ('j' = 1 .. nops(ps)),'(1-zz)*f[j]' $ ('j' = 1 .. nops(f))
4369 else qs := ['zz*ps[j]' $ ('j' = 1 .. nops(ps)),(1-zz)*f]
4371 gb := grobner['gbasis'](
4372 qs,[zz,'ord[nops(ord)-j+1]' $ ('j' = 1 .. nops(ord))],'plex');
4373 qs := [];
4374 for j to nops(gb) do
4375 if {zz} minus indets(gb[j]) = {zz} then qs := [gb[j],op(qs)] fi
4377 if 1 < printlevel then lprint(`ideal intersection finished at`,time())
4380 end:
4382 # basis of the saturation of ideal(ps) wrt js
4383 `charsets/saturbasisR` :=
4385 proc(ps,js,ord)
4386 local qs,gb,zz,j;
4387 options remember;
4388 if js <> {} then
4389 qs := [op(ps),'`charsets/@z`.j*js[j]-1' $ ('j' = 1 .. nops(js))];
4390 zz := ['`charsets/@z`.(nops(js)-j+1)' $ ('j' = 1 .. nops(js))];
4391 gb := grobner['gbasis'](
4392 qs,[op(zz),'ord[nops(ord)-j+1]' $ ('j' = 1 .. nops(ord))],'plex');
4393 qs := [];
4394 for j to nops(gb) do
4395 if {op(zz)} minus indets(gb[j]) = {op(zz)} then
4396 qs := [gb[j],op(qs)]
4399 else qs := ps
4402 end:
4404 # the extend:ed irreducible char series of polyset ps
4405 # test: is zero(ps) empty?
4406 `charsets/eicsTest` :=
4408 proc(ps,ord,medset)
4409 local qs,cs,is,iss,n,i,j,qhi,qsi,r,rr,factorset,mind,fset,ind,ts,den;
4410 if type(ps[1],{set,list}) then qhi := {ps} else qhi := {[ps,1]} fi;
4411 if medset = `charsets/basset` then mind := true else mind := false fi;
4412 qsi := {};
4413 if 1 < printlevel then lprint(`radical membership test starts at`,time())
4415 for n from 0 while qhi <> {} and qsi = {} do
4416 qs := qhi[1][1];
4417 if not mind then
4418 if n < 20 then
4419 `charsets/f`.(substring(medset,10 .. length(medset)))(
4420 qs,ord,[{},indets(qs)],'fset');
4421 cs := `charsets/removecont`(%,ord,'factorset');
4422 factorset := factorset union fset[1]
4423 else
4424 `charsets/`.(substring(medset,10 .. length(medset)))(qs,ord);
4425 cs := `charsets/removecont`(%,ord,'factorset')
4427 else
4428 if n < 20 then
4429 cs := `charsets/fcharseta`([op(qs)],ord,medset);
4430 factorset := op(2,cs[2]);
4431 cs := `charsets/removecont`(cs[1],ord,'ts');
4432 factorset := factorset union ts
4433 else
4434 `charsets/charseta`([op(qs)],ord,medset);
4435 cs := `charsets/removecont`(%,ord,'factorset')
4437 if 1 < printlevel then
4438 lprint(`characteristic set produced`); print(cs)
4441 if 0 < `charsets/class`(cs[1],ord) then
4442 ts := `charsets/irras`(cs,ord,ind,'den');
4443 if ts[2] = 0 then
4444 if not mind then
4445 if not `charsets/subset`(cs,qs) then
4446 cs := `charsets/charseta`({op(cs),op(qs)},ord,medset)
4448 if 1 < printlevel then
4449 lprint(`characteristic set produced`); print(cs)
4452 if 0 < `charsets/class`(cs[1],ord) then
4453 ts := `charsets/irras`(cs,ord,ind,'den');
4454 if ts[2] = 0 then
4455 is := `charsets/initialset`(cs,ord) union
4456 `charsets/factorps`(factorset);
4457 if nops(cs) = nops(ord) then
4458 rr := `charsets/nopower`(qhi[1][2])
4459 else
4460 rr := `charsets/nopower`(
4461 `charsets/prod`({qhi[1][2],op(is)}))
4463 `charsets/premas`(rr,cs,ord);
4464 r := `charsets/simp`(%,cs,ord);
4465 if r <> 0 then
4466 if r = 1 then qsi := {cs,op(qsi)}
4467 else qsi := {[cs,`charsets/simpb`(r,rr)],op(qsi)}
4471 else is := `charsets/factorps`(factorset); ts := [1,0]
4474 if ts[2] <> 0 then
4475 if 1 < ts[2] then
4476 is := `charsets/initialset`({op(1 .. ts[2]-1,cs)},ord)
4477 union `charsets/factorps`(factorset)
4478 else is := `charsets/factorps`(factorset)
4481 else is := `charsets/factorps`(factorset); ts := [1,0]
4483 iss := {};
4484 if nops(ord) <= nops(ps)+1 then
4485 for i in is do iss := {op(iss),[{i,op(qs)},qhi[1][2]]} od
4486 else
4487 for i to nops(is) do
4488 if i = 1 then 1 else product('is[j]','j' = 1 .. i-1) fi;
4489 iss := {op(iss),[{op(qs),is[i]},%*qhi[1][2]]}
4492 if ts[2] <> 0 and ts[1] <> {} then
4493 if not mind then
4494 if not `charsets/subset`(cs,qs) then
4495 `charsets/charseta`({op(cs),op(qs)},ord,medset)
4496 else cs
4498 if % <> cs then
4499 if ts[2] = 1 then cs := qs
4500 else cs := {op(qs),op(1 .. ts[2]-1,cs)}
4504 for i in ts[1] do
4505 iss :=
4506 {op(iss),[{op(cs),i},`charsets/prod`({den,qhi[1][2],op(is)})]}
4508 if 0 < `charsets/class`(den,ord) and
4509 ts[2] < `charsets/class`(ts[1][1],ord) then
4510 iss := {op(iss),[{op(cs),den},qhi[1][2]]}
4513 if 1 < nops(qhi) then qhi := {op(iss),op(2 .. nops(qhi),qhi)}
4514 else qhi := iss
4517 if qsi <> {} then op(qsi) else [] fi
4518 end:
4520 # ordering wrt length
4521 `charsets/lenord` :=
4523 proc(a,b) if length(b) < length(a) then true else false fi end:
4525 #save
4526 #with,
4527 #`charsets/getvars`, `charsets/csolve`, `charsets/pfactor`, `charsets/lvar`,
4528 #`charsets/mcharset`, `charsets/iniset`, `charsets/irrvardec`, `charsets/minus
4530 #`charsets/trisetc`, `charsets/simp`, `charsets/reordera`, `charsets/reorderb`
4532 #`charsets/degord`, `charsets/fsubtriset`, `charsets/newfactoras`,
4533 #`charsets/irras`, `charsets/fcharser`, `charsets/irrcharser`,
4534 #`charsets/fcharseta`, `charsets/factorps`, `charsets/initialset`,
4535 #`charsets/adjoina`, `charsets/verify`, `charsets/trisersub`,
4536 #`charsets/remseta`, `charsets/mcs`, `charsets/remsetb`,
4537 #`charsets/fcharsetsub`, `charsets/degpsmin`,
4538 #`charsets/nopower`, `charsets/fcnormal`, `charsets/fcharsetn`,
4539 #`charsets/subtriset`, `charsets/qirrcharser`, `charsets/subrank`,
4540 #`charsets/charser`, `charsets/premasb`, `charsets/charset`,
4541 #`charsets/subtrisetc`, `charsets/deg1`,
4542 #`charsets/exirrcharser`, `charsets/eics`, `charsets/gcdex`, `charsets/ics`,
4543 #`charsets/charseta`, `charsets/remset`, `charsets/mecs`, `charsets/qbasset`,
4544 #`charsets/qirras`, `charsets/index`, `charsets/solveas`, `charsets/adjoin`,
4545 #`charsets/cfactor`, `charsets/removecont`, `charsets/charsetn`,
4546 #`charsets/irrassub`, `help/text/charsets`, `charsets/nopsord`,
4547 #`charsets/initialset1`, `charsets/fwcharsetn`, `charsets/reorder`,
4548 #`charsets/solvel`, `charsets/ecs`, `charsets/rank`, `charsets/basset`,
4549 #`charsets/removefactor`, `charsets/premas`, `charsets/solveasr`,
4550 #`charsets/fsubtrisetsub`, `charsets/deg0`, `charsets/wcharsetn`,
4551 #`charsets/initial`, `charsets/contractsub`, `charsets/union`, `charsets/summ`
4553 #`charsets/triser`, `charsets/select`, `charsets/triset`, `charsets/solveps`,
4554 #`charsets/getfactor`, `charsets/mrank`, `charsets/compress`, `charsets/qics`,
4555 #`charsets/degpsmax`, `charsets/@con`, _seed, `charsets/sfactor`,
4556 #`charsets/fqcharsetn`, `charsets/ivd`, `charsets/charseries`,
4557 #`charsets/newfactorassub`, `charsets/wbasset`, `charsets/ftriset`,
4558 #`charsets/coeff`, `charsets/measure`, `charsets/prem`, `charsets/simpa`,
4559 #`charsets/simpb`, `charsets/fexcharser`, `charsets/die`,
4560 #`charsets/class`, `charsets/contract`, `charsets`, `charsets/factoras`,
4561 #`charsets/ftrisetc`, `charsets/qcharsetn`, `charsets/movefactor`,
4562 #`charsets/trank`, `charsets/prod`, `charsets/linas`,`charsets/primebasis`,
4563 #`charsets/excharser`, `charsets/getfact`, `charsets/sort`,
4564 #`charsets.m`;
4565 #quit
4567 #read help;
4568 #save `charsets.m`;
4569 #quit
4571 # vim: syntax=maple