aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/zerodim.spad.pamphlet
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
committerdos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
commitab8cc85adde879fb963c94d15675783f2cf4b183 (patch)
treec202482327f474583b750b2c45dedfc4e4312b1d /src/algebra/zerodim.spad.pamphlet
downloadopen-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz
Initial population.
Diffstat (limited to 'src/algebra/zerodim.spad.pamphlet')
-rw-r--r--src/algebra/zerodim.spad.pamphlet1189
1 files changed, 1189 insertions, 0 deletions
diff --git a/src/algebra/zerodim.spad.pamphlet b/src/algebra/zerodim.spad.pamphlet
new file mode 100644
index 00000000..6b1db2a9
--- /dev/null
+++ b/src/algebra/zerodim.spad.pamphlet
@@ -0,0 +1,1189 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra zerodim.spad}
+\author{Marc Moreno Maza}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{package FGLMICPK FGLMIfCanPackage}
+<<package FGLMICPK FGLMIfCanPackage>>=
+)abbrev package FGLMICPK FGLMIfCanPackage
+++ Author: Marc Moreno Maza
+++ Date Created: 08/02/1999
+++ Date Last Updated: 08/02/1999
+++ Description:
+++ This is just an interface between several packages and domains.
+++ The goal is to compute lexicographical Groebner bases
+++ of sets of polynomial with type \spadtype{Polynomial R}
+++ by the {\em FGLM} algorithm if this is possible (i.e.
+++ if the input system generates a zero-dimensional ideal).
+++ Version: 1.
+FGLMIfCanPackage(R,ls): Exports == Implementation where
+ R: GcdDomain
+ ls: List Symbol
+ V ==> OrderedVariableList ls
+ N ==> NonNegativeInteger
+ Z ==> Integer
+ B ==> Boolean
+ Q1 ==> Polynomial R
+ Q2 ==> HomogeneousDistributedMultivariatePolynomial(ls,R)
+ Q3 ==> DistributedMultivariatePolynomial(ls,R)
+ E2 ==> HomogeneousDirectProduct(#ls,NonNegativeInteger)
+ E3 ==> DirectProduct(#ls,NonNegativeInteger)
+ poltopol ==> PolToPol(ls, R)
+ lingrobpack ==> LinGroebnerPackage(ls,R)
+ groebnerpack2 ==> GroebnerPackage(R,E2,V,Q2)
+ groebnerpack3 ==> GroebnerPackage(R,E3,V,Q3)
+ Exports == with
+
+ zeroDimensional?: List(Q1) -> B
+ ++ \axiom{zeroDimensional?(lq1)} returns true iff
+ ++ \axiom{lq1} generates a zero-dimensional ideal
+ ++ w.r.t. the variables of \axiom{ls}.
+ fglmIfCan: List(Q1) -> Union(List(Q1), "failed")
+ ++ \axiom{fglmIfCan(lq1)} returns the lexicographical Groebner
+ ++ basis of \axiom{lq1} by using the {\em FGLM} strategy,
+ ++ if \axiom{zeroDimensional?(lq1)} holds.
+ groebner: List(Q1) -> List(Q1)
+ ++ \axiom{groebner(lq1)} returns the lexicographical Groebner
+ ++ basis of \axiom{lq1}. If \axiom{lq1} generates a zero-dimensional
+ ++ ideal then the {\em FGLM} strategy is used, otherwise
+ ++ the {\em Sugar} strategy is used.
+
+ Implementation == add
+
+ zeroDim?(lq2: List Q2): Boolean ==
+ lq2 := groebner(lq2)$groebnerpack2
+ empty? lq2 => false
+ #lq2 < #ls => false
+ lv: List(V) := [(variable(s)$V)::V for s in ls]
+ for q2 in lq2 while not empty?(lv) repeat
+ m := leadingMonomial(q2)
+ x := mainVariable(m)::V
+ if ground?(leadingCoefficient(univariate(m,x))) then
+ lv := remove(x, lv)
+ empty? lv
+
+ zeroDimensional?(lq1: List(Q1)): Boolean ==
+ lq2: List(Q2) := [pToHdmp(q1)$poltopol for q1 in lq1]
+ zeroDim?(lq2)
+
+ fglmIfCan(lq1:List(Q1)): Union(List(Q1),"failed") ==
+ lq2: List(Q2) := [pToHdmp(q1)$poltopol for q1 in lq1]
+ lq2 := groebner(lq2)$groebnerpack2
+ not zeroDim?(lq2) => "failed"::Union(List(Q1),"failed")
+ lq3: List(Q3) := totolex(lq2)$lingrobpack
+ lq1 := [dmpToP(q3)$poltopol for q3 in lq3]
+ lq1::Union(List(Q1),"failed")
+
+ groebner(lq1:List(Q1)): List(Q1) ==
+ lq2: List(Q2) := [pToHdmp(q1)$poltopol for q1 in lq1]
+ lq2 := groebner(lq2)$groebnerpack2
+ not zeroDim?(lq2) =>
+ lq3: List(Q3) := [pToDmp(q1)$poltopol for q1 in lq1]
+ lq3 := groebner(lq3)$groebnerpack3
+ [dmpToP(q3)$poltopol for q3 in lq3]
+ lq3: List(Q3) := totolex(lq2)$lingrobpack
+ [dmpToP(q3)$poltopol for q3 in lq3]
+
+@
+\section{domain RGCHAIN RegularChain}
+<<domain RGCHAIN RegularChain>>=
+)abbrev domain RGCHAIN RegularChain
+++ Author: Marc Moreno Maza
+++ Date Created: 01/1999
+++ Date Last Updated: 23/01/1999
+++ Description:
+++ A domain for regular chains (i.e. regular triangular sets) over
+++ a Gcd-Domain and with a fix list of variables.
+++ This is just a front-end for the \spadtype{RegularTriangularSet}
+++ domain constructor.
+++ Version: 1.
+
+RegularChain(R,ls): Exports == Implementation where
+ R : GcdDomain
+ ls: List Symbol
+ V ==> OrderedVariableList ls
+ E ==> IndexedExponents V
+ P ==> NewSparseMultivariatePolynomial(R,V)
+ TS ==> RegularTriangularSet(R,E,V,P)
+
+ Exports == RegularTriangularSetCategory(R,E,V,P) with
+ zeroSetSplit: (List P, Boolean, Boolean) -> List $
+ ++ \spad{zeroSetSplit(lp,clos?,info?)} returns a list \spad{lts} of regular
+ ++ chains such that the union of the closures of their regular zero sets
+ ++ equals the affine variety associated with \spad{lp}. Moreover,
+ ++ if \spad{clos?} is \spad{false} then the union of the regular zero
+ ++ set of the \spad{ts} (for \spad{ts} in \spad{lts}) equals this variety.
+ ++ If \spad{info?} is \spad{true} then some information is
+ ++ displayed during the computations. See
+ ++ \axiomOpFrom{zeroSetSplit}{RegularTriangularSet}.
+
+ Implementation == RegularTriangularSet(R,E,V,P)
+
+@
+\section{package LEXTRIPK LexTriangularPackage}
+<<package LEXTRIPK LexTriangularPackage>>=
+)abbrev package LEXTRIPK LexTriangularPackage
+++ Author: Marc Moreno Maza
+++ Date Created: 08/02/1999
+++ Date Last Updated: 08/02/1999
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ Description:
+++ A package for solving polynomial systems with finitely many solutions.
+++ The decompositions are given by means of regular triangular sets.
+++ The computations use lexicographical Groebner bases.
+++ The main operations are \axiomOpFrom{lexTriangular}{LexTriangularPackage}
+++ and \axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage}.
+++ The second one provide decompositions by means of square-free regular triangular sets.
+++ Both are based on the {\em lexTriangular} method described in [1].
+++ They differ from the algorithm described in [2] by the fact that
+++ multiciplities of the roots are not kept.
+++ With the \axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage} operation
+++ all multiciplities are removed. With the other operation some multiciplities may remain.
+++ Both operations admit an optional argument to produce normalized triangular sets. \newline
+++ References: \newline
+++ [1] D. LAZARD "Solving Zero-dimensional Algebraic Systems"
+++ published in the J. of Symbol. Comput. (1992) 13, 117-131.\newline
+++ [2] M. MORENO MAZA and R. RIOBOO "Computations of gcd over
+++ algebraic towers of simple extensions" In proceedings of AAECC11, Paris, 1995.\newline
+++ Version: 2.
+
+LexTriangularPackage(R,ls): Exports == Implementation where
+
+ R: GcdDomain
+ ls: List Symbol
+ V ==> OrderedVariableList ls
+ E ==> IndexedExponents V
+ P ==> NewSparseMultivariatePolynomial(R,V)
+ TS ==> RegularChain(R,ls)
+ ST ==> SquareFreeRegularTriangularSet(R,E,V,P)
+ Q1 ==> Polynomial R
+ PS ==> GeneralPolynomialSet(R,E,V,P)
+ N ==> NonNegativeInteger
+ Z ==> Integer
+ B ==> Boolean
+ S ==> String
+ K ==> Fraction R
+ LP ==> List P
+ BWTS ==> Record(val : Boolean, tower : TS)
+ LpWTS ==> Record(val : (List P), tower : TS)
+ BWST ==> Record(val : Boolean, tower : ST)
+ LpWST ==> Record(val : (List P), tower : ST)
+ polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P)
+ quasicomppackTS ==> QuasiComponentPackage(R,E,V,P,TS)
+ regsetgcdpackTS ==> SquareFreeRegularTriangularSetGcdPackage(R,E,V,P,TS)
+ normalizpackTS ==> NormalizationPackage(R,E,V,P,TS)
+ quasicomppackST ==> QuasiComponentPackage(R,E,V,P,ST)
+ regsetgcdpackST ==> SquareFreeRegularTriangularSetGcdPackage(R,E,V,P,ST)
+ normalizpackST ==> NormalizationPackage(R,E,V,P,ST)
+
+ Exports == with
+
+ zeroDimensional?: LP -> B
+ ++ \axiom{zeroDimensional?(lp)} returns true iff
+ ++ \axiom{lp} generates a zero-dimensional ideal
+ ++ w.r.t. the variables involved in \axiom{lp}.
+ fglmIfCan: LP -> Union(LP, "failed")
+ ++ \axiom{fglmIfCan(lp)} returns the lexicographical Groebner
+ ++ basis of \axiom{lp} by using the {\em FGLM} strategy,
+ ++ if \axiom{zeroDimensional?(lp)} holds .
+ groebner: LP -> LP
+ ++ \axiom{groebner(lp)} returns the lexicographical Groebner
+ ++ basis of \axiom{lp}. If \axiom{lp} generates a zero-dimensional
+ ++ ideal then the {\em FGLM} strategy is used, otherwise
+ ++ the {\em Sugar} strategy is used.
+ lexTriangular: (LP, B) -> List TS
+ ++ \axiom{lexTriangular(base, norm?)} decomposes the variety
+ ++ associated with \axiom{base} into regular chains.
+ ++ Thus a point belongs to this variety iff it is a regular
+ ++ zero of a regular set in in the output.
+ ++ Note that \axiom{base} needs to be a lexicographical Groebner basis
+ ++ of a zero-dimensional ideal. If \axiom{norm?} is \axiom{true}
+ ++ then the regular sets are normalized.
+ squareFreeLexTriangular: (LP, B) -> List ST
+ ++ \axiom{squareFreeLexTriangular(base, norm?)} decomposes the variety
+ ++ associated with \axiom{base} into square-free regular chains.
+ ++ Thus a point belongs to this variety iff it is a regular
+ ++ zero of a regular set in in the output.
+ ++ Note that \axiom{base} needs to be a lexicographical Groebner basis
+ ++ of a zero-dimensional ideal. If \axiom{norm?} is \axiom{true}
+ ++ then the regular sets are normalized.
+ zeroSetSplit: (LP, B) -> List TS
+ ++ \axiom{zeroSetSplit(lp, norm?)} decomposes the variety
+ ++ associated with \axiom{lp} into regular chains.
+ ++ Thus a point belongs to this variety iff it is a regular
+ ++ zero of a regular set in in the output.
+ ++ Note that \axiom{lp} needs to generate a zero-dimensional ideal.
+ ++ If \axiom{norm?} is \axiom{true} then the regular sets are normalized.
+ zeroSetSplit: (LP, B) -> List ST
+ ++ \axiom{zeroSetSplit(lp, norm?)} decomposes the variety
+ ++ associated with \axiom{lp} into square-free regular chains.
+ ++ Thus a point belongs to this variety iff it is a regular
+ ++ zero of a regular set in in the output.
+ ++ Note that \axiom{lp} needs to generate a zero-dimensional ideal.
+ ++ If \axiom{norm?} is \axiom{true} then the regular sets are normalized.
+
+ Implementation == add
+
+ trueVariables(lp: List(P)): List Symbol ==
+ lv: List V := variables([lp]$PS)
+ truels: List Symbol := []
+ for s in ls repeat
+ if member?(variable(s)::V, lv) then truels := cons(s,truels)
+ reverse truels
+
+ zeroDimensional?(lp:List(P)): Boolean ==
+ truels: List Symbol := trueVariables(lp)
+ fglmpack := FGLMIfCanPackage(R,truels)
+ lq1: List(Q1) := [p::Q1 for p in lp]
+ zeroDimensional?(lq1)$fglmpack
+
+ fglmIfCan(lp:List(P)): Union(List(P), "failed") ==
+ truels: List Symbol := trueVariables(lp)
+ fglmpack := FGLMIfCanPackage(R,truels)
+ lq1: List(Q1) := [p::Q1 for p in lp]
+ foo := fglmIfCan(lq1)$fglmpack
+ foo case "failed" => return("failed" :: Union(List(P), "failed"))
+ lp := [retract(q1)$P for q1 in (foo :: List(Q1))]
+ lp::Union(List(P), "failed")
+
+ groebner(lp:List(P)): List(P) ==
+ truels: List Symbol := trueVariables(lp)
+ fglmpack := FGLMIfCanPackage(R,truels)
+ lq1: List(Q1) := [p::Q1 for p in lp]
+ lq1 := groebner(lq1)$fglmpack
+ lp := [retract(q1)$P for q1 in lq1]
+
+ lexTriangular(base: List(P), norm?: Boolean): List(TS) ==
+ base := sort(infRittWu?,base)
+ base := remove(zero?, base)
+ any?(ground?, base) => []
+ ts: TS := empty()
+ toSee: List LpWTS := [[base,ts]$LpWTS]
+ toSave: List TS := []
+ while not empty? toSee repeat
+ lpwt := first toSee; toSee := rest toSee
+ lp := lpwt.val; ts := lpwt.tower
+ empty? lp => toSave := cons(ts, toSave)
+ p := first lp; lp := rest lp; v := mvar(p)
+ algebraic?(v,ts) =>
+ error "lexTriangular$LEXTRIPK: should never happen !"
+ norm? and zero? remainder(init(p),ts).polnum =>
+ toSee := cons([lp, ts]$LpWTS, toSee)
+ (not norm?) and zero? (initiallyReduce(init(p),ts)) =>
+ toSee := cons([lp, ts]$LpWTS, toSee)
+ lbwt: List BWTS := invertible?(init(p),ts)$TS
+ while (not empty? lbwt) repeat
+ bwt := first lbwt; lbwt := rest lbwt
+ b := bwt.val; us := bwt.tower
+ (not b) => toSee := cons([lp, us], toSee)
+ lus: List TS
+ if norm?
+ then
+ newp := normalizedAssociate(p,us)$normalizpackTS
+ lus := [internalAugment(newp,us)$TS]
+ else
+ newp := p
+ lus := augment(newp,us)$TS
+ newlp := lp
+ while (not empty? newlp) and (mvar(first newlp) = v) repeat
+ newlp := rest newlp
+ for us in lus repeat
+ toSee := cons([newlp, us]$LpWTS, toSee)
+ algebraicSort(toSave)$quasicomppackTS
+
+ zeroSetSplit(lp:List(P), norm?:B): List TS ==
+ bar := fglmIfCan(lp)
+ bar case "failed" =>
+ error "zeroSetSplit$LEXTRIPK: #1 not zero-dimensional"
+ lexTriangular(bar::(List P),norm?)
+
+ squareFreeLexTriangular(base: List(P), norm?: Boolean): List(ST) ==
+ base := sort(infRittWu?,base)
+ base := remove(zero?, base)
+ any?(ground?, base) => []
+ ts: ST := empty()
+ toSee: List LpWST := [[base,ts]$LpWST]
+ toSave: List ST := []
+ while not empty? toSee repeat
+ lpwt := first toSee; toSee := rest toSee
+ lp := lpwt.val; ts := lpwt.tower
+ empty? lp => toSave := cons(ts, toSave)
+ p := first lp; lp := rest lp; v := mvar(p)
+ algebraic?(v,ts) =>
+ error "lexTriangular$LEXTRIPK: should never happen !"
+ norm? and zero? remainder(init(p),ts).polnum =>
+ toSee := cons([lp, ts]$LpWST, toSee)
+ (not norm?) and zero? (initiallyReduce(init(p),ts)) =>
+ toSee := cons([lp, ts]$LpWST, toSee)
+ lbwt: List BWST := invertible?(init(p),ts)$ST
+ while (not empty? lbwt) repeat
+ bwt := first lbwt; lbwt := rest lbwt
+ b := bwt.val; us := bwt.tower
+ (not b) => toSee := cons([lp, us], toSee)
+ lus: List ST
+ if norm?
+ then
+ newp := normalizedAssociate(p,us)$normalizpackST
+ lus := augment(newp,us)$ST
+ else
+ lus := augment(p,us)$ST
+ newlp := lp
+ while (not empty? newlp) and (mvar(first newlp) = v) repeat
+ newlp := rest newlp
+ for us in lus repeat
+ toSee := cons([newlp, us]$LpWST, toSee)
+ algebraicSort(toSave)$quasicomppackST
+
+ zeroSetSplit(lp:List(P), norm?:B): List ST ==
+ bar := fglmIfCan(lp)
+ bar case "failed" =>
+ error "zeroSetSplit$LEXTRIPK: #1 not zero-dimensional"
+ squareFreeLexTriangular(bar::(List P),norm?)
+
+@
+\section{package IRURPK InternalRationalUnivariateRepresentationPackage}
+<<package IRURPK InternalRationalUnivariateRepresentationPackage>>=
+)abbrev package IRURPK InternalRationalUnivariateRepresentationPackage
+++ Author: Marc Moreno Maza
+++ Date Created: 01/1999
+++ Date Last Updated: 23/01/1999
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ Description:
+++ An internal package for computing the rational univariate representation
+++ of a zero-dimensional algebraic variety given by a square-free
+++ triangular set.
+++ The main operation is \axiomOpFrom{rur}{InternalRationalUnivariateRepresentationPackage}.
+++ It is based on the {\em generic} algorithm description in [1]. \newline References:
+++ [1] D. LAZARD "Solving Zero-dimensional Algebraic Systems"
+++ Journal of Symbolic Computation, 1992, 13, 117-131
+++ Version: 1.
+
+InternalRationalUnivariateRepresentationPackage(R,E,V,P,TS): Exports == Implementation where
+ R : Join(EuclideanDomain,CharacteristicZero)
+ E : OrderedAbelianMonoidSup
+ V : OrderedSet
+ P : RecursivePolynomialCategory(R,E,V)
+ TS : SquareFreeRegularTriangularSetCategory(R,E,V,P)
+ N ==> NonNegativeInteger
+ Z ==> Integer
+ B ==> Boolean
+ LV ==> List V
+ LP ==> List P
+ PWT ==> Record(val: P, tower: TS)
+ LPWT ==> Record(val: LP, tower: TS)
+ WIP ==> Record(pol: P, gap: Z, tower: TS)
+ BWT ==> Record(val:Boolean, tower: TS)
+ polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P)
+ normpack ==> NormalizationPackage(R,E,V,P,TS)
+
+ Exports == with
+
+ rur: (TS,B) -> List TS
+ ++ \spad{rur(ts,univ?)} returns a rational univariate representation
+ ++ of \spad{ts}. This assumes that the lowest polynomial in \spad{ts}
+ ++ is a variable \spad{v} which does not occur in the other polynomials
+ ++ of \spad{ts}. This variable will be used to define the simple
+ ++ algebraic extension over which these other polynomials will be
+ ++ rewritten as univariate polynomials with degree one.
+ ++ If \spad{univ?} is \spad{true} then these polynomials will have
+ ++ a constant initial.
+ checkRur: (TS, List TS) -> Boolean
+ ++ \spad{checkRur(ts,lus)} returns \spad{true} if \spad{lus}
+ ++ is a rational univariate representation of \spad{ts}.
+
+ Implementation == add
+
+ checkRur(ts: TS, lts: List TS): Boolean ==
+ f0 := last(ts)::P
+ z := mvar(f0)
+ ts := collectUpper(ts,z)
+ dts: N := degree(ts)
+ lp := parts(ts)
+ dlts: N := 0
+ for us in lts repeat
+ dlts := dlts + degree(us)
+ rems := [removeZero(p,us) for p in lp]
+ not every?(zero?,rems) =>
+ output(us::OutputForm)$OutputPackage
+ return false
+ (dts =$N dlts)@Boolean
+
+ convert(p:P,sqfr?:B):TS ==
+ -- if sqfr? ASSUME p is square-free
+ newts: TS := empty()
+ sqfr? => internalAugment(p,newts)
+ p := squareFreePart(p)
+ internalAugment(p,newts)
+
+ prepareRur(ts: TS): List LPWT ==
+ not purelyAlgebraic?(ts)$TS =>
+ error "rur$IRURPK: #1 is not zero-dimensional"
+ lp: LP := parts(ts)$TS
+ lp := sort(infRittWu?,lp)
+ empty? lp =>
+ error "rur$IRURPK: #1 is empty"
+ f0 := first lp; lp := rest lp
+-- not (one?(init(f0)) and one?(mdeg(f0)) and zero?(tail(f0))) =>
+ not ((init(f0) = 1) and (mdeg(f0) = 1) and zero?(tail(f0))) =>
+ error "rur$IRURPK: #1 has no generating root."
+ empty? lp =>
+ error "rur$IRURPK: #1 has a generating root but no indeterminates"
+ z: V := mvar(f0)
+ f1 := first lp; lp := rest lp
+ x1: V := mvar(f1)
+ newf1 := x1::P - z::P
+ toSave: List LPWT := []
+ for ff1 in irreducibleFactors([f1])$polsetpack repeat
+ newf0 := eval(ff1,mvar(f1),f0)
+ ts := internalAugment(newf1,convert(newf0,true)@TS)
+ toSave := cons([lp,ts],toSave)
+ toSave
+
+ makeMonic(z:V,c:P,r:P,ts:TS,s:P,univ?:B): TS ==
+ --ASSUME r is a irreducible univariate polynomial in z
+ --ASSUME c and s only depends on z and mvar(s)
+ --ASSUME c and a have main degree 1
+ --ASSUME c and s have a constant initial
+ --ASSUME mvar(ts) < mvar(s)
+ lp: LP := parts(ts)
+ lp := sort(infRittWu?,lp)
+ newts: TS := convert(r,true)@TS
+ s := remainder(s,newts).polnum
+ if univ?
+ then
+ s := normalizedAssociate(s,newts)$normpack
+ for p in lp repeat
+ p := lazyPrem(eval(p,z,c),s)
+ p := remainder(p,newts).polnum
+ newts := internalAugment(p,newts)
+ internalAugment(s,newts)
+
+ next(lambda:Z):Z ==
+ if lambda < 0 then lambda := - lambda + 1 else lambda := - lambda
+
+ makeLinearAndMonic(p: P, xi: V, ts: TS, univ?:B, check?: B, info?: B): List TS ==
+ -- if check? THEN some VERIFICATIONS are performed
+ -- if info? THEN some INFORMATION is displayed
+ f0 := last(ts)::P
+ z: V := mvar(f0)
+ lambda: Z := 1
+ ts := collectUpper(ts,z)
+ toSee: List WIP := [[f0,lambda,ts]$WIP]
+ toSave: List TS := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ (f0, lambda, ts) := (wip.pol, wip.gap, wip.tower)
+ if check? and ((not univariate?(f0)$polsetpack) or (mvar(f0) ~= z))
+ then
+ output("Bad f0: ")$OutputPackage
+ output(f0::OutputForm)$OutputPackage
+ c: P := lambda * xi::P + z::P
+ f := eval(f0,z,c); q := eval(p,z,c)
+ prs := subResultantChain(q,f)
+ r := first prs; prs := rest prs
+ check? and ((not zero? degree(r,xi)) or (empty? prs)) =>
+ error "rur$IRURPK: should never happen !"
+ s := first prs; prs := rest prs
+ check? and (zero? degree(s,xi)) and (empty? prs) =>
+ error "rur$IRURPK: should never happen !!"
+ if zero? degree(s,xi) then s := first prs
+-- not one? degree(s,xi) =>
+ not (degree(s,xi) = 1) =>
+ toSee := cons([f0,next(lambda),ts]$WIP,toSee)
+ h := init(s)
+ r := squareFreePart(r)
+ ground?(h) or ground?(gcd(h,r)) =>
+ for fr in irreducibleFactors([r])$polsetpack repeat
+ ground? fr => "leave"
+ toSave := cons(makeMonic(z,c,fr,ts,s,univ?),toSave)
+ if info?
+ then
+ output("Unlucky lambda")$OutputPackage
+ output(h::OutputForm)$OutputPackage
+ output(r::OutputForm)$OutputPackage
+ toSee := cons([f0,next(lambda),ts]$WIP,toSee)
+ toSave
+
+ rur (ts: TS,univ?:Boolean): List TS ==
+ toSee: List LPWT := prepareRur(ts)
+ toSave: List TS := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ ts: TS := wip.tower
+ lp: LP := wip.val
+ empty? lp => toSave := cons(ts,toSave)
+ p := first lp; lp := rest lp
+ xi: V := mvar(p)
+ p := remainder(p,ts).polnum
+ if not univ?
+ then
+ p := primitivePart stronglyReduce(p,ts)
+ ground?(p) or (mvar(p) < xi) =>
+ error "rur$IRUROK: should never happen"
+-- (one? mdeg(p)) and (ground? init(p)) =>
+ (mdeg(p) = 1) and (ground? init(p)) =>
+ ts := internalAugment(p,ts)
+ wip := [lp,ts]
+ toSee := cons(wip,toSee)
+ lts := makeLinearAndMonic(p,xi,ts,univ?,false,false)
+ for ts in lts repeat
+ wip := [lp,ts]
+ toSee := cons(wip,toSee)
+ toSave
+
+@
+\section{package RURPK RationalUnivariateRepresentationPackage}
+<<package RURPK RationalUnivariateRepresentationPackage>>=
+)abbrev package RURPK RationalUnivariateRepresentationPackage
+++ Author: Marc Moreno Maza
+++ Date Created: 01/1999
+++ Date Last Updated: 23/01/1999
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Description:
+++ A package for computing the rational univariate representation
+++ of a zero-dimensional algebraic variety given by a regular
+++ triangular set. This package is essentially an interface for the
+++ \spadtype{InternalRationalUnivariateRepresentationPackage} constructor.
+++ It is used in the \spadtype{ZeroDimensionalSolvePackage}
+++ for solving polynomial systems with finitely many solutions.
+++ Version: 1.
+
+RationalUnivariateRepresentationPackage(R,ls): Exports == Implementation where
+ R : Join(EuclideanDomain,CharacteristicZero)
+ ls: List Symbol
+ N ==> NonNegativeInteger
+ Z ==> Integer
+ P ==> Polynomial R
+ LP ==> List P
+ U ==> SparseUnivariatePolynomial(R)
+ RUR ==> Record(complexRoots: U, coordinates: LP)
+
+ Exports == with
+
+ rur: (LP,Boolean) -> List RUR
+ ++ \spad{rur(lp,univ?)} returns a rational univariate representation
+ ++ of \spad{lp}. This assumes that \spad{lp} defines a regular
+ ++ triangular \spad{ts} whose associated variety is zero-dimensional
+ ++ over \spad{R}. \spad{rur(lp,univ?)} returns a list of items
+ ++ \spad{[u,lc]} where \spad{u} is an irreducible univariate polynomial
+ ++ and each \spad{c} in \spad{lc} involves two variables: one from \spad{ls},
+ ++ called the coordinate of \spad{c}, and an extra variable which
+ ++ represents any root of \spad{u}. Every root of \spad{u} leads to
+ ++ a tuple of values for the coordinates of \spad{lc}. Moreover,
+ ++ a point \spad{x} belongs to the variety associated with \spad{lp} iff
+ ++ there exists an item \spad{[u,lc]} in \spad{rur(lp,univ?)} and
+ ++ a root \spad{r} of \spad{u} such that \spad{x} is given by the
+ ++ tuple of values for the coordinates of \spad{lc} evaluated at \spad{r}.
+ ++ If \spad{univ?} is \spad{true} then each polynomial \spad{c}
+ ++ will have a constant leading coefficient w.r.t. its coordinate.
+ ++ See the example which illustrates the \spadtype{ZeroDimensionalSolvePackage}
+ ++ package constructor.
+ rur: (LP) -> List RUR
+ ++ \spad{rur(lp)} returns the same as \spad{rur(lp,true)}
+ rur: (LP,Boolean,Boolean) -> List RUR
+ ++ \spad{rur(lp,univ?,check?)} returns the same as \spad{rur(lp,true)}.
+ ++ Moreover, if \spad{check?} is \spad{true} then the result is checked.
+
+ Implementation == add
+ news: Symbol := new()$Symbol
+ lv: List Symbol := concat(ls,news)
+ V ==> OrderedVariableList(lv)
+ Q ==> NewSparseMultivariatePolynomial(R,V)
+ E ==> IndexedExponents V
+ TS ==> SquareFreeRegularTriangularSet(R,E,V,Q)
+ QWT ==> Record(val: Q, tower: TS)
+ LQWT ==> Record(val: List Q, tower: TS)
+ polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,Q)
+ normpack ==> NormalizationPackage(R,E,V,Q,TS)
+ rurpack ==> InternalRationalUnivariateRepresentationPackage(R,E,V,Q,TS)
+ newv: V := variable(news)::V
+ newq : Q := newv :: Q
+
+ rur(lp: List P, univ?: Boolean, check?: Boolean): List RUR ==
+ lp := remove(zero?,lp)
+ empty? lp =>
+ error "rur$RURPACK: #1 is empty"
+ any?(ground?,lp) =>
+ error "rur$RURPACK: #1 is not a triangular set"
+ ts: TS := [[newq]$(List Q)]
+ lq: List Q := []
+ for p in lp repeat
+ rif: Union(Q,"failed") := retractIfCan(p)$Q
+ rif case "failed" =>
+ error "rur$RURPACK: #1 is not a subset of R[ls]"
+ q: Q := rif::Q
+ lq := cons(q,lq)
+ lq := sort(infRittWu?,lq)
+ toSee: List LQWT := [[lq,ts]$LQWT]
+ toSave: List TS := []
+ while not empty? toSee repeat
+ lqwt := first toSee; toSee := rest toSee
+ lq := lqwt.val; ts := lqwt.tower
+ empty? lq =>
+ -- output(ts::OutputForm)$OutputPackage
+ toSave := cons(ts,toSave)
+ q := first lq; lq := rest lq
+ not (mvar(q) > mvar(ts)) =>
+ error "rur$RURPACK: #1 is not a triangular set"
+ empty? (rest(ts)::TS) =>
+ lfq := irreducibleFactors([q])$polsetpack
+ for fq in lfq repeat
+ newts := internalAugment(fq,ts)
+ newlq := [remainder(q,newts).polnum for q in lq]
+ toSee := cons([newlq,newts]$LQWT,toSee)
+ lsfqwt: List QWT := squareFreePart(q,ts)
+ for qwt in lsfqwt repeat
+ q := qwt.val; ts := qwt.tower
+ if not ground? init(q)
+ then
+ q := normalizedAssociate(q,ts)$normpack
+ newts := internalAugment(q,ts)
+ newlq := [remainder(q,newts).polnum for q in lq]
+ toSee := cons([newlq,newts]$LQWT,toSee)
+ toReturn: List RUR := []
+ for ts in toSave repeat
+ lus := rur(ts,univ?)$rurpack
+ check? and (not checkRur(ts,lus)$rurpack) =>
+ output("RUR for: ")$OutputPackage
+ output(ts::OutputForm)$OutputPackage
+ output("Is: ")$OutputPackage
+ for us in lus repeat output(us::OutputForm)$OutputPackage
+ error "rur$RURPACK: bad result with function rur$IRURPK"
+ for us in lus repeat
+ g: U := univariate(select(us,newv)::Q)$Q
+ lc: LP := [convert(q)@P for q in parts(collectUpper(us,newv))]
+ toReturn := cons([g,lc]$RUR, toReturn)
+ toReturn
+
+ rur(lp: List P, univ?: Boolean): List RUR ==
+ rur(lp,univ?,false)
+
+ rur(lp: List P): List RUR == rur(lp,true)
+
+@
+\section{package ZDSOLVE ZeroDimensionalSolvePackage}
+Based on triangular decompositions and the {\bf RealClosure} constructor,
+the pacakge {\bf ZeroDimensionalSolvePackage} provides operations for
+computing symbolically the real or complex roots of polynomial systems
+with finitely many solutions.
+<<package ZDSOLVE ZeroDimensionalSolvePackage>>=
+)abbrev package ZDSOLVE ZeroDimensionalSolvePackage
+++ Author: Marc Moreno Maza
+++ Date Created: 23/01/1999
+++ Date Last Updated: 08/02/1999
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ A package for computing symbolically the complex and real roots of
+++ zero-dimensional algebraic systems over the integer or rational
+++ numbers. Complex roots are given by means of univariate representations
+++ of irreducible regular chains. Real roots are given by means of tuples
+++ of coordinates lying in the \spadtype{RealClosure} of the coefficient ring.
+++ This constructor takes three arguments. The first one \spad{R} is the
+++ coefficient ring. The second one \spad{ls} is the list of variables involved
+++ in the systems to solve. The third one must be \spad{concat(ls,s)} where
+++ \spad{s} is an additional symbol used for the univariate representations.
+++ WARNING: The third argument is not checked.
+++ All operations are based on triangular decompositions.
+++ The default is to compute these decompositions directly from the input
+++ system by using the \spadtype{RegularChain} domain constructor.
+++ The lexTriangular algorithm can also be used for computing these decompositions
+++ (see the \spadtype{LexTriangularPackage} package constructor).
+++ For that purpose, the operations \axiomOpFrom{univariateSolve}{ZeroDimensionalSolvePackage},
+++ \axiomOpFrom{realSolve}{ZeroDimensionalSolvePackage} and
+++ \axiomOpFrom{positiveSolve}{ZeroDimensionalSolvePackage} admit an optional
+++ argument. \newline Author: Marc Moreno Maza.
+
+++ Version: 1.
+
+ZeroDimensionalSolvePackage(R,ls,ls2): Exports == Implementation where
+ R : Join(OrderedRing,EuclideanDomain,CharacteristicZero,RealConstant)
+ ls: List Symbol
+ ls2: List Symbol
+ V ==> OrderedVariableList(ls)
+ N ==> NonNegativeInteger
+ Z ==> Integer
+ B ==> Boolean
+ P ==> Polynomial R
+ LP ==> List P
+ LS ==> List Symbol
+ Q ==> NewSparseMultivariatePolynomial(R,V)
+ U ==> SparseUnivariatePolynomial(R)
+ TS ==> RegularChain(R,ls)
+ RUR ==> Record(complexRoots: U, coordinates: LP)
+ K ==> Fraction R
+ RC ==> RealClosure(K)
+ PRC ==> Polynomial RC
+ REALSOL ==> List RC
+ URC ==> SparseUnivariatePolynomial RC
+ V2 ==> OrderedVariableList(ls2)
+ Q2 ==> NewSparseMultivariatePolynomial(R,V2)
+ E2 ==> IndexedExponents V2
+ ST ==> SquareFreeRegularTriangularSet(R,E2,V2,Q2)
+ Q2WT ==> Record(val: Q2, tower: ST)
+ LQ2WT ==> Record(val: List(Q2), tower: ST)
+ WIP ==> Record(reals: List(RC), vars: List(Symbol), pols: List(Q2))
+ polsetpack ==> PolynomialSetUtilitiesPackage(R,E2,V2,Q2)
+ normpack ==> NormalizationPackage(R,E2,V2,Q2,ST)
+ rurpack ==> InternalRationalUnivariateRepresentationPackage(R,E2,V2,Q2,ST)
+ quasicomppack ==> SquareFreeQuasiComponentPackage(R,E2,V2,Q2,ST)
+ lextripack ==> LexTriangularPackage(R,ls)
+
+ Exports == with
+ triangSolve: (LP,B,B) -> List RegularChain(R,ls)
+ ++ \spad{triangSolve(lp,info?,lextri?)} decomposes the variety
+ ++ associated with \axiom{lp} into regular chains.
+ ++ Thus a point belongs to this variety iff it is a regular
+ ++ zero of a regular set in in the output.
+ ++ Note that \axiom{lp} needs to generate a zero-dimensional ideal.
+ ++ If \axiom{lp} is not zero-dimensional then the result is only
+ ++ a decomposition of its zero-set in the sense of the closure
+ ++ (w.r.t. Zarisky topology).
+ ++ Moreover, if \spad{info?} is \spad{true} then some information is
+ ++ displayed during the computations.
+ ++ See \axiomOpFrom{zeroSetSplit}{RegularTriangularSetCategory}(lp,true,info?).
+ ++ If \spad{lextri?} is \spad{true} then the lexTriangular algorithm is called
+ ++ from the \spadtype{LexTriangularPackage} constructor
+ ++ (see \axiomOpFrom{zeroSetSplit}{LexTriangularPackage}(lp,false)).
+ ++ Otherwise, the triangular decomposition is computed directly from the input
+ ++ system by using the \axiomOpFrom{zeroSetSplit}{RegularChain} from \spadtype{RegularChain}.
+ triangSolve: (LP,B) -> List RegularChain(R,ls)
+ ++ \spad{triangSolve(lp,info?)} returns the same as \spad{triangSolve(lp,false)}
+ triangSolve: LP -> List RegularChain(R,ls)
+ ++ \spad{triangSolve(lp)} returns the same as \spad{triangSolve(lp,false,false)}
+ univariateSolve: RegularChain(R,ls) -> List Record(complexRoots: U, coordinates: LP)
+ ++ \spad{univariateSolve(ts)} returns a univariate representation
+ ++ of \spad{ts}.
+ ++ See \axiomOpFrom{rur}{RationalUnivariateRepresentationPackage}(lp,true).
+ univariateSolve: (LP,B,B,B) -> List RUR
+ ++ \spad{univariateSolve(lp,info?,check?,lextri?)} returns a univariate
+ ++ representation of the variety associated with \spad{lp}.
+ ++ Moreover, if \spad{info?} is \spad{true} then some information is
+ ++ displayed during the decomposition into regular chains.
+ ++ If \spad{check?} is \spad{true} then the result is checked.
+ ++ See \axiomOpFrom{rur}{RationalUnivariateRepresentationPackage}(lp,true).
+ ++ If \spad{lextri?} is \spad{true} then the lexTriangular algorithm is called
+ ++ from the \spadtype{LexTriangularPackage} constructor
+ ++ (see \axiomOpFrom{zeroSetSplit}{LexTriangularPackage}(lp,false)).
+ ++ Otherwise, the triangular decomposition is computed directly from the input
+ ++ system by using the \axiomOpFrom{zeroSetSplit}{RegularChain} from \spadtype{RegularChain}.
+ univariateSolve: (LP,B,B) -> List RUR
+ ++ \spad{univariateSolve(lp,info?,check?)} returns the same as
+ ++ \spad{univariateSolve(lp,info?,check?,false)}.
+ univariateSolve: (LP,B) -> List RUR
+ ++ \spad{univariateSolve(lp,info?)} returns the same as
+ ++ \spad{univariateSolve(lp,info?,false,false)}.
+ univariateSolve: LP -> List RUR
+ ++ \spad{univariateSolve(lp)} returns the same as
+ ++ \spad{univariateSolve(lp,false,false,false)}.
+ realSolve: RegularChain(R,ls) -> List REALSOL
+ ++ \spad{realSolve(ts)} returns the set of the points in the regular
+ ++ zero set of \spad{ts} whose coordinates are all real.
+ ++ WARNING: For each set of coordinates given by \spad{realSolve(ts)}
+ ++ the ordering of the indeterminates is reversed w.r.t. \spad{ls}.
+ realSolve: (LP,B,B,B) -> List REALSOL
+ ++ \spad{realSolve(ts,info?,check?,lextri?)} returns the set of the points
+ ++ in the variety associated with \spad{lp} whose coordinates are all real.
+ ++ Moreover, if \spad{info?} is \spad{true} then some information is
+ ++ displayed during decomposition into regular chains.
+ ++ If \spad{check?} is \spad{true} then the result is checked.
+ ++ If \spad{lextri?} is \spad{true} then the lexTriangular algorithm is called
+ ++ from the \spadtype{LexTriangularPackage} constructor
+ ++ (see \axiomOpFrom{zeroSetSplit}{LexTriangularPackage}(lp,false)).
+ ++ Otherwise, the triangular decomposition is computed directly from the input
+ ++ system by using the \axiomOpFrom{zeroSetSplit}{RegularChain} from \spadtype{RegularChain}.
+ ++ WARNING: For each set of coordinates given by \spad{realSolve(ts,info?,check?,lextri?)}
+ ++ the ordering of the indeterminates is reversed w.r.t. \spad{ls}.
+ realSolve: (LP,B,B) -> List REALSOL
+ ++ \spad{realSolve(ts,info?,check?)} returns the same as \spad{realSolve(ts,info?,check?,false)}.
+ realSolve: (LP,B) -> List REALSOL
+ ++ \spad{realSolve(ts,info?)} returns the same as \spad{realSolve(ts,info?,false,false)}.
+ realSolve: LP -> List REALSOL
+ ++ \spad{realSolve(lp)} returns the same as \spad{realSolve(ts,false,false,false)}
+ positiveSolve: RegularChain(R,ls) -> List REALSOL
+ ++ \spad{positiveSolve(ts)} returns the points of the regular
+ ++ set of \spad{ts} with (real) strictly positive coordinates.
+ positiveSolve: (LP,B,B) -> List REALSOL
+ ++ \spad{positiveSolve(lp,info?,lextri?)} returns the set of the points
+ ++ in the variety associated with \spad{lp} whose coordinates are (real) strictly positive.
+ ++ Moreover, if \spad{info?} is \spad{true} then some information is
+ ++ displayed during decomposition into regular chains.
+ ++ If \spad{lextri?} is \spad{true} then the lexTriangular algorithm is called
+ ++ from the \spadtype{LexTriangularPackage} constructor
+ ++ (see \axiomOpFrom{zeroSetSplit}{LexTriangularPackage}(lp,false)).
+ ++ Otherwise, the triangular decomposition is computed directly from the input
+ ++ system by using the \axiomOpFrom{zeroSetSplit}{RegularChain} from \spadtype{RegularChain}.
+ ++ WARNING: For each set of coordinates given by \spad{positiveSolve(lp,info?,lextri?)}
+ ++ the ordering of the indeterminates is reversed w.r.t. \spad{ls}.
+ positiveSolve: (LP,B) -> List REALSOL
+ ++ \spad{positiveSolve(lp)} returns the same as \spad{positiveSolve(lp,info?,false)}.
+ positiveSolve: LP -> List REALSOL
+ ++ \spad{positiveSolve(lp)} returns the same as \spad{positiveSolve(lp,false,false)}.
+ squareFree: (TS) -> List ST
+ ++ \spad{squareFree(ts)} returns the square-free factorization of \spad{ts}.
+ ++ Moreover, each factor is a Lazard triangular set and the decomposition
+ ++ is a Kalkbrener split of \spad{ts}, which is enough here for
+ ++ the matter of solving zero-dimensional algebraic systems.
+ ++ WARNING: \spad{ts} is not checked to be zero-dimensional.
+ convert: Q -> Q2
+ ++ \spad{convert(q)} converts \spad{q}.
+ convert: P -> PRC
+ ++ \spad{convert(p)} converts \spad{p}.
+ convert: Q2 -> PRC
+ ++ \spad{convert(q)} converts \spad{q}.
+ convert: U -> URC
+ ++ \spad{convert(u)} converts \spad{u}.
+ convert: ST -> List Q2
+ ++ \spad{convert(st)} returns the members of \spad{st}.
+
+ Implementation == add
+ news: Symbol := last(ls2)$(List Symbol)
+ newv: V2 := (variable(news)$V2)::V2
+ newq: Q2 := newv :: Q2
+
+ convert(q:Q):Q2 ==
+ ground? q => (ground(q))::Q2
+ q2: Q2 := 0
+ while not ground?(q) repeat
+ v: V := mvar(q)
+ d: N := mdeg(q)
+ v2: V2 := (variable(convert(v)@Symbol)$V2)::V2
+ iq2: Q2 := convert(init(q))@Q2
+ lq2: Q2 := (v2 :: Q2)
+ lq2 := lq2 ** d
+ q2 := iq2 * lq2 + q2
+ q := tail(q)
+ q2 + (ground(q))::Q2
+
+ squareFree(ts:TS):List(ST) ==
+ irred?: Boolean := false
+ st: ST := [[newq]$(List Q2)]
+ lq: List(Q2) := [convert(p)@Q2 for p in parts(ts)]
+ lq := sort(infRittWu?,lq)
+ toSee: List LQ2WT := []
+ if irred?
+ then
+ lf := irreducibleFactors([first lq])$polsetpack
+ lq := rest lq
+ for f in lf repeat
+ toSee := cons([cons(f,lq),st]$LQ2WT, toSee)
+ else
+ toSee := [[lq,st]$LQ2WT]
+ toSave: List ST := []
+ while not empty? toSee repeat
+ lqwt := first toSee; toSee := rest toSee
+ lq := lqwt.val; st := lqwt.tower
+ empty? lq =>
+ toSave := cons(st,toSave)
+ q := first lq; lq := rest lq
+ lsfqwt: List Q2WT := squareFreePart(q,st)$ST
+ for sfqwt in lsfqwt repeat
+ q := sfqwt.val; st := sfqwt.tower
+ if not ground? init(q)
+ then
+ q := normalizedAssociate(q,st)$normpack
+ newts := internalAugment(q,st)$ST
+ newlq := [remainder(q,newts).polnum for q in lq]
+ toSee := cons([newlq,newts]$LQ2WT,toSee)
+ toSave
+
+
+ triangSolve(lp: LP, info?: B, lextri?: B): List TS ==
+ lq: List(Q) := [convert(p)$Q for p in lp]
+ lextri? => zeroSetSplit(lq,false)$lextripack
+ zeroSetSplit(lq,true,info?)$TS
+
+ triangSolve(lp: LP, info?: B): List TS == triangSolve(lp,info?,false)
+
+ triangSolve(lp: LP): List TS == triangSolve(lp,false)
+
+ convert(u: U): URC ==
+ zero? u => 0
+ ground? u => ((ground(u) :: K)::RC)::URC
+ uu: URC := 0
+ while not ground? u repeat
+ uu := monomial((leadingCoefficient(u) :: K):: RC,degree(u)) + uu
+ u := reductum u
+ uu + ((ground(u) :: K)::RC)::URC
+
+ coerceFromRtoRC(r:R): RC ==
+ (r::K)::RC
+
+ convert(p:P): PRC ==
+ map(coerceFromRtoRC,p)$PolynomialFunctions2(R,RC)
+
+ convert(q2:Q2): PRC ==
+ p: P := coerce(q2)$Q2
+ convert(p)@PRC
+
+ convert(sts:ST): List Q2 ==
+ lq2: List(Q2) := parts(sts)$ST
+ lq2 := sort(infRittWu?,lq2)
+ rest(lq2)
+
+ realSolve(ts: TS): List REALSOL ==
+ lsts: List ST := squareFree(ts)
+ lr: REALSOL := []
+ lv: List Symbol := []
+ toSee := [[lr,lv,convert(sts)@(List Q2)]$WIP for sts in lsts]
+ toSave: List REALSOL := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ lr := wip.reals; lv := wip.vars; lq2 := wip.pols
+ (empty? lq2) and (not empty? lr) =>
+ toSave := cons(reverse(lr),toSave)
+ q2 := first lq2; lq2 := rest lq2
+ qrc := convert(q2)@PRC
+ if not empty? lr
+ then
+ for r in reverse(lr) for v in reverse(lv) repeat
+ qrc := eval(qrc,v,r)
+ lv := cons((mainVariable(qrc) :: Symbol),lv)
+ urc: URC := univariate(qrc)@URC
+ urcRoots := allRootsOf(urc)$RC
+ for urcRoot in urcRoots repeat
+ toSee := cons([cons(urcRoot,lr),lv,lq2]$WIP, toSee)
+ toSave
+
+ realSolve(lp: List(P), info?:Boolean, check?:Boolean, lextri?: Boolean): List REALSOL ==
+ lts: List TS
+ lq: List(Q) := [convert(p)$Q for p in lp]
+ if lextri?
+ then
+ lts := zeroSetSplit(lq,false)$lextripack
+ else
+ lts := zeroSetSplit(lq,true,info?)$TS
+ lsts: List ST := []
+ for ts in lts repeat
+ lsts := concat(squareFree(ts), lsts)
+ lsts := removeSuperfluousQuasiComponents(lsts)$quasicomppack
+ lr: REALSOL := []
+ lv: List Symbol := []
+ toSee := [[lr,lv,convert(sts)@(List Q2)]$WIP for sts in lsts]
+ toSave: List REALSOL := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ lr := wip.reals; lv := wip.vars; lq2 := wip.pols
+ (empty? lq2) and (not empty? lr) =>
+ toSave := cons(reverse(lr),toSave)
+ q2 := first lq2; lq2 := rest lq2
+ qrc := convert(q2)@PRC
+ if not empty? lr
+ then
+ for r in reverse(lr) for v in reverse(lv) repeat
+ qrc := eval(qrc,v,r)
+ lv := cons((mainVariable(qrc) :: Symbol),lv)
+ urc: URC := univariate(qrc)@URC
+ urcRoots := allRootsOf(urc)$RC
+ for urcRoot in urcRoots repeat
+ toSee := cons([cons(urcRoot,lr),lv,lq2]$WIP, toSee)
+ if check?
+ then
+ for p in lp repeat
+ for realsol in toSave repeat
+ prc: PRC := convert(p)@PRC
+ for rr in realsol for symb in reverse(ls) repeat
+ prc := eval(prc,symb,rr)
+ not zero? prc =>
+ error "realSolve$ZDSOLVE: bad result"
+ toSave
+
+ realSolve(lp: List(P), info?:Boolean, check?:Boolean): List REALSOL ==
+ realSolve(lp,info?,check?,false)
+
+ realSolve(lp: List(P), info?:Boolean): List REALSOL ==
+ realSolve(lp,info?,false,false)
+
+ realSolve(lp: List(P)): List REALSOL ==
+ realSolve(lp,false,false,false)
+
+ positiveSolve(ts: TS): List REALSOL ==
+ lsts: List ST := squareFree(ts)
+ lr: REALSOL := []
+ lv: List Symbol := []
+ toSee := [[lr,lv,convert(sts)@(List Q2)]$WIP for sts in lsts]
+ toSave: List REALSOL := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ lr := wip.reals; lv := wip.vars; lq2 := wip.pols
+ (empty? lq2) and (not empty? lr) =>
+ toSave := cons(reverse(lr),toSave)
+ q2 := first lq2; lq2 := rest lq2
+ qrc := convert(q2)@PRC
+ if not empty? lr
+ then
+ for r in reverse(lr) for v in reverse(lv) repeat
+ qrc := eval(qrc,v,r)
+ lv := cons((mainVariable(qrc) :: Symbol),lv)
+ urc: URC := univariate(qrc)@URC
+ urcRoots := allRootsOf(urc)$RC
+ for urcRoot in urcRoots repeat
+ if positive? urcRoot
+ then
+ toSee := cons([cons(urcRoot,lr),lv,lq2]$WIP, toSee)
+ toSave
+
+ positiveSolve(lp: List(P), info?:Boolean, lextri?: Boolean): List REALSOL ==
+ lts: List TS
+ lq: List(Q) := [convert(p)$Q for p in lp]
+ if lextri?
+ then
+ lts := zeroSetSplit(lq,false)$lextripack
+ else
+ lts := zeroSetSplit(lq,true,info?)$TS
+ lsts: List ST := []
+ for ts in lts repeat
+ lsts := concat(squareFree(ts), lsts)
+ lsts := removeSuperfluousQuasiComponents(lsts)$quasicomppack
+ lr: REALSOL := []
+ lv: List Symbol := []
+ toSee := [[lr,lv,convert(sts)@(List Q2)]$WIP for sts in lsts]
+ toSave: List REALSOL := []
+ while not empty? toSee repeat
+ wip := first toSee; toSee := rest toSee
+ lr := wip.reals; lv := wip.vars; lq2 := wip.pols
+ (empty? lq2) and (not empty? lr) =>
+ toSave := cons(reverse(lr),toSave)
+ q2 := first lq2; lq2 := rest lq2
+ qrc := convert(q2)@PRC
+ if not empty? lr
+ then
+ for r in reverse(lr) for v in reverse(lv) repeat
+ qrc := eval(qrc,v,r)
+ lv := cons((mainVariable(qrc) :: Symbol),lv)
+ urc: URC := univariate(qrc)@URC
+ urcRoots := allRootsOf(urc)$RC
+ for urcRoot in urcRoots repeat
+ if positive? urcRoot
+ then
+ toSee := cons([cons(urcRoot,lr),lv,lq2]$WIP, toSee)
+ toSave
+
+ positiveSolve(lp: List(P), info?:Boolean): List REALSOL ==
+ positiveSolve(lp, info?, false)
+
+ positiveSolve(lp: List(P)): List REALSOL ==
+ positiveSolve(lp, false, false)
+
+ univariateSolve(ts: TS): List RUR ==
+ toSee: List ST := squareFree(ts)
+ toSave: List RUR := []
+ for st in toSee repeat
+ lus: List ST := rur(st,true)$rurpack
+ for us in lus repeat
+ g: U := univariate(select(us,newv)::Q2)$Q2
+ lc: LP := [convert(q2)@P for q2 in parts(collectUpper(us,newv)$ST)$ST]
+ toSave := cons([g,lc]$RUR, toSave)
+ toSave
+
+ univariateSolve(lp: List(P), info?:Boolean, check?:Boolean, lextri?: Boolean): List RUR ==
+ lts: List TS
+ lq: List(Q) := [convert(p)$Q for p in lp]
+ if lextri?
+ then
+ lts := zeroSetSplit(lq,false)$lextripack
+ else
+ lts := zeroSetSplit(lq,true,info?)$TS
+ toSee: List ST := []
+ for ts in lts repeat
+ toSee := concat(squareFree(ts), toSee)
+ toSee := removeSuperfluousQuasiComponents(toSee)$quasicomppack
+ toSave: List RUR := []
+ if check?
+ then
+ lq2: List(Q2) := [convert(p)$Q2 for p in lp]
+ for st in toSee repeat
+ lus: List ST := rur(st,true)$rurpack
+ for us in lus repeat
+ if check?
+ then
+ rems: List(Q2) := [removeZero(q2,us)$ST for q2 in lq2]
+ not every?(zero?,rems) =>
+ output(st::OutputForm)$OutputPackage
+ output("Has a bad RUR component:")$OutputPackage
+ output(us::OutputForm)$OutputPackage
+ error "univariateSolve$ZDSOLVE: bad RUR"
+ g: U := univariate(select(us,newv)::Q2)$Q2
+ lc: LP := [convert(q2)@P for q2 in parts(collectUpper(us,newv)$ST)$ST]
+ toSave := cons([g,lc]$RUR, toSave)
+ toSave
+
+ univariateSolve(lp: List(P), info?:Boolean, check?:Boolean): List RUR ==
+ univariateSolve(lp,info?,check?,false)
+
+ univariateSolve(lp: List(P), info?:Boolean): List RUR ==
+ univariateSolve(lp,info?,false,false)
+
+ univariateSolve(lp: List(P)): List RUR ==
+ univariateSolve(lp,false,false,false)
+
+@
+\section{License}
+<<license>>=
+--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+--All rights reserved.
+--
+--Redistribution and use in source and binary forms, with or without
+--modification, are permitted provided that the following conditions are
+--met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@
+<<*>>=
+<<license>>
+
+<<package FGLMICPK FGLMIfCanPackage>>
+<<domain RGCHAIN RegularChain>>
+<<package LEXTRIPK LexTriangularPackage>>
+<<package IRURPK InternalRationalUnivariateRepresentationPackage>>
+<<package RURPK RationalUnivariateRepresentationPackage>>
+<<package ZDSOLVE ZeroDimensionalSolvePackage>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}