1 #
-*- mode
: maplev
; -*-
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 #####################################################################
10 # CHARACTERISTIC SETS PACKAGE #
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 #
18 # Date
: February
1996 #
20 #
Copyright (C) 1990-1996 by Dongming Wang #
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. #
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
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;
107 if `charsets/class`(as
[i
],ord
) <= ind
then
109 `second argument must be a non-contradictory (weak-, quasi-) ascend\
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
)
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
)
129 # the char set of poly set ps
: user function
130 `charsets/charset` :=
132 proc(ps
,lst
,medset
,y
)
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
)
153 ERROR(`medial set must be one of ``basset``,``wbasset``, ``qbasset``,`.
154 ```charsetn``,``wcharsetn``,``qcharsetn``,``triset`` and ``trisetc```
159 # modified
from expand for lists
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
))}
170 # the modified char set of poly set ps
: user function
171 `charsets/mcharset` :=
173 proc(ps
,lst
,medset
,y
)
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
)
194 ERROR(`medial set must be one of ``basset``,``wbasset``, ``qbasset``,`.
195 ```charsetn``,``wcharsetn``,``qcharsetn``,``triset`` and ``trisetc```
200 # the set of all nonconstant
factors of initials of polys
in as
: user function
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
)
216 if `charsets/class`(as
[i
],ord
) <= ind
then
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
)
226 # the char
series of poly set ps
: user function
227 `charsets/charser` :=
229 proc(ps
,lst
,medset
,y
)
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
)
249 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
250 ```charsetn``,``wcharsetn`` and ``trisetc```)
254 # the char
series of poly set ps
-- allowing
to remove factors
258 proc(ps
,lst
,medset
,y
)
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
)
278 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
279 ```charsetn``,``wcharsetn`` and ``trisetc```)
283 # the extended char
series of poly set ps
287 proc(ps
,lst
,medset
,y
)
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
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
)
318 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
319 ```charsetn``,``wcharsetn`` and ``trisetc```)
323 # the extended char
series of poly set ps
-- allowing
to remove factors
327 proc(ps
,lst
,medset
,y
)
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
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
)
358 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
359 ```charsetn``,``wcharsetn`` and ``trisetc```)
363 # the irreducible char
series of poly set ps
: user function
366 proc(ps
,lst
,medset
,y
)
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
)
387 `medial set must be one of ``basset``,``charsetn```.
` and ``trisetc```
392 # the extended irreducible char
series of poly set ps
: user function
395 proc(ps
,lst
,medset
,y
)
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
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
)
427 `medial set must be one of ``basset``,`.
```charsetn`` and ``trisetc```
432 # the quasi
-irreducible char
series of poly set ps
: user function
435 proc(ps
,lst
,medset
,y
)
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
)
455 ERROR(`medial set must be one of ``basset``,``wbasset``,`.
456 ```charsetn``,``wcharsetn`` and ``trisetc```)
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` :=
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
)
482 inda
:= `charsets/class`(as
[i
],ord
);
484 ERROR(`second argument must be a non-contradictory ascending set`)
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
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
)
503 # prepare a list of
triangular forms
from poly set ps
: user function
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`)
512 if nops(lst
) < 1 then ERROR(`no indeterminates specified`) fi
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};
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
)
532 #
solve a set of poly eqs ps
=0: user function
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`)
541 if nops(lst
) < 1 then ERROR(`no indeterminates specified`) fi
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};
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
))})
564 # irreducible decomposition of
algebraic variety defined
by ps
:
568 proc(ps
,lst
,medset
,y
)
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
)
589 `medial set must be one of ``basset``,`.
```charsetn`` and ``trisetc```
594 # primary decomposition of polynomial ideal generated
by ps
598 proc(ps
,lst
,medset
,y
)
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
)
619 `medial set must be one of ``basset``,`.
```charsetn`` and ``trisetc```
624 ##### Part I. Routines
for Computing Characteristic Sets #####
626 # the class of poly f wrt variable ordering ord
627 `charsets/class` := proc(f
,ord
)
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
636 # the leading variable of poly f wrt variable ordering ord
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`)
650 # the
index set of a
poly (or a poly set f
) wrt ord
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
))}
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
)
666 `[`.ng.
` `.i.
` `.g.
`]`
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` :=
678 options remember
,system;
680 if `charsets/class`(f
,ord
) = 0 then 1
681 else lcoeff(f
,`charsets/lvar`(f
,ord
)); numer(%/lcoeff(%))
685 # modified rank of two polys
: comparing further the rank
686 # of initials when f
and g have same rank
691 options remember
,system;
692 cf
:= `charsets/class`(f
,ord
);
693 cg
:= `charsets/class`(g
,ord
);
695 elif cf
< cg
then true
697 cf
:= `charsets/degreel`(f
,ord
);
698 cg
:= `charsets/degreel`(g
,ord
);
702 `charsets/initial`(f
,ord
),`charsets/initial`(g
,ord
),ord
)
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
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
)));
723 if nops(expand(f
)) < nops(expand(g
)) then true else false fi
730 # subroutine
for rank
731 `charsets/subrank` :=
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
741 cf
:= `charsets/degreel`(f
,ord
);
742 cg
:= `charsets/degreel`(g
,ord
);
746 `charsets/initial`(f
,ord
),`charsets/initial`(g
,ord
),ord
,'ind')
753 # the rank of two polys
with same classes
:
754 # used
for computing
triangular form
759 options remember
,system;
760 cf
:= `charsets/degreel`(f
,ord
);
761 cg
:= `charsets/degreel`(g
,ord
);
765 `charsets/initial`(f
,ord
),`charsets/initial`(g
,ord
),ord
)
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
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
)
784 if dv
<= dr
then l
:= coeff(v
,x
,dv
); v
:= expand(v
-l
*x
^dv
)
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;
801 # pseudo remainder of poly f wrt ascending set as
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
813 # set of non
-zero remainders of polys
in ps wrt ascending set as
814 `charsets/remseta` :=
818 {'`charsets/premas`(ps[i],as,ord)' $
('i' = 1 ..
nops(ps
))} minus {0}
821 # pseudo remainder of poly f wrt ascending set as
-- version b
822 `charsets/premasb` :=
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
838 # set of non
-zero remainders of polys
in ps wrt ascending set as
-- version b
839 `charsets/remsetb` :=
843 {'`charsets/premasb`(ps[i],as,ord)' $
('i' = 1 ..
nops(ps
))} minus {0}
846 # reorder the list ord of variables wrt poly set ps
847 `charsets/reorder` :=
850 op(`charsets/reordera`(ord
,ps
));
851 [op(`charsets/reorderb`([op({op(ord
)} minus {%})],p
,ps
)),%]
854 # subroutine
for reorder
: first criterion
855 `charsets/reordera` :=
859 if nops(ps
) = 0 then ord
864 pp
:= `charsets/deg0`(ps
,i
);
867 [op(`charsets/reordera`([op(orb
minus {i
})],qs
minus pp
)),i
]
875 # subroutine
for reorder
-- modified
from sort: second criterion
876 `charsets/reorderb` :=
879 local n
,tn
,gap
,i
,j
,temp
,v
;
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;
886 for i
from gap
to n
-1 do
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
]
895 ['eval(v[i],1)' $
('i' = 0 .. n
-1)]
898 # determine the
order between x
and y wrt ps
902 if op(2,`charsets/degpsmax`(ps
,y
)) < op(2,`charsets/degpsmax`(ps
,x
)) then
904 elif op(2,`charsets/degpsmax`(ps
,x
)) < op(2,`charsets/degpsmax`(ps
,y
)) then
906 elif op(1,`charsets/degpsmax`(ps
,y
)) < op(1,`charsets/degpsmax`(ps
,x
)) then
908 elif op(1,`charsets/degpsmax`(ps
,x
)) < op(1,`charsets/degpsmax`(ps
,y
)) then
910 elif op(2,`charsets/degpsmin`(ps
,x
)) < op(2,`charsets/degpsmin`(ps
,y
)) then
912 elif op(2,`charsets/degpsmin`(ps
,y
)) < op(2,`charsets/degpsmin`(ps
,x
)) then
914 elif op(1,`charsets/degpsmin`(ps
,y
)) < op(1,`charsets/degpsmin`(ps
,x
)) then
916 elif op(1,`charsets/degpsmin`(ps
,x
)) < op(1,`charsets/degpsmin`(ps
,y
)) then
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
925 # the maximal
degree of polys
in qs wrt x
926 #
and the number of polys having this
degree
927 `charsets/degpsmax` :=
931 options remember
,system;
933 m
:= max('degree(ps[i],x)' $
('i' = 1 ..
nops(ps
)));
935 for i
to nops(ps
) do if degree(ps
[i
],x
) = m
then mm
:= mm
+m
fi od;
939 # the minimal non
-zero degree of polys
in qs wrt x
940 #
and the number of polys having this
degree
941 `charsets/degpsmin` :=
945 options remember
,system;
947 {'degree(ps[i],x)' $
('i' = 1 ..
nops(ps
))} minus {0};
948 if % = {} then m
:= 0 else m
:= min(op(%)) fi;
950 for i
to nops(ps
) do if degree(ps
[i
],x
) = m
then mm
:= mm
+m
fi od;
954 # determine
if ps
has one
and only one poly involving x
955 `charsets/deg0` := proc(ps
,x
)
958 for i
in ps
while nops(ms
) < 2 do
959 if member(x
,indets(i
)) then ms
:= {i
,op(ms
)} fi
964 # the minimal total
degree of lcoeffs of polys
in PS wrt x
965 #
and the minimal number of terms of those lcoeffs
970 options remember
,system;
973 k
:= op(2,`charsets/degpsmin`(ps
,x
));
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
)))]
981 # search an element
with lowest rank
in ps
982 #
and assign the rest of polys
to qs
987 if nops(ps
) = 1 then qs
:= []; ps
[1]
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
)]
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
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` :=
1023 if nops(ps
) < 2 then ps
1025 b
:= `charsets/sort`(ps
,`charsets/rank`,ord
,'qs1');
1027 if 0 < `charsets/class`(b
,ord
) then
1029 if `charsets/brank`(i
,b
,ord
) then qs
:= [i
,op(qs
)] fi
1033 [b
,op(`charsets/basset`(qs
,ord
))]
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
1055 if `charsets/degree`(a
,`charsets/lvar`(b
,ord
)) < `charsets/degreel`(b
,ord
)
1062 `charsets/wbrank` :=
1065 if `charsets/class`(b
,ord
) < `charsets/class`(a
,ord
) and
1066 `charsets/brank`(`charsets/initial`(a
,ord
),b
,ord
) then
1072 `charsets/qbrank` :=
1075 if `charsets/class`(b
,ord
) < `charsets/class`(a
,ord
) then true
1080 # the char set of poly set ps
1081 `charsets/charseta` :=
1085 global `charsets/with`;
1086 if nops(ps
) < 2 then [op(ps
)]
1088 if medset
= `charsets/qcharsetn` then
1089 `charsets/with` := {};
1090 med
:= subs(`charsets/remseta` = `charsets/remsetaA`,
1091 `charsets/qcharsetn` = med
,op(`charsets/qcharsetn`));
1093 else cs
:= medset(ps
,ord
)
1095 if 0 < `charsets/class`(cs
[1],ord
) then
1097 medset
,{`charsets/wbasset`,`charsets/qbasset`,`charsets/basset`}
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`)
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
)
1115 ['numer(cs[l]/lcoeff(expand(cs[l])))' $
('l' = 1 ..
nops(cs
))]
1116 else `charsets/charseta`(`charsets/union`(rs
,cs
,ps
),ord
,medset
)
1121 # the modified char set of poly set ps
1122 `charsets/fcharseta` :=
1126 csf
:= `charsets/fcharsetsub`(
1127 `charsets/nopower`(ps
),ord
,medset
,[{},indets(ps
)],'fset');
1128 csf
,`factors removed` = fset
[1]
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
)]
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]
1157 if 1 < printlevel
then
1158 lprint(`Strategy for 0 remainder succeed`)
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])
1172 ['numer(cs[l]/lcoeff(expand(cs[l])))' $
('l' = 1 ..
nops(cs
))]
1174 `charsets/fcharsetsub`(
1175 `charsets/union`(rs
,cs
,ps
),ord
,medset
,fset2
,'fset')
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])
1187 ['numer(cs[l]/lcoeff(expand(cs[l])))' $
('l' = 1 ..
nops(cs
))]
1189 `charsets/fcharsetsub`(
1190 `charsets/union`(rs
,cs
,ps
),ord
,medset
,fset3
,'fset')
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.
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
)
1210 if dv
<= dr
then l
:= coeff(v
,x
,dv
); v
:= expand(v
-l
*x
^dv
)
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
}
1230 `charsets/remsetaA` :=
1234 {'`charsets/premasA`(ps[i],as,ord)' $
('i' = 1 ..
nops(ps
))} minus {0}
1237 `charsets/premasA` :=
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
1248 `charsets/checkwith` :=
1252 rs
:= ps1
minus ps2
;
1253 if rs
= {} then true
1254 elif ps2
= {} then false
1257 {'`charsets/pfactor`(convert(rs[i],sqrfree))' $
('i' = 1 ..
nops(rs
))}
1259 for i
to nops(rs
) do
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
1270 # replace the power of
factors of polys
in as
by 1 if any
1271 `charsets/nopower` :=
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
))
1281 else ['`charsets/nopower`(as[i])' $
('i' = 1 ..
nops(as
))]
1285 # the nearly char set
-- a medial set
1286 `charsets/charsetn` :=
1290 if nops(ps
) < 2 then ps
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
)
1297 if rs
= {} then cs
else `charsets/charsetn`([op(rs
),op(cs
)],ord
) fi
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
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')
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` :=
1354 global `charsets/@qs`;
1355 if nops(ps
) < 2 then ps
1357 for i
from 0 to nops(ord
) do `charsets/@qs`[i
] := [] od;
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
)
1367 if `charsets/@qs`[0] <> [] then [1]
1368 else ['op(`charsets/@qs`[i])' $
('i' = 1 ..
nops(ord
))]
1373 # subroutine
for triset
1374 `charsets/subtriset` :=
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
];
1383 p
:= `charsets/prem`(j
,ss1
,ord
[i
]);
1385 `charsets/@qs`[`charsets/class`(p
,ord
)] := [
1386 op(`charsets/@qs`[`charsets/class`(p
,ord
)]),numer(p
/lcoeff(p
))
1390 `charsets/subtriset`(i
,ord
)
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` :=
1400 if not type(f
,{set
,list
}) and not type(g
,integer
)
1401 and divide(f
,g
,'fg') then
1403 if 0 < `charsets/class`(g
,ord
) then ja
:= true
1407 `charsets/movefactor`(fg
,g
,ord
)
1408 else if 3 < nargs
then ja
:= false fi; f
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;
1426 for k
in fs
[1] do rr
:= `charsets/movefactor`(rr
,k
,ord
,'ja') od;
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
];
1436 rs
:= `charsets/nopower`(rs
);
1438 if not type(ps
,{set
,list
}) then rs
[1] else rs
fi
1441 #
remove contents of all polys
in ps wrt leading variables
1442 # the set of removed
factors is assigned to ms
1443 `charsets/removecont` :=
1446 local qs
,fs
,i
,cc
,pp
;
1447 if `charsets/class`(ps
[1],ord
) = 0 then if 2 < nargs
then ms
:= {} fi; ps
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;
1456 if 2 < nargs
then ms
:= fs
fi;
1461 # the modified
triangular set of poly set ps
-- a modified quasi
-medial set
1462 `charsets/ftriset` :=
1464 proc(ps
,ord
,fset1
,fset
)
1466 global `charsets/@fact`,`charsets/@qs`;
1467 `charsets/@fact` := 1;
1468 if nops(ps
) < 2 then fset
:= fset1
; ps
1471 for i
from 0 to nops(ord
) do `charsets/@qs`[i
] := [] od;
1473 `charsets/@qs`[`charsets/class`(i
,ord
)] :=
1474 [op(`charsets/@qs`[`charsets/class`(i
,ord
)]),i
]
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]
1486 ['op(`charsets/@qs`[i])' $
('i' = 1 ..
nops(ord
))]
1491 # subroutine
for ftriset
1492 `charsets/fsubtriset` :=
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
];
1501 qq
:= {'numer(ps[l]/lcoeff(expand(ps[l])))' $
('l' = 1 ..
nops(ps
))};
1503 pp
:= `charsets/prem`(j
,ss1
,ord
[i
]);
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');
1510 fset2
:= {op(fset2
),numer(
1511 `charsets/@fact`/lcoeff(expand(`charsets/@fact`)))}
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
)
1533 # subroutine
for fsubtriset
1534 `charsets/fsubtrisetsub` :=
1538 for i
to nops(aa
) do if subs(aa
[i
] = 0,bb
) = 0 then RETURN(false) fi od;
1542 # reduce a
triangular set into an ascending set
1543 `charsets/trisetc` :=
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
1553 # reduce a
triangular set into an ascending set
with factors moved
1554 `charsets/ftrisetc` :=
1556 proc(ps
,ord
,fset1
,fset
)
1558 global `charsets/@cs`;
1559 `charsets/@cs` := `charsets/ftriset`(ps
,ord
,fset1
,'fs');
1562 {'op(`charsets/pfactor`(fs[1][i]))' $
('i' = 1 ..
nops(fs
[1]))}
1565 cs
:= `charsets/subtrisetc`(ord
,%,'ind');
1566 if ind
= 0 then `charsets/fcharsetn`([op(ps
),op(cs
)],ord
,fset1
,'fset')
1571 # subroutine
for ftrisetc
1572 `charsets/subtrisetc` :=
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
)
1588 cs
:= [op(cs
),`charsets/nopower`(numer(r
/lcoeff(r
)))]
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
1604 # the set of nonconstant initials of as
1605 #
with certain repeated
factors cancelled
1606 `charsets/initialset1` :=
1612 `charsets/initial`(i
,ord
);
1613 if 0 < `charsets/class`(%,ord
) then
1614 is := {`charsets/pfactor`(%),op(is)}
1617 is := `charsets/compress`(is,ord
);
1620 if 0 < `charsets/class`(i
,ord
) then iss
:= {i
,op(iss
)} fi
1625 # compress some repeated
factors
1626 `charsets/compress` :=
1629 local is,is1
,i
,j
,ss
;
1631 if 1 < nops(is) then
1633 for i
to nops(is)-1 do
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
)];
1644 if 1 < nops(is1
) then
1645 for i
to nops(is1
)-1 do
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
)]}
1661 # the sequence of distinct
factors of f
1662 `charsets/pfactor` :=
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
)))
1674 # the sequence of
factors of f
1675 `charsets/sfactor` :=
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
))
1688 # the set of all nonconstant
factors of initials of polys
in as
1689 `charsets/initialset` :=
1695 `charsets/initial`(i
,ord
);
1696 if 0 < `charsets/class`(%,ord
) then is := {%,op(is)} fi
1698 is := `charsets/factorps`(is);
1701 if 0 < `charsets/class`(i
,ord
) then iss
:= {i
,op(iss
)} fi
1706 # all irreducible nonconstant
factors of a set of polynomials
1707 `charsets/factorps` :=
1716 if not type(op(j
,q
),integer
) then
1717 if type(op(j
,q
),`^`) then
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
1731 ##### Part II. Routines
for Various Decompositions
and Others #####
1733 # the char
series of poly set ps
1734 `charsets/charseries` :=
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;
1743 for n
from 0 while qhi
<> {} do
1744 qhi
:= sort([op(qhi
)],`charsets/nopsord`);
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
1753 `Characteristic set produced`,csno
,nops(qhi
),nops(qsi
),nops(qs
)
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
)
1763 if 1 < nops(qhi
) then qhi
:= {op(iss
),op(2 ..
nops(qhi
),qhi
)}
1768 else op(sort(`charsets/contract`(qsi
,ord
,0),`charsets/lenord`))
1772 # the char
series of poly set ps
-- allowing
to remove factors
1773 `charsets/fcharser` :=
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;
1782 for n
from 0 while qhi
<> {} do
1783 qhi
:= sort([op(qhi
)],`charsets/nopsord`);
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]);
1793 `charsets/charseta`([op(qs
)],ord
,medset
);
1794 cs
:= `charsets/removecont`(%,ord
,'factorset')
1796 if 1 < printlevel
then
1799 `Characteristic set produced`,csno
,nops(qhi
),nops(qsi
),nops(qs
)
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
)}
1815 else op(sort(`charsets/contract`(qsi
,ord
,0),`charsets/lenord`))
1819 # the extended char
series of poly set ps
1820 `charsets/excharser` :=
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;
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
);
1838 if r
= 1 then qsi
:= {cs
,op(qsi
)}
1839 else qsi
:= {op(qsi
),[cs
,`charsets/simpb`(r
,rr
)]}
1845 if nops(ord
) <= nops(ps
)+1 then
1846 for i
in is do iss
:= {op(iss
),[{op(qs
),i
},qhi
[1][2]]} od
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
)}
1857 if qsi
= {} then [] else op(sort([op(qsi
)],`charsets/lenord`)) fi
1860 #
simplify r
to rr so that
Zero(cs
/r
) = Zero(cs
/rr
) holds still
1864 local rr
,i
,fs
,j
,ind
;
1867 fs
:= {`charsets/pfactor`(r
)};
1870 if 0 < `charsets/class`(i
,ord
) then
1875 if `charsets/class`(`charsets/movefactor`(j
,i
,ord
),ord
)
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
1889 # check whether
Zero(cs
/fs
) is empty
1894 if nops(cs
) = 1 then 1
1896 ds
:= [op(1 ..
nops(cs
)-1,cs
)];
1899 if subs(i
= 0,j
) = 0 then
1900 if `charsets/class`(`charsets/movefactor`(j
,i
,ord
),ord
) = 0
1911 # the simpler one of a
and b
1915 if `charsets/measure`(a
) < `charsets/measure`(b
) then a
else b
fi
1918 # the measure of complexity of a according
to number of terms
1919 `charsets/measure` :=
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
))
1930 # the extended char
series of poly set ps
-- allowing
to remove factors
1931 `charsets/fexcharser` :=
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;
1937 for n
from 0 while qhi
<> {} do
1940 cs
:= `charsets/fcharseta`([op(qs
)],ord
,medset
);
1941 factorset
:= op(2,cs
[2]);
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
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
);
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
)
1965 if nops(ord
) <= nops(ps
)+1 then
1966 for i
in is do iss
:= {op(iss
),[{op(qs
),i
},qhi
[1][2]]} od
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
)}
1977 if qsi
= {} then [] else op(sort([op(qsi
)],`charsets/lenord`)) fi
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;
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;
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`);
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
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]
2012 cs := `charsets/fcharseta`(qs,ord,medset);
2013 factorset := op(2,cs[2]);
2015 if 1 < printlevel and ind = 1 then
2017 lprint(`Characteristic set produced`,csno,nops(qhi),
2018 nops(qsi),nops(qs));
2023 cs := [`charsets/fcnormal`(cs,ord,2)];
2024 if 1 < nops(cs) then factorset := factorset union op(2,cs[2])
2028 if mind and 2 < nops(indets(cs[1])) then
2029 cs := `charsets/removecont`(cs,ord,'ts
');
2030 factorset := factorset union ts
2033 cs := `charsets/removecont`(
2034 `charsets/charseta`([op(qs)],ord,medset),ord,'factorset
')
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);
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
2047 lprint(`Characteristic set produced`,csno,nops(qhi),
2048 nops(qsi),nops(qs));
2052 if not member(cs,pi) then
2054 if 0 < `charsets/class`(cs[1],ord) then
2055 ts := `charsets/irras`(cs,ord,ind);
2057 qsi := {cs,op(qsi)};
2058 if nops(cs) = nops(ord) then
2059 is := `charsets/factorps`(factorset)
2061 is := `charsets/initialset`(cs,ord) union
2062 `charsets/factorps`(factorset)
2064 iss := `charsets/adjoin`(is,qs,qqi)
2067 iss := `charsets/adjoin`(
2068 `charsets/factorps`(factorset),qs,qqi)
2072 `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2076 is := `charsets/factorps`(factorset);
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)}
2092 else op(sort(`charsets/contract`(qsi,ord,1),`charsets/lenord`))
2096 # test whether ps is a subset or sublist of qs
2097 `charsets/subset` :=
2101 for p in ps do if not member(p,qs) then RETURN(false) fi od; true
2104 # subroutine for irrcharser, qirrcharser and others
2105 `charsets/adjoinb` :=
2108 local iss,i,j,ind,qhi,itt;
2110 qhi := qh minus {qs};
2113 itt := {i,op(qs),op(cs)};
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
2126 # examine the irreducibility of as for irrcharser
2129 proc(as,ord,inda,den)
2130 local ind,i,j,p,qs,n,fs,ja,dd;
2131 options remember,system;
2135 for i to nops(as) do
2137 fs := `charsets/dfactors`(p);
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
')
2156 if 3 < nargs then den := dd fi;
2160 # subroutine for irras
2161 `charsets/irrassub` :=
2163 proc(as,n,ord,ind,ja,den)
2165 global `charsets/das`;
2166 for m from n+1 while m <= nops(as) and `charsets/degreel`(as[m],ord) = 1
2171 if m <= nops(as) then
2172 vv := `charsets/lvar`(as[m],ord);
2174 qs := `charsets/factoras`(as[m],['as
[i
]' $ ('i
' = 1 .. m-1)],ord)
2176 qs := `charsets/cfactor`(as[m],['as
[i
]' $ ('i
' = 1 .. m-1)],ord);
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
')
2187 if 5 < nargs then den := dd fi;
2191 # collect distinct nonconstant factors of a polynomial q
2192 `charsets/dfactors` :=
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
2212 # normalize ascending set cs wrt ord
2213 `charsets/fcnorm` := proc(cs,ord,m)
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
2223 # normalize the last pol in an ascending set cs wrt ord
2224 `charsets/fcnormal` :=
2227 local n,ini,i,j,ggg,gg,ff,ccs,dd,cd,fs,nt;
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));
2238 if 0 < `charsets/degree`(gg,`charsets/lvar`(cs[i],ord)) then
2240 gg := {`charsets/pfactor`(gg)};
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]]
2252 ccs := [`charsets/fcnormal`(subs(cs[i] = ff,cs),ord,m)]
2254 if nops(ccs) = 1 then
2255 RETURN(ccs[1],`common divisors` = cd)
2258 ccs[1],`common divisors` = {op(cd),op(op(2,ccs[2]))}
2263 `charsets/prem`(dd*ggg[2],cs[i],`charsets/lvar`(cs[i],ord))
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
'))};
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))))];
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)))
2298 # the modified gcdex for fcnormal
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
');
2315 r := prem(c,d,x,'m
','q
');
2317 divide(m*c1-q*d1,pm,'r1
');
2318 divide(c2*m-q*d2,pm,'r2
');
2327 subs(II,[c1*cd,c2*cc,c*cc*cd])
2330 # the extended irreducible char series of poly set ps
2331 `charsets/exirrcharser` :=
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;
2338 for n from 0 while qhi <> {} do
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]
2347 `charsets/`.(substring(medset,10 .. length(medset)))(qs,ord);
2348 cs := `charsets/removecont`(%,ord,'factorset
')
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
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
');
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
');
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])
2383 rr := `charsets/nopower`(
2384 `charsets/prod`({op(is),qhi[1][2]}))
2386 `charsets/premas`(rr,cs,ord);
2387 r := `charsets/simp`(%,cs,ord);
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]
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]
2407 if nops(ord) <= nops(ps)+1 then
2408 for i in is do iss := {op(iss),[{op(qs),i},qhi[1][2]]} od
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
2417 if not `charsets/subset`(cs,qs) then
2418 `charsets/charseta`({op(qs),op(cs)},ord,medset)
2422 if ts[2] = 1 then cs := qs
2423 else cs := {op(qs),op(1 .. ts[2]-1,cs)}
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)}
2440 if qsi = {} then [] else op(sort([op(qsi)],`charsets/lenord`)) fi
2443 # subroutine for irrcharser, qirrcharser and others
2444 `charsets/select` :=
2451 if n <= nops(i) then qq := {i,op(qq)} else pp := {i,op(pp)} fi
2456 # subroutine for irrcharser, qirrcharser and others
2457 `charsets/adjoin` :=
2460 local iss,i,j,ind,qhi,itt;
2462 qhi := qh minus {qs};
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
2478 # subroutine for trisersub
2479 `charsets/adjoina` :=
2482 local iss,i,j,ind,qhi,itt;
2484 qhi := qh minus {qs};
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
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
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` :=
2515 if nops(cs) < 2 then [op(cs)]
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)}
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)]
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` :=
2545 if `charsets/premas`(i,cs2,ord) <> 0 then RETURN(false) fi
2547 is := `charsets/initialset1`(cs1,ord);
2549 if `charsets/premas`(i,cs2,ord) = 0 then RETURN(false) fi
2554 # check the irreducibility of as: subroutine for contract
2559 if irr = 1 then true
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
2576 if 1 < `charsets/degreel`(i,ord) then RETURN(false) fi
2578 if irr = 0 or nops(as) < 2 then true
2580 for i from 2 to nops(as) do
2583 `charsets/initial`(as[i],ord),`charsets/lvar`(as[j],ord)
2594 # the quasi-irreducible char series of poly set ps
2595 `charsets/qirrcharser` :=
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;
2605 if medset <> `charsets/basset` and medset <> `charsets/wbasset` then
2609 for n from 0 while qhi <> {} do
2610 qhi := sort([op(qhi)],`charsets/nopsord`);
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
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]
2625 cs := `charsets/fcharseta`(qs,ord,medset);
2626 factorset := op(2,cs[2]);
2627 if 1 < printlevel then
2629 lprint(`Characteristic set produced`,csno,nops(qhi),
2630 nops(qsi),nops(qs));
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
')
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);
2646 if not `charsets/subset`(cs,qs) then
2647 cs := `charsets/charseta`({op(qs),op(cs)},ord,medset)
2649 if 1 < printlevel then
2651 lprint(`Characteristic set produced`,csno,nops(qhi),
2652 nops(qsi),nops(qs));
2656 if not member(cs,pi) then
2658 if 0 < `charsets/class`(cs[1],ord) then
2659 ts := `charsets/qirras`(cs,ord);
2661 qsi := {cs,op(qsi)};
2662 if nops(cs) = nops(ord) then
2663 is := `charsets/factorps`(factorset)
2665 is := `charsets/initialset`(cs,ord) union
2666 `charsets/factorps`(factorset)
2668 iss := `charsets/adjoin`(is,qs,qqi)
2671 iss := `charsets/adjoin`(
2672 `charsets/factorps`(factorset),qs,qqi)
2676 `charsets/adjoin`(`charsets/factorps`(factorset),qs,qqi)
2680 is := `charsets/factorps`(factorset) union ts[1];
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)}
2694 else op(sort(`charsets/contract`(qsi,ord,2),`charsets/lenord`))
2698 # examine the irreducibility of as for qirrcharser
2699 `charsets/qirras` :=
2702 local ind,i,j,p,qs,fs,n,m,ja;
2703 options remember,system;
2707 for i to nops(as) do
2709 fs := `charsets/dfactors`(p);
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
2730 `Warning: factorization over algebraic field required for ics`
2738 # subroutine for `charsets/cfactor`
2739 `charsets/cfactorsub` :=
2742 local ind,i,ff,fn,ffn,lind;
2744 if type(ff,`^`) then ind := map(`charsets/newfactoras`,ff,as,ord)
2745 elif type(ff,`*`) then
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)
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
');
2765 if type(%,{`*`,`^`}) then simplify(%/denom(f)) else f fi
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` :=
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
2781 elif `charsets/degree`(f,vf) = 1 then RETURN(f)
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))
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)
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)
2823 # test for a trivial case --- can it be extended?
2825 `charsets/trivial` :=
2827 proc(ff,aa,vf,va,fn)
2828 local f,a,da,df,ss,i;
2833 if numer(f/lcoeff(f)) = subs(va = vf,numer(a/lcoeff(a))) and 2 < nops(f)
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);
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
2849 # modified pseudo-divison with multiplied initial factor as 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)
2861 if dv <= dr then l := coeff(v,x,dv); v := expand(v-l*x^dv)
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;
2880 # main subroutine for newfactoras
2881 # considerably modified and improved in December 1991
2882 `charsets/newfactorassub` :=
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`;
2890 vf := `charsets/lvar`(f,ord);
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);
2900 for i from 2 to nops(nord) do
2901 con := con+`charsets/degree`(f,nord[i])
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(%)]))
2920 if con <> 0 and `charsets/con` then der := 0; ff := f; con := 0
2922 if `charsets/das` <> [false] then
2923 die := `charsets/das`[1];
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
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]}
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)};
2972 if `charsets/checkwith`(`charsets/with`,is union fs) then
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)]
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`)
2993 cs := [`charsets/qfactor`(factor(ccs[1]),nord)]
2996 if nops(cs) = 1 then
2997 if `charsets/linearas`(ccs,nord) then
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
3008 fff := `charsets/divide`(fff,cc,as,mord);
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)
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
3027 else cr := [op(cr),cc]
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
3054 con := op(2 .. nops(ccs),ccs);
3055 if inda and not `charsets/vanish`(cs[i],is)
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
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
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
3086 ['`charsets/newfactorassub`(cr
[i
],as
,ord
)' $ ('i
' = 1 .. nops(cr))]
3088 elif nops(cr) = 0 then product('ci
[i
]','i
' = 1 .. nops(ci))
3090 product('ci
[i
]','i
' = 1 .. nops(ci))*`charsets/prod`(
3091 ['`charsets/newfactorassub`(cr
[i
],as
,ord
)' $ ('i
' = 1 .. nops(cr))]
3096 # compute the GCD of f and g over the algebraic field having
3097 # adjoining asc set as
3103 if `charsets/degree`(f,mord[nas]) = 0 or `charsets/degree`(g,mord[nas]) = 0
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
3116 # subroutine for algcd
3117 `charsets/fcharsetnA` :=
3119 proc(as,ps,ord,fset1,fset)
3120 local cs,rs,fset2,fset3,nas;
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
')
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` :=
3143 for i
from nas
by -1 to 1 do subs(mord
[i
] = RootOf(as
[i
],mord
[i
]),%) od;
3145 for i
to nas
do subs(RootOf(as
[i
],mord
[i
]) = mord
[i
],%) od;
3149 # division over an
algebraic field
with adjoining ascending set as
3150 `charsets/divide` :=
3154 sprem(ff
,f
,`charsets/lvar`(ff
,ord
),'m','q'); `charsets/premas`(q
,as
,ord
)
3157 # check
if an ascending set
is quasilinear
3159 `charsets/linearas` :=
3163 if nops(cs
) = 1 then true
3165 for i
from 2 to nops(cs
) do
3166 if 1 < `charsets/degreel`(cs
[i
],ord
) then RETURN(false) fi
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` :=
3181 if `charsets/degree`(f
,x
) < `charsets/degree`(g
,x
) then true
3186 # random generator
for linear transformation
3187 `charsets/die` := rand(3 ..
8):
3189 #
remove polys
in ps as
factors from f
3190 `charsets/movefactorps` :=
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
))}
3200 # check
if q vansihes one poly
in ps
3201 `charsets/vanish` :=
3205 for p
in ps
do if divide(q
,p
) then RETURN(true) fi od; false
3208 # sequence of non
-constant factors of f
3209 `charsets/qfactor` :=
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
))
3221 # sequence of non
-constant (multiple
) factors of f
3222 `charsets/qqfactor` :=
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
))
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
3240 `charsets/tefactor` :=
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`;
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]);
3254 [`charsets/qqfactor`(%,[vf
])];
3255 if type(%%,{`*`,`^`}) and
3256 max('`charsets/degree`(%[i],vf)' $
('i' = 1 ..
nops(%))) < df
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;
3268 `charsets/dasA` := [1,-1,2,-2,3,-3,false];
3269 `charsets/dieA` := rand(-10*nv ..
10*nv
);
3272 global `charsets/dasA`,`charsets/dieA`;
3273 if `charsets/dasA` <> [false] then
3275 `charsets/dasA` := [op(2 ..
nops(`charsets/dasA`),`charsets/dasA`)]
3278 else `charsets/dieA`()
3282 tvar
:= `charsets/noterms`(nv
,`charsets/degree`(f
,var
));
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
3299 else fs
:= [op(fs
),ff
]
3303 sum('var[i]','i' = 1 ..
nops(var
));
3304 coeffs(expand(%^mm
),var
,'tt');
3307 gg
:= gg
+sum('_y.(%+i)*tt[i]','i' = 1 ..
nops(tt
));
3308 yvar
:= yvar
union {'_y.(%%+i)' $
('i' = 1 ..
nops(tt
))};
3311 for j
to nops(fs
[1]) do
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');
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
3336 `charsets/divideA`(ff
,j
,as
,ord
);
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
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;
3352 sol
:= expand(subs(op(sol
),gg
));
3353 `charsets/divideA`(ff
,sol
,as
,ord
);
3356 ci
:= ci
union {sol
};
3357 if 1 < printlevel
then
3358 lprint(`A non-trivial factor found:`,j
)
3366 ci
:= ci
union {ff
};
3367 `charsets/prod`(map(`charsets/newfactoras`,ci
,as
,ord
))
3369 if 1 < printlevel
then lprint(`Heuristic tefactor failed`) fi;
3370 `charsets/newfactorassub`(f
,as
,ord
,0)
3374 # numbers of maximal terms
in a poly of total
degree d
in n variables
3375 `charsets/noterms` :=
3379 sum('product('n
+j
-1','j
' = 1 .. i)/i!','i' = 1 .. d
)+1
3382 # check
if an ascending set as
is irreducible
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
3392 fs
:= {`charsets/qfactor`(factor(as
[1]),[xa
])};
3393 if nops(fs
) = 1 then true else false fi
3396 as1
:= [op(1 ..
nops(as
)-1,as
)];
3397 if not `charsets/isirr`(as1
,ord
) then false
3400 xa
:= `charsets/lvar`(f
,ord
);
3401 if xa
= 0 then false
3402 elif `charsets/degree`(f
,xa
) = 1 then true
3404 fs
:= {`charsets/qfactor`(`charsets/cfactor`(f
,as1
,ord
),[xa
])};
3405 if nops(fs
) = 1 then true else false fi
3411 # get all possible
combinations (used
for tefactor
)
3412 `charsets/getall` :=
3416 if nops(fs
) = 1 then {'[fs[1][i]]' $
('i' = 1 ..
nops(fs
[1]))}
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
))}
3426 #
select a poly
in fs closest
to g
3427 `charsets/getclose` :=
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
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;
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;
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;
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;
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
3485 if _help
<> true then
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;
3502 cv
:= [coeffs(expand(g
),vv
,'dg')];
3503 for i
to nops(gs
) do
3504 chs
:= [op(chs
),[coeffs(expand(gs
[i
]),vv
,'df')]];
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
))]
3523 lprint(`Please help to choose one polynomial in the list`);
3525 lprint(`which is closest to the polynomial`);
3527 rr
:= readstat(`and enter the polynomial number in the list: `);
3530 else ja
:= 1; RETURN(fs
[1])
3535 # a subroutine
for getclose
3543 for i
to nops(ps
) do if ps
[i
] <> qs
[i
] then m
:= m
+1 fi od;
3548 # division over an
algebraic field
with adjoining ascending set as
3549 `charsets/divideA` :=
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
)
3560 # factorize poly f over
algebraic number field
with minimal polys
in as
3561 #
-- Hu
-Wang
's method
3562 `charsets/factoras` :=
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`;
3569 vf := `charsets/lvar`(pf,ord);
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);
3579 for i from 2 to nops(nord) do
3580 con := con+`charsets/degree`(pf,nord[i])
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(%)]))
3597 for i to nops(pas) do
3598 df := `charsets/degreel`(pas[i],ord);
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);
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
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)
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));
3632 for i from 0 to df-1 do
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))
3647 fg := subs(sol[1],gg)*
3648 `charsets/factoras`(numer(subs(sol[1],hh)),as,ord);
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` :=
3662 local i,vf,nv,df,inf,ff,sol,das;
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]);
3670 [`charsets/qqfactor`(%,[vf])];
3671 if type(%%,{`*`,`^`}) and
3672 max('`charsets/degree`(%[i
],vf
)' $ ('i
' = 1 .. nops(%))) < df
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)
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
3692 if 1 < printlevel then lprint(`Heuristic tsfactor failed`) fi;
3693 `charsets/factoras`(f,as,ord,0)
3696 # subroutine for factoras
3700 if r = 1 then sum(ss,`charsets/@k`.r = 0 .. `charsets/@m`.r-1)
3702 sum(`charsets/summ`(ss,r-1),`charsets/@k`.r = 0 .. `charsets/@m`.r-1)
3706 # subroutine for factoras
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))}
3719 # subroutine for factoras
3720 `charsets/getvars` :=
3724 if type(as,{set,list}) then
3725 {'op(`charsets/getvars`(as
[i
]))' $ ('i
' = 1 .. nops(as))}
3730 if type(i,indexed) then
3731 if op(0,i) = `charsets/@g` or op(0,i) = `charsets/@h` then
3740 # find rational zeros of poly set ps
3741 `charsets/solveps` :=
3744 local cs,ord,sol,j,phi,qs,qs1,n,factorset;
3746 if 1 < printlevel then
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);
3755 cs := `charsets/fqcharsetn`(ps,ord,[{},{}],'factorset
');
3756 factorset := factorset[1];
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;
3762 cs := `charsets/charseta`(phi[1],ord,`charsets/`.wcharsetn);
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(%)})];
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))}
3777 if 1 < nops(phi) then phi := {op(2 .. nops(phi),phi)}
3782 if sol = {} then op({}) else op(sol) fi
3785 # subroutine for solveps
3786 `charsets/verify` :=
3790 for i to nops(sol) do
3791 if simplify(subs(sol[i],ps)) = {0} then RETURN({sol[i]})
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
3801 # prepare a list of triangular forms from poly set ps
3802 `charsets/trisersub` :=
3805 local qs,cs,iss,n,i,qhi,qsi,factorset,csno,ppi,qqi,ind,mem;
3808 for i to nops(ps) do
3809 if nops(expand(ps[i])) < 3 then ind := 1; break fi
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]);
3822 for n from 0 while qhi <> {} do
3823 qhi := sort([op(qhi)],`charsets/nopsord`);
3825 ppi := `charsets/select`(ppi,nops(qs));
3826 qqi := {op(qqi),op(ppi[2])};
3827 if n = 0 then ppi := {}
3829 ppi := {qs,op(ppi[1])};
3831 for i to nops(ps) do
3832 if nops(expand(ps[i])) < 3 then ind := 1; break fi
3835 cs := `charsets/nopower`(
3836 `charsets/charseta`(qs,ord,`charsets/`.charsetn));
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]);
3842 elif nops(qs)-3 < nops(ord) then
3843 cs := `charsets/fcharseta`(qs,ord,`charsets/`.wcharsetn);
3844 factorset := op(2,cs[2]);
3847 cs := `charsets/nopower`(
3848 `charsets/charseta`(qs,ord,`charsets/`.wcharsetn));
3853 if 1 < printlevel then
3856 `Characteristic set produced`,csno,nops(qhi),nops(qsi),nops(qs)
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)}
3872 else op(sort(`charsets/contract`(qsi,ord,-1),`charsets/lenord`))
3876 # find zeros of ascending set as
3877 `charsets/solveas` :=
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);
3886 for j to nops(sol) do
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])}}
3901 # find rational zeros of ascending set cs
3902 `charsets/solveasr` :=
3905 local is,ss,ts,sol,solm,i,j,k;
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);
3914 for j to nops(sol) do
3915 if simplify(subs(op(sol[j]),is)) = 0 then
3918 ss := {`charsets/solvel`(
3919 subs(sol[j],cs[i]),`charsets/lvar`(cs[i],ord))}
3922 '{op(sol
[j
]),op(ss
[k
])}' $ ('k
' = 1 .. nops(ss))
3933 if 2 < nargs then qs := ts fi;
3937 # find rational zeros of polynomial f wrt x: subroutine for solveasr
3938 `charsets/solvel` := proc(f,x)
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
3945 g := `charsets/factorps`({numer(f)});
3947 if `charsets/degree`(i,x) = 1 then
3948 sol := {op(sol),solve({i},{x})}
3955 # find a list of distinct linear factors of univariate poly f
3956 `charsets/getfactor` :=
3960 q := `charsets/getfact`(f,x);
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
3977 # find the product of linear factors of univar poly f using `factor/linfacts`
3978 `charsets/getfact` :=
3982 if `charsets/degree`(ff,x) = 1 then RETURN(ff) fi;
3983 f := convert(ff,`sqrfree/sqrfree`,x);
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(%))
3994 readlib(`factor/polynom`);
3995 readlib(`factor/unifactor`);
3996 readlib(`factor/linfacts`)(expand(numer(f)),x)
4000 # irreducible decomposition of algebraic variety defined by ps
4001 `charsets/irrvardec` :=
4004 local phi,psi,i,j,mem,qq,qs;
4007 if 1 < printlevel and nargs < 3 then lprint(`Variable order chosen:`,ord)
4009 if nargs <> 4 then psi := [`charsets/irrcharser`(ps,ord,medset)]
4011 psi := [`charsets/exirrcharser`([ps,1],ord,medset)];
4016 if type(i[1],list) then psi := psi,i[1] else psi := psi,i fi
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)
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
4049 op(sort([op(psi)],`charsets/lenord`))
4055 `charsets/primebasis` := proc(cs,ord)
4057 if nops(cs) = nops(ord) then is := {}
4058 else is := `charsets/initialset`(cs,ord)
4060 `charsets/saturbasis`(cs,is,ord)
4063 # basis of saturation of ps wrt js
4064 `charsets/saturbasis` :=
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
');
4074 for j to nops(gb) do
4075 if {op(zz)} minus indets(gb[j]) = {op(zz)} then
4076 qs := [gb[j],op(qs)]
4084 # primary decomposition of polynomial ideal generated by ps
4086 `charsets/pridealdec` :=
4090 ps,phi,psi,fs,pi,ph,e,i,ss,S,j,gb,gb1,urd,vrd,f,gs,k,n,ind,indb,con,sep,
4092 ps := {op(`charsets/expand`(qs))} minus {0};
4093 ps := grobner['gbasis
'](ps,`charsets/reverse`(ord),'plex
');
4094 phi := [[ps,1,0,{1}]];
4097 for n while phi <> [] do
4099 phi := [op(2 .. nops(phi),phi)];
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
4113 pi := [`charsets/irrvardec`(fs,ord,medset,0,0)];
4116 if 1 < printlevel then
4117 lprint(`pid: ivd finished at`,time(),e)
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)
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,
4151 if psi = {} then psi := {[gs,pi[i]]}; ph := gs
4153 psi union {[gs,pi[i]]};
4156 ph := `charsets/idealint`(ph,gs,ord);
4157 if `charsets/contain`(ps,ph,ord,'plex
') then
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}
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
');
4175 `charsets/satisfy`({op(gb)} union {f^k},sep*ss,ord)
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 []
4203 sort([`charsets/remred`([op(psi minus {[1]})],ord)],`charsets/lenord`)
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` :=
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
4224 # remove redundant poly sets from phi
4225 `charsets/remred` :=
4228 op(`charsets/remrsub`(`charsets/reverse`(`charsets/remrsub`(phi,ord)),ord))
4231 # main subroutine for remred
4232 `charsets/remrsub` :=
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
4247 ph := [op(ph),phi[i]]
4253 # test: does ideal(ps) contain ideal(qs)?
4254 `charsets/contain` :=
4258 if 1 < printlevel then lprint(`containment test starts at`,time()) fi;
4259 X := `charsets/reverse`(ord);
4261 if grobner['normalf
'](q,ps,X,pt) <> 0 then RETURN(false) fi
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` :=
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!`)
4284 # maximal independent set modulo gb
4285 `charsets/maxindset` :=
4288 local j,x,g,ind,u,urd;
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
4303 # compute the exponent
4304 `charsets/exponent` :=
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;
4317 `charsets/idealquo` :=
4321 if type(f,{set,list}) then
4322 qs := `charsets/idealquo`(ps,f[1],ord);
4324 [op(2 .. nops(f),f)];
4325 qs := `charsets/idealint`(qs,`charsets/idealquo`(ps,%,ord),ord)
4329 qs := `charsets/idealint`(ps,f,ord);
4330 grobner['gbasis
']({'simplify(qs
[j
]/f
)' $ ('j
' = 1 .. nops(qs))},
4331 `charsets/reverse`(ord),'plex
')
4335 # ideal intersection
4336 `charsets/idealint` :=
4340 if 1 < printlevel then lprint(`ideal intersection starts at`,time()) fi;
4341 if type(f,{set,list}) then
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
');
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())
4358 # ideal intersection - with remember
4359 `charsets/idealintR` :=
4364 if 1 < printlevel then lprint(`ideal intersection starts at`,time()) fi;
4365 if type(f,{set,list}) then
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
');
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())
4382 # basis of the saturation of ideal(ps) wrt js
4383 `charsets/saturbasisR` :=
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
');
4394 for j to nops(gb) do
4395 if {op(zz)} minus indets(gb[j]) = {op(zz)} then
4396 qs := [gb[j],op(qs)]
4404 # the extend:ed irreducible char series of polyset ps
4405 # test: is zero(ps) empty?
4406 `charsets/eicsTest` :=
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;
4413 if 1 < printlevel then lprint(`radical membership test starts at`,time())
4415 for n from 0 while qhi <> {} and qsi = {} do
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]
4424 `charsets/`.(substring(medset,10 .. length(medset)))(qs,ord);
4425 cs := `charsets/removecont`(%,ord,'factorset
')
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
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
');
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
');
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])
4460 rr := `charsets/nopower`(
4461 `charsets/prod`({qhi[1][2],op(is)}))
4463 `charsets/premas`(rr,cs,ord);
4464 r := `charsets/simp`(%,cs,ord);
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]
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]
4484 if nops(ord) <= nops(ps)+1 then
4485 for i in is do iss := {op(iss),[{i,op(qs)},qhi[1][2]]} od
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
4494 if not `charsets/subset`(cs,qs) then
4495 `charsets/charseta`({op(cs),op(qs)},ord,medset)
4499 if ts[2] = 1 then cs := qs
4500 else cs := {op(qs),op(1 .. ts[2]-1,cs)}
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)}
4517 if qsi <> {} then op(qsi) else [] fi
4520 # ordering wrt length
4521 `charsets/lenord` :=
4523 proc(a,b) if length(b) < length(a) then true else false fi end:
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`,