diff options
author | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
commit | ab8cc85adde879fb963c94d15675783f2cf4b183 (patch) | |
tree | c202482327f474583b750b2c45dedfc4e4312b1d /src/algebra/sregset.spad.pamphlet | |
download | open-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz |
Initial population.
Diffstat (limited to 'src/algebra/sregset.spad.pamphlet')
-rw-r--r-- | src/algebra/sregset.spad.pamphlet | 1606 |
1 files changed, 1606 insertions, 0 deletions
diff --git a/src/algebra/sregset.spad.pamphlet b/src/algebra/sregset.spad.pamphlet new file mode 100644 index 00000000..19886881 --- /dev/null +++ b/src/algebra/sregset.spad.pamphlet @@ -0,0 +1,1606 @@ +\documentclass{article} +\usepackage{axiom} +\begin{document} +\title{\$SPAD/src/algebra sregset.spad} +\author{Marc Moreno Maza} +\maketitle +\begin{abstract} +\end{abstract} +\eject +\tableofcontents +\eject +\section{category SFRTCAT SquareFreeRegularTriangularSetCategory} +<<category SFRTCAT SquareFreeRegularTriangularSetCategory>>= +)abbrev category SFRTCAT SquareFreeRegularTriangularSetCategory +++ Author: Marc Moreno Maza +++ Date Created: 09/03/1996 +++ Date Last Updated: 09/10/1998 +++ Basic Functions: +++ Related Constructors: +++ Also See: essai Graphisme +++ AMS Classifications: +++ Keywords: polynomial, multivariate, ordered variables set +++ Description: +++ The category of square-free regular triangular sets. +++ A regular triangular set \spad{ts} is square-free if +++ the gcd of any polynomial \spad{p} in \spad{ts} and +++ \spad{differentiate(p,mvar(p))} w.r.t. +++ \axiomOpFrom{collectUnder}{TriangularSetCategory}(ts,\axiomOpFrom{mvar}{RecursivePolynomialCategory}(p)) +++ has degree zero w.r.t. \spad{mvar(p)}. Thus any square-free regular +++ set defines a tower of square-free simple extensions.\newline +++ References : +++ [1] D. LAZARD "A new method for solving algebraic systems of +++ positive dimension" Discr. App. Math. 33:147-160,1991 +++ [2] M. KALKBRENER "Algorithmic properties of polynomial rings" +++ Habilitation Thesis, ETZH, Zurich, 1995. +++ [3] M. MORENO MAZA "A new algorithm for computing triangular +++ decomposition of algebraic varieties" NAG Tech. Rep. 4/98. + + + +SquareFreeRegularTriangularSetCategory(R:GcdDomain,E:OrderedAbelianMonoidSup,_ + V:OrderedSet,P:RecursivePolynomialCategory(R,E,V)): + Category == + RegularTriangularSetCategory(R,E,V,P) + +@ +\section{package SFQCMPK SquareFreeQuasiComponentPackage} +<<package SFQCMPK SquareFreeQuasiComponentPackage>>= +)abbrev package SFQCMPK SquareFreeQuasiComponentPackage +++ Author: Marc Moreno Maza +++ Date Created: 09/23/1998 +++ Date Last Updated: 12/16/1998 +++ Basic Functions: +++ Related Constructors: +++ Also See: +++ AMS Classifications: +++ Keywords: +++ Description: +++ A internal package for removing redundant quasi-components and redundant +++ branches when decomposing a variety by means of quasi-components +++ of regular triangular sets. \newline +++ References : +++ [1] D. LAZARD "A new method for solving algebraic systems of +++ positive dimension" Discr. App. Math. 33:147-160,1991 +++ Tech. Report (PoSSo project) +++ [2] M. MORENO MAZA "Calculs de pgcd au-dessus des tours +++ d'extensions simples et resolution des systemes d'equations +++ algebriques" These, Universite P.etM. Curie, Paris, 1997. +++ [3] M. MORENO MAZA "A new algorithm for computing triangular +++ decomposition of algebraic varieties" NAG Tech. Rep. 4/98. +++ Version: 1. + +SquareFreeQuasiComponentPackage(R,E,V,P,TS): Exports == Implementation where + + R : GcdDomain + E : OrderedAbelianMonoidSup + V : OrderedSet + P : RecursivePolynomialCategory(R,E,V) + TS : RegularTriangularSetCategory(R,E,V,P) + N ==> NonNegativeInteger + Z ==> Integer + B ==> Boolean + S ==> String + LP ==> List P + PtoP ==> P -> P + PS ==> GeneralPolynomialSet(R,E,V,P) + PWT ==> Record(val : P, tower : TS) + BWT ==> Record(val : Boolean, tower : TS) + LpWT ==> Record(val : (List P), tower : TS) + Branch ==> Record(eq: List P, tower: TS, ineq: List P) + UBF ==> Union(Branch,"failed") + Split ==> List TS + Key ==> Record(left:TS, right:TS) + Entry ==> Boolean + H ==> TabulatedComputationPackage(Key, Entry) + polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P) + SQUAREFREE ==> SquareFreeRegularTriangularSetCategory(R,E,V,P) + + Exports == with + startTable!: (S,S,S) -> Void + ++ \axiom{startTableGcd!(s1,s2,s3)} + ++ is an internal subroutine, exported only for developement. + stopTable!: () -> Void + ++ \axiom{stopTableGcd!()} + ++ is an internal subroutine, exported only for developement. + supDimElseRittWu?: (TS,TS) -> Boolean + ++ \axiom{supDimElseRittWu(ts,us)} returns true iff \axiom{ts} + ++ has less elements than \axiom{us} otherwise if \axiom{ts} + ++ has higher rank than \axiom{us} w.r.t. Riit and Wu ordering. + algebraicSort: Split -> Split + ++ \axiom{algebraicSort(lts)} sorts \axiom{lts} w.r.t + ++ \axiomOpFrom{supDimElseRittWu}{QuasiComponentPackage}. + moreAlgebraic?: (TS,TS) -> Boolean + ++ \axiom{moreAlgebraic?(ts,us)} returns false iff \axiom{ts} + ++ and \axiom{us} are both empty, or \axiom{ts} + ++ has less elements than \axiom{us}, or some variable is + ++ algebraic w.r.t. \axiom{us} and is not w.r.t. \axiom{ts}. + subTriSet?: (TS,TS) -> Boolean + ++ \axiom{subTriSet?(ts,us)} returns true iff \axiom{ts} is + ++ a sub-set of \axiom{us}. + subPolSet?: (LP, LP) -> Boolean + ++ \axiom{subPolSet?(lp1,lp2)} returns true iff \axiom{lp1} is + ++ a sub-set of \axiom{lp2}. + internalSubPolSet?: (LP, LP) -> Boolean + ++ \axiom{internalSubPolSet?(lp1,lp2)} returns true iff \axiom{lp1} is + ++ a sub-set of \axiom{lp2} assuming that these lists are sorted + ++ increasingly w.r.t. \axiomOpFrom{infRittWu?}{RecursivePolynomialCategory}. + internalInfRittWu?: (LP, LP) -> Boolean + ++ \axiom{internalInfRittWu?(lp1,lp2)} + ++ is an internal subroutine, exported only for developement. + infRittWu?: (LP, LP) -> Boolean + ++ \axiom{infRittWu?(lp1,lp2)} + ++ is an internal subroutine, exported only for developement. + internalSubQuasiComponent?: (TS,TS) -> Union(Boolean,"failed") + ++ \axiom{internalSubQuasiComponent?(ts,us)} returns a boolean \spad{b} value + ++ if the fact the regular zero set of \axiom{us} contains that of + ++ \axiom{ts} can be decided (and in that case \axiom{b} gives this + ++ inclusion) otherwise returns \axiom{"failed"}. + subQuasiComponent?: (TS,TS) -> Boolean + ++ \axiom{subQuasiComponent?(ts,us)} returns true iff + ++ \axiomOpFrom{internalSubQuasiComponent?(ts,us)}{QuasiComponentPackage} + ++ returs true. + subQuasiComponent?: (TS,Split) -> Boolean + ++ \axiom{subQuasiComponent?(ts,lus)} returns true iff + ++ \axiom{subQuasiComponent?(ts,us)} holds for one \spad{us} in \spad{lus}. + removeSuperfluousQuasiComponents: Split -> Split + ++ \axiom{removeSuperfluousQuasiComponents(lts)} removes from \axiom{lts} + ++ any \spad{ts} such that \axiom{subQuasiComponent?(ts,us)} holds for + ++ another \spad{us} in \axiom{lts}. + subCase?: (LpWT,LpWT) -> Boolean + ++ \axiom{subCase?(lpwt1,lpwt2)} + ++ is an internal subroutine, exported only for developement. + removeSuperfluousCases: List LpWT -> List LpWT + ++ \axiom{removeSuperfluousCases(llpwt)} + ++ is an internal subroutine, exported only for developement. + prepareDecompose: (LP, List(TS),B,B) -> List Branch + ++ \axiom{prepareDecompose(lp,lts,b1,b2)} + ++ is an internal subroutine, exported only for developement. + branchIfCan: (LP,TS,LP,B,B,B,B,B) -> Union(Branch,"failed") + ++ \axiom{branchIfCan(leq,ts,lineq,b1,b2,b3,b4,b5)} + ++ is an internal subroutine, exported only for developement. + + Implementation == add + + squareFreeFactors(lp: LP): LP == + lsflp: LP := [] + for p in lp repeat + lsfp := squareFreeFactors(p)$polsetpack + lsflp := concat(lsfp,lsflp) + sort(infRittWu?,removeDuplicates lsflp) + + startTable!(ok: S, ko: S, domainName: S): Void == + initTable!()$H + if (not empty? ok) and (not empty? ko) then printInfo!(ok,ko)$H + if (not empty? domainName) then startStats!(domainName)$H + void() + + stopTable!(): Void == + if makingStats?()$H then printStats!()$H + clearTable!()$H + + supDimElseRittWu? (ts:TS,us:TS): Boolean == + #ts < #us => true + #ts > #us => false + lp1 :LP := members(ts) + lp2 :LP := members(us) + while (not empty? lp1) and (not infRittWu?(first(lp2),first(lp1))) repeat + lp1 := rest lp1 + lp2 := rest lp2 + not empty? lp1 + + algebraicSort (lts:Split): Split == + lts := removeDuplicates lts + sort(supDimElseRittWu?,lts) + + moreAlgebraic?(ts:TS,us:TS): Boolean == + empty? ts => empty? us + empty? us => true + #ts < #us => false + for p in (members us) repeat + not algebraic?(mvar(p),ts) => return false + true + + subTriSet?(ts:TS,us:TS): Boolean == + empty? ts => true + empty? us => false + mvar(ts) > mvar(us) => false + mvar(ts) < mvar(us) => subTriSet?(ts,rest(us)::TS) + first(ts)::P = first(us)::P => subTriSet?(rest(ts)::TS,rest(us)::TS) + false + + internalSubPolSet?(lp1: LP, lp2: LP): Boolean == + empty? lp1 => true + empty? lp2 => false + associates?(first lp1, first lp2) => + internalSubPolSet?(rest lp1, rest lp2) + infRittWu?(first lp1, first lp2) => false + internalSubPolSet?(lp1, rest lp2) + + subPolSet?(lp1: LP, lp2: LP): Boolean == + lp1 := sort(infRittWu?, lp1) + lp2 := sort(infRittWu?, lp2) + internalSubPolSet?(lp1,lp2) + + infRittWu?(lp1: LP, lp2: LP): Boolean == + lp1 := sort(infRittWu?, lp1) + lp2 := sort(infRittWu?, lp2) + internalInfRittWu?(lp1,lp2) + + internalInfRittWu?(lp1: LP, lp2: LP): Boolean == + empty? lp1 => not empty? lp2 + empty? lp2 => false + infRittWu?(first lp1, first lp2)$P => true + infRittWu?(first lp2, first lp1)$P => false + infRittWu?(rest lp1, rest lp2)$$ + + subCase? (lpwt1:LpWT,lpwt2:LpWT): Boolean == + -- ASSUME lpwt.{1,2}.val is sorted w.r.t. infRittWu? + not internalSubPolSet?(lpwt2.val, lpwt1.val) => false + subQuasiComponent?(lpwt1.tower,lpwt2.tower) + + if TS has SquareFreeRegularTriangularSetCategory(R,E,V,P) + then + + internalSubQuasiComponent?(ts:TS,us:TS): Union(Boolean,"failed") == + subTriSet?(us,ts) => true + not moreAlgebraic?(ts,us) => false::Union(Boolean,"failed") + for p in (members us) repeat + mdeg(p) < mdeg(select(ts,mvar(p))::P) => + return("failed"::Union(Boolean,"failed")) + for p in (members us) repeat + not zero? initiallyReduce(p,ts) => + return("failed"::Union(Boolean,"failed")) + lsfp := squareFreeFactors(initials us) + for p in lsfp repeat + b: B := invertible?(p,ts)$TS + not b => + return(false::Union(Boolean,"failed")) + true::Union(Boolean,"failed") + + else + + internalSubQuasiComponent?(ts:TS,us:TS): Union(Boolean,"failed") == + subTriSet?(us,ts) => true + not moreAlgebraic?(ts,us) => false::Union(Boolean,"failed") + for p in (members us) repeat + mdeg(p) < mdeg(select(ts,mvar(p))::P) => + return("failed"::Union(Boolean,"failed")) + for p in (members us) repeat + not zero? reduceByQuasiMonic(p,ts) => + return("failed"::Union(Boolean,"failed")) + true::Union(Boolean,"failed") + + subQuasiComponent?(ts:TS,us:TS): Boolean == + k: Key := [ts, us] + e := extractIfCan(k)$H + e case Entry => e::Entry + ubf: Union(Boolean,"failed") := internalSubQuasiComponent?(ts,us) + b: Boolean := (ubf case Boolean) and (ubf::Boolean) + insert!(k,b)$H + b + + subQuasiComponent?(ts:TS,lus:Split): Boolean == + for us in lus repeat + subQuasiComponent?(ts,us)@B => return true + false + + removeSuperfluousCases (cases:List LpWT) == + #cases < 2 => cases + toSee := sort(supDimElseRittWu?(#1.tower,#2.tower),cases) + lpwt1,lpwt2 : LpWT + toSave,headmaxcases,maxcases,copymaxcases : List LpWT + while not empty? toSee repeat + lpwt1 := first toSee + toSee := rest toSee + toSave := [] + for lpwt2 in toSee repeat + if subCase?(lpwt1,lpwt2) + then + lpwt1 := lpwt2 + else + if not subCase?(lpwt2,lpwt1) + then + toSave := cons(lpwt2,toSave) + if empty? maxcases + then + headmaxcases := [lpwt1] + maxcases := headmaxcases + else + copymaxcases := maxcases + while (not empty? copymaxcases) and _ + (not subCase?(lpwt1,first(copymaxcases))) repeat + copymaxcases := rest copymaxcases + if empty? copymaxcases + then + setrest!(headmaxcases,[lpwt1]) + headmaxcases := rest headmaxcases + toSee := reverse toSave + maxcases + + removeSuperfluousQuasiComponents(lts: Split): Split == + lts := removeDuplicates lts + #lts < 2 => lts + toSee := algebraicSort lts + toSave,headmaxlts,maxlts,copymaxlts : Split + while not empty? toSee repeat + ts := first toSee + toSee := rest toSee + toSave := [] + for us in toSee repeat + if subQuasiComponent?(ts,us)@B + then + ts := us + else + if not subQuasiComponent?(us,ts)@B + then + toSave := cons(us,toSave) + if empty? maxlts + then + headmaxlts := [ts] + maxlts := headmaxlts + else + copymaxlts := maxlts + while (not empty? copymaxlts) and _ + (not subQuasiComponent?(ts,first(copymaxlts))@B) repeat + copymaxlts := rest copymaxlts + if empty? copymaxlts + then + setrest!(headmaxlts,[ts]) + headmaxlts := rest headmaxlts + toSee := reverse toSave + algebraicSort maxlts + + removeAssociates (lp:LP):LP == + removeDuplicates [primitivePart(p) for p in lp] + + branchIfCan(leq: LP,ts: TS,lineq: LP, b1:B,b2:B,b3:B,b4:B,b5:B):UBF == + -- ASSUME pols in leq are squarefree and mainly primitive + -- if b1 then CLEAN UP leq + -- if b2 then CLEAN UP lineq + -- if b3 then SEARCH for ZERO in lineq with leq + -- if b4 then SEARCH for ZERO in lineq with ts + -- if b5 then SEARCH for ONE in leq with lineq + if b1 + then + leq := removeAssociates(leq) + leq := remove(zero?,leq) + any?(ground?,leq) => + return("failed"::Union(Branch,"failed")) + if b2 + then + any?(zero?,lineq) => + return("failed"::Union(Branch,"failed")) + lineq := removeRedundantFactors(lineq)$polsetpack + if b3 + then + ps: PS := construct(leq)$PS + for q in lineq repeat + zero? remainder(q,ps).polnum => + return("failed"::Union(Branch,"failed")) + (empty? leq) or (empty? lineq) => ([leq, ts, lineq]$Branch)::UBF + if b4 + then + for q in lineq repeat + zero? initiallyReduce(q,ts) => + return("failed"::Union(Branch,"failed")) + if b5 + then + newleq: LP := [] + for p in leq repeat + for q in lineq repeat + if mvar(p) = mvar(q) + then + g := gcd(p,q) + newp := (p exquo g)::P + ground? newp => + return("failed"::Union(Branch,"failed")) + newleq := cons(newp,newleq) + else + newleq := cons(p,newleq) + leq := newleq + leq := sort(infRittWu?, removeDuplicates leq) + ([leq, ts, lineq]$Branch)::UBF + + prepareDecompose(lp: LP, lts: List(TS), b1: B, b2: B): List Branch == + -- if b1 then REMOVE REDUNDANT COMPONENTS in lts + -- if b2 then SPLIT the input system with squareFree + lp := sort(infRittWu?, remove(zero?,removeAssociates(lp))) + any?(ground?,lp) => [] + empty? lts => [] + if b1 then lts := removeSuperfluousQuasiComponents lts + not b2 => + [[lp,ts,squareFreeFactors(initials ts)]$Branch for ts in lts] + toSee: List Branch + lq: LP := [] + toSee := [[lq,ts,squareFreeFactors(initials ts)]$Branch for ts in lts] + empty? lp => toSee + for p in lp repeat + lsfp := squareFreeFactors(p)$polsetpack + branches: List Branch := [] + lq := [] + for f in lsfp repeat + for branch in toSee repeat + leq : LP := branch.eq + ts := branch.tower + lineq : LP := branch.ineq + ubf1: UBF := branchIfCan(leq,ts,lq,false,false,true,true,true)@UBF + ubf1 case "failed" => "leave" + ubf2: UBF := branchIfCan([f],ts,lineq,false,false,true,true,true)@UBF + ubf2 case "failed" => "leave" + leq := sort(infRittWu?,removeDuplicates concat(ubf1.eq,ubf2.eq)) + lineq := sort(infRittWu?,removeDuplicates concat(ubf1.ineq,ubf2.ineq)) + newBranch := branchIfCan(leq,ts,lineq,false,false,false,false,false) + branches:= cons(newBranch::Branch,branches) + lq := cons(f,lq) + toSee := branches + sort(supDimElseRittWu?(#1.tower,#2.tower),toSee) + +@ +\section{package SFRGCD SquareFreeRegularTriangularSetGcdPackage} +<<package SFRGCD SquareFreeRegularTriangularSetGcdPackage>>= +)abbrev package SFRGCD SquareFreeRegularTriangularSetGcdPackage +++ Author: Marc Moreno Maza +++ Date Created: 09/23/1998 +++ Date Last Updated: 10/01/1998 +++ Basic Functions: +++ Related Constructors: +++ Also See: +++ AMS Classifications: +++ Keywords: +++ Description: +++ A internal package for computing gcds and resultants of univariate polynomials +++ with coefficients in a tower of simple extensions of a field. +++ There is no need to use directly this package since its main operations are +++ available from \spad{TS}. \newline +++ References : +++ [1] M. MORENO MAZA and R. RIOBOO "Computations of gcd over +++ algebraic towers of simple extensions" In proceedings of AAECC11 +++ Paris, 1995. +++ [2] M. MORENO MAZA "Calculs de pgcd au-dessus des tours +++ d'extensions simples et resolution des systemes d'equations +++ algebriques" These, Universite P.etM. Curie, Paris, 1997. +++ [3] M. MORENO MAZA "A new algorithm for computing triangular +++ decomposition of algebraic varieties" NAG Tech. Rep. 4/98. +++ Version: 1. + +SquareFreeRegularTriangularSetGcdPackage(R,E,V,P,TS): Exports == Implementation where + + R : GcdDomain + E : OrderedAbelianMonoidSup + V : OrderedSet + P : RecursivePolynomialCategory(R,E,V) + TS : RegularTriangularSetCategory(R,E,V,P) + N ==> NonNegativeInteger + Z ==> Integer + B ==> Boolean + S ==> String + LP ==> List P + PtoP ==> P -> P + PS ==> GeneralPolynomialSet(R,E,V,P) + PWT ==> Record(val : P, tower : TS) + BWT ==> Record(val : Boolean, tower : TS) + LpWT ==> Record(val : (List P), tower : TS) + Branch ==> Record(eq: List P, tower: TS, ineq: List P) + UBF ==> Union(Branch,"failed") + Split ==> List TS + KeyGcd ==> Record(arg1: P, arg2: P, arg3: TS, arg4: B) + EntryGcd ==> List PWT + HGcd ==> TabulatedComputationPackage(KeyGcd, EntryGcd) + KeyInvSet ==> Record(arg1: P, arg3: TS) + EntryInvSet ==> List TS + HInvSet ==> TabulatedComputationPackage(KeyInvSet, EntryInvSet) + iprintpack ==> InternalPrintPackage() + polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P) + quasicomppack ==> SquareFreeQuasiComponentPackage(R,E,V,P,TS) + + SQUAREFREE ==> SquareFreeRegularTriangularSetCategory(R,E,V,P) + + Exports == with + startTableGcd!: (S,S,S) -> Void + stopTableGcd!: () -> Void + startTableInvSet!: (S,S,S) -> Void + stopTableInvSet!: () -> Void + stosePrepareSubResAlgo: (P,P,TS) -> List LpWT + stoseInternalLastSubResultant: (P,P,TS,B,B) -> List PWT + stoseInternalLastSubResultant: (List LpWT,V,B) -> List PWT + stoseIntegralLastSubResultant: (P,P,TS) -> List PWT + stoseLastSubResultant: (P,P,TS) -> List PWT + stoseInvertible?: (P,TS) -> B + stoseInvertible?_sqfreg: (P,TS) -> List BWT + stoseInvertibleSet_sqfreg: (P,TS) -> Split + stoseInvertible?_reg: (P,TS) -> List BWT + stoseInvertibleSet_reg: (P,TS) -> Split + stoseInvertible?: (P,TS) -> List BWT + stoseInvertibleSet: (P,TS) -> Split + stoseSquareFreePart: (P,TS) -> List PWT + + Implementation == add + + startTableGcd!(ok: S, ko: S, domainName: S): Void == + initTable!()$HGcd + printInfo!(ok,ko)$HGcd + startStats!(domainName)$HGcd + void() + + stopTableGcd!(): Void == + if makingStats?()$HGcd then printStats!()$HGcd + clearTable!()$HGcd + + startTableInvSet!(ok: S, ko: S, domainName: S): Void == + initTable!()$HInvSet + printInfo!(ok,ko)$HInvSet + startStats!(domainName)$HInvSet + void() + + stopTableInvSet!(): Void == + if makingStats?()$HInvSet then printStats!()$HInvSet + clearTable!()$HInvSet + + stoseInvertible?(p:P,ts:TS): Boolean == + q := primitivePart initiallyReduce(p,ts) + zero? q => false + normalized?(q,ts) => true + v := mvar(q) + not algebraic?(v,ts) => + toCheck: List BWT := stoseInvertible?(p,ts)@(List BWT) + for bwt in toCheck repeat + bwt.val = false => return false + return true + ts_v := select(ts,v)::P + ts_v_- := collectUnder(ts,v) + lgwt := stoseInternalLastSubResultant(ts_v,q,ts_v_-,false,true) + for gwt in lgwt repeat + g := gwt.val; + (not ground? g) and (mvar(g) = v) => + return false + true + + stosePrepareSubResAlgo(p1:P,p2:P,ts:TS): List LpWT == + -- ASSUME mvar(p1) = mvar(p2) > mvar(ts) and mdeg(p1) >= mdeg(p2) + -- ASSUME init(p1) invertible modulo ts !!! + toSee: List LpWT := [[[p1,p2],ts]$LpWT] + toSave: List LpWT := [] + v := mvar(p1) + while (not empty? toSee) repeat + lpwt := first toSee; toSee := rest toSee + p1 := lpwt.val.1; p2 := lpwt.val.2 + ts := lpwt.tower + lbwt := stoseInvertible?(leadingCoefficient(p2,v),ts)@(List BWT) + for bwt in lbwt repeat + (bwt.val = true) and (degree(p2,v) > 0) => + p3 := prem(p1, -p2) + s: P := init(p2)**(mdeg(p1) - mdeg(p2))::N + toSave := cons([[p2,p3,s],bwt.tower]$LpWT,toSave) + -- p2 := initiallyReduce(p2,bwt.tower) + newp2 := primitivePart initiallyReduce(p2,bwt.tower) + (bwt.val = true) => + -- toSave := cons([[p2,0,1],bwt.tower]$LpWT,toSave) + toSave := cons([[p2,0,1],bwt.tower]$LpWT,toSave) + -- zero? p2 => + zero? newp2 => + toSave := cons([[p1,0,1],bwt.tower]$LpWT,toSave) + -- toSee := cons([[p1,p2],bwt.tower]$LpWT,toSee) + toSee := cons([[p1,newp2],bwt.tower]$LpWT,toSee) + toSave + + stoseIntegralLastSubResultant(p1:P,p2:P,ts:TS): List PWT == + -- ASSUME mvar(p1) = mvar(p2) > mvar(ts) and mdeg(p1) >= mdeg(p2) + -- ASSUME p1 and p2 have no algebraic coefficients + lsr := lastSubResultant(p1, p2) + ground?(lsr) => [[lsr,ts]$PWT] + mvar(lsr) < mvar(p1) => [[lsr,ts]$PWT] + gi1i2 := gcd(init(p1),init(p2)) + ex: Union(P,"failed") := (gi1i2 * lsr) exquo$P init(lsr) + ex case "failed" => [[lsr,ts]$PWT] + [[ex::P,ts]$PWT] + + stoseInternalLastSubResultant(p1:P,p2:P,ts:TS,b1:B,b2:B): List PWT == + -- ASSUME mvar(p1) = mvar(p2) > mvar(ts) and mdeg(p1) >= mdeg(p2) + -- if b1 ASSUME init(p2) invertible w.r.t. ts + -- if b2 BREAK with the first non-trivial gcd + k: KeyGcd := [p1,p2,ts,b2] + e := extractIfCan(k)$HGcd + e case EntryGcd => e::EntryGcd + toSave: List PWT + empty? ts => + toSave := stoseIntegralLastSubResultant(p1,p2,ts) + insert!(k,toSave)$HGcd + return toSave + toSee: List LpWT + if b1 + then + p3 := prem(p1, -p2) + s: P := init(p2)**(mdeg(p1) - mdeg(p2))::N + toSee := [[[p2,p3,s],ts]$LpWT] + else + toSee := stosePrepareSubResAlgo(p1,p2,ts) + toSave := stoseInternalLastSubResultant(toSee,mvar(p1),b2) + insert!(k,toSave)$HGcd + toSave + + stoseInternalLastSubResultant(llpwt: List LpWT,v:V,b2:B): List PWT == + toReturn: List PWT := []; toSee: List LpWT; + while (not empty? llpwt) repeat + toSee := llpwt; llpwt := [] + -- CONSIDER FIRST the vanishing current last subresultant + for lpwt in toSee repeat + p1 := lpwt.val.1; p2 := lpwt.val.2; s := lpwt.val.3; ts := lpwt.tower + lbwt := stoseInvertible?(leadingCoefficient(p2,v),ts)@(List BWT) + for bwt in lbwt repeat + bwt.val = false => + toReturn := cons([p1,bwt.tower]$PWT, toReturn) + b2 and positive?(degree(p1,v)) => return toReturn + llpwt := cons([[p1,p2,s],bwt.tower]$LpWT, llpwt) + empty? llpwt => "leave" + -- CONSIDER NOW the branches where the computations continue + toSee := llpwt; llpwt := [] + lpwt := first toSee; toSee := rest toSee + p1 := lpwt.val.1; p2 := lpwt.val.2; s := lpwt.val.3 + delta: N := (mdeg(p1) - degree(p2,v))::N + p3: P := LazardQuotient2(p2, leadingCoefficient(p2,v), s, delta) + zero?(degree(p3,v)) => + toReturn := cons([p3,lpwt.tower]$PWT, toReturn) + for lpwt in toSee repeat + toReturn := cons([p3,lpwt.tower]$PWT, toReturn) + (p1, p2) := (p3, next_subResultant2(p1, p2, p3, s)) + s := leadingCoefficient(p1,v) + llpwt := cons([[p1,p2,s],lpwt.tower]$LpWT, llpwt) + for lpwt in toSee repeat + llpwt := cons([[p1,p2,s],lpwt.tower]$LpWT, llpwt) + toReturn + + stoseLastSubResultant(p1:P,p2:P,ts:TS): List PWT == + ground? p1 => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #1" + ground? p2 => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #2" + not (mvar(p2) = mvar(p1)) => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #2" + algebraic?(mvar(p1),ts) => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #1" + not initiallyReduced?(p1,ts) => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #1" + not initiallyReduced?(p2,ts) => + error"in stoseLastSubResultantElseSplit$SFRGCD : bad #2" + purelyTranscendental?(p1,ts) and purelyTranscendental?(p2,ts) => + stoseIntegralLastSubResultant(p1,p2,ts) + if mdeg(p1) < mdeg(p2) then + (p1, p2) := (p2, p1) + if odd?(mdeg(p1)) and odd?(mdeg(p2)) then p2 := - p2 + stoseInternalLastSubResultant(p1,p2,ts,false,false) + + stoseSquareFreePart_wip(p:P, ts: TS): List PWT == + -- ASSUME p is not constant and mvar(p) > mvar(ts) + -- ASSUME init(p) is invertible w.r.t. ts + -- ASSUME p is mainly primitive +-- one? mdeg(p) => [[p,ts]$PWT] + mdeg(p) = 1 => [[p,ts]$PWT] + v := mvar(p)$P + q: P := mainPrimitivePart D(p,v) + lgwt: List PWT := stoseInternalLastSubResultant(p,q,ts,true,false) + lpwt : List PWT := [] + sfp : P + for gwt in lgwt repeat + g := gwt.val; us := gwt.tower + (ground? g) or (mvar(g) < v) => + lpwt := cons([p,us],lpwt) + g := mainPrimitivePart g + sfp := lazyPquo(p,g) + sfp := mainPrimitivePart stronglyReduce(sfp,us) + lpwt := cons([sfp,us],lpwt) + lpwt + + stoseSquareFreePart_base(p:P, ts: TS): List PWT == [[p,ts]$PWT] + + stoseSquareFreePart(p:P, ts: TS): List PWT == stoseSquareFreePart_wip(p,ts) + + stoseInvertible?_sqfreg(p:P,ts:TS): List BWT == + --iprint("+")$iprintpack + q := primitivePart initiallyReduce(p,ts) + zero? q => [[false,ts]$BWT] + normalized?(q,ts) => [[true,ts]$BWT] + v := mvar(q) + not algebraic?(v,ts) => + lbwt: List BWT := [] + toCheck: List BWT := stoseInvertible?_sqfreg(init(q),ts)@(List BWT) + for bwt in toCheck repeat + bwt.val => lbwt := cons(bwt,lbwt) + newq := removeZero(q,bwt.tower) + zero? newq => lbwt := cons(bwt,lbwt) + lbwt := concat(stoseInvertible?_sqfreg(newq,bwt.tower)@(List BWT), lbwt) + return lbwt + ts_v := select(ts,v)::P + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + lgwt := stoseInternalLastSubResultant(ts_v,q,ts_v_-,false,false) + lbwt: List BWT := [] + lts, lts_g, lts_h: Split + for gwt in lgwt repeat + g := gwt.val; ts := gwt.tower + (ground? g) or (mvar(g) < v) => + lts := augment(ts_v,ts)$TS + lts := augment(members(ts_v_+),lts)$TS + for ts in lts repeat + lbwt := cons([true, ts]$BWT,lbwt) + g := mainPrimitivePart g + lts_g := augment(g,ts)$TS + lts_g := augment(members(ts_v_+),lts_g)$TS + -- USE stoseInternalAugment with parameters ?? + for ts_g in lts_g repeat + lbwt := cons([false, ts_g]$BWT,lbwt) + h := lazyPquo(ts_v,g) + (ground? h) or (mvar(h) < v) => "leave" + h := mainPrimitivePart h + lts_h := augment(h,ts)$TS + lts_h := augment(members(ts_v_+),lts_h)$TS + -- USE stoseInternalAugment with parameters ?? + for ts_h in lts_h repeat + lbwt := cons([true, ts_h]$BWT,lbwt) + sort(#1.val < #2.val,lbwt) + + stoseInvertibleSet_sqfreg(p:P,ts:TS): Split == + --iprint("*")$iprintpack + k: KeyInvSet := [p,ts] + e := extractIfCan(k)$HInvSet + e case EntryInvSet => e::EntryInvSet + q := primitivePart initiallyReduce(p,ts) + zero? q => [] + normalized?(q,ts) => [ts] + v := mvar(q) + toSave: Split := [] + not algebraic?(v,ts) => + toCheck: List BWT := stoseInvertible?_sqfreg(init(q),ts)@(List BWT) + for bwt in toCheck repeat + bwt.val => toSave := cons(bwt.tower,toSave) + newq := removeZero(q,bwt.tower) + zero? newq => "leave" + toSave := concat(stoseInvertibleSet_sqfreg(newq,bwt.tower), toSave) + toSave := removeDuplicates toSave + return algebraicSort(toSave)$quasicomppack + ts_v := select(ts,v)::P + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + lgwt := stoseInternalLastSubResultant(ts_v,q,ts_v_-,false,false) + lts, lts_h: Split + for gwt in lgwt repeat + g := gwt.val; ts := gwt.tower + (ground? g) or (mvar(g) < v) => + lts := augment(ts_v,ts)$TS + lts := augment(members(ts_v_+),lts)$TS + toSave := concat(lts,toSave) + g := mainPrimitivePart g + h := lazyPquo(ts_v,g) + h := mainPrimitivePart h + (ground? h) or (mvar(h) < v) => "leave" + lts_h := augment(h,ts)$TS + lts_h := augment(members(ts_v_+),lts_h)$TS + toSave := concat(lts_h,toSave) + toSave := algebraicSort(toSave)$quasicomppack + insert!(k,toSave)$HInvSet + toSave + + stoseInvertible?_reg(p:P,ts:TS): List BWT == + --iprint("-")$iprintpack + q := primitivePart initiallyReduce(p,ts) + zero? q => [[false,ts]$BWT] + normalized?(q,ts) => [[true,ts]$BWT] + v := mvar(q) + not algebraic?(v,ts) => + lbwt: List BWT := [] + toCheck: List BWT := stoseInvertible?_reg(init(q),ts)@(List BWT) + for bwt in toCheck repeat + bwt.val => lbwt := cons(bwt,lbwt) + newq := removeZero(q,bwt.tower) + zero? newq => lbwt := cons(bwt,lbwt) + lbwt := concat(stoseInvertible?_reg(newq,bwt.tower)@(List BWT), lbwt) + return lbwt + ts_v := select(ts,v)::P + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + lgwt := stoseInternalLastSubResultant(ts_v,q,ts_v_-,false,false) + lbwt: List BWT := [] + lts, lts_g, lts_h: Split + for gwt in lgwt repeat + g := gwt.val; ts := gwt.tower + (ground? g) or (mvar(g) < v) => + lts := augment(ts_v,ts)$TS + lts := augment(members(ts_v_+),lts)$TS + for ts in lts repeat + lbwt := cons([true, ts]$BWT,lbwt) + g := mainPrimitivePart g + lts_g := augment(g,ts)$TS + lts_g := augment(members(ts_v_+),lts_g)$TS + -- USE internalAugment with parameters ?? + for ts_g in lts_g repeat + lbwt := cons([false, ts_g]$BWT,lbwt) + h := lazyPquo(ts_v,g) + (ground? h) or (mvar(h) < v) => "leave" + h := mainPrimitivePart h + lts_h := augment(h,ts)$TS + lts_h := augment(members(ts_v_+),lts_h)$TS + -- USE internalAugment with parameters ?? + for ts_h in lts_h repeat + inv := stoseInvertible?_reg(q,ts_h)@(List BWT) + lbwt := concat([bwt for bwt in inv | bwt.val],lbwt) + sort(#1.val < #2.val,lbwt) + + stoseInvertibleSet_reg(p:P,ts:TS): Split == + --iprint("/")$iprintpack + k: KeyInvSet := [p,ts] + e := extractIfCan(k)$HInvSet + e case EntryInvSet => e::EntryInvSet + q := primitivePart initiallyReduce(p,ts) + zero? q => [] + normalized?(q,ts) => [ts] + v := mvar(q) + toSave: Split := [] + not algebraic?(v,ts) => + toCheck: List BWT := stoseInvertible?_reg(init(q),ts)@(List BWT) + for bwt in toCheck repeat + bwt.val => toSave := cons(bwt.tower,toSave) + newq := removeZero(q,bwt.tower) + zero? newq => "leave" + toSave := concat(stoseInvertibleSet_reg(newq,bwt.tower), toSave) + toSave := removeDuplicates toSave + return algebraicSort(toSave)$quasicomppack + ts_v := select(ts,v)::P + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + lgwt := stoseInternalLastSubResultant(ts_v,q,ts_v_-,false,false) + lts, lts_h: Split + for gwt in lgwt repeat + g := gwt.val; ts := gwt.tower + (ground? g) or (mvar(g) < v) => + lts := augment(ts_v,ts)$TS + lts := augment(members(ts_v_+),lts)$TS + toSave := concat(lts,toSave) + g := mainPrimitivePart g + h := lazyPquo(ts_v,g) + h := mainPrimitivePart h + (ground? h) or (mvar(h) < v) => "leave" + lts_h := augment(h,ts)$TS + lts_h := augment(members(ts_v_+),lts_h)$TS + for ts_h in lts_h repeat + inv := stoseInvertibleSet_reg(q,ts_h) + toSave := removeDuplicates concat(inv,toSave) + toSave := algebraicSort(toSave)$quasicomppack + insert!(k,toSave)$HInvSet + toSave + + if TS has SquareFreeRegularTriangularSetCategory(R,E,V,P) + then + + stoseInvertible?(p:P,ts:TS): List BWT == stoseInvertible?_sqfreg(p,ts) + + stoseInvertibleSet(p:P,ts:TS): Split == stoseInvertibleSet_sqfreg(p,ts) + + else + + stoseInvertible?(p:P,ts:TS): List BWT == stoseInvertible?_reg(p,ts) + + stoseInvertibleSet(p:P,ts:TS): Split == stoseInvertibleSet_reg(p,ts) + +@ +\section{package SRDCMPK SquareFreeRegularSetDecompositionPackage} +<<package SRDCMPK SquareFreeRegularSetDecompositionPackage>>= +)abbrev package SRDCMPK SquareFreeRegularSetDecompositionPackage +++ Author: Marc Moreno Maza +++ Date Created: 09/23/1998 +++ Date Last Updated: 12/16/1998 +++ Basic Functions: +++ Related Constructors: +++ Also See: +++ AMS Classifications: +++ Keywords: +++ Description: +++ A package providing a new algorithm for solving polynomial systems +++ by means of regular chains. Two ways of solving are provided: +++ in the sense of Zariski closure (like in Kalkbrener's algorithm) +++ or in the sense of the regular zeros (like in Wu, Wang or Lazard- +++ Moreno methods). This algorithm is valid for nay type +++ of regular set. It does not care about the way a polynomial is +++ added in an regular set, or how two quasi-components are compared +++ (by an inclusion-test), or how the invertibility test is made in +++ the tower of simple extensions associated with a regular set. +++ These operations are realized respectively by the domain \spad{TS} +++ and the packages \spad{QCMPPK(R,E,V,P,TS)} and \spad{RSETGCD(R,E,V,P,TS)}. +++ The same way it does not care about the way univariate polynomial +++ gcds (with coefficients in the tower of simple extensions associated +++ with a regular set) are computed. The only requirement is that these +++ gcds need to have invertible initials (normalized or not). +++ WARNING. There is no need for a user to call diectly any operation +++ of this package since they can be accessed by the domain \axiomType{TS}. +++ Thus, the operations of this package are not documented.\newline +++ References : +++ [1] M. MORENO MAZA "A new algorithm for computing triangular +++ decomposition of algebraic varieties" NAG Tech. Rep. 4/98. +++ Version: 2. Does not use any unproved criteria. + +SquareFreeRegularSetDecompositionPackage(R,E,V,P,TS): Exports == Implementation where + + R : GcdDomain + E : OrderedAbelianMonoidSup + V : OrderedSet + P : RecursivePolynomialCategory(R,E,V) + TS : SquareFreeRegularTriangularSetCategory(R,E,V,P) + N ==> NonNegativeInteger + Z ==> Integer + B ==> Boolean + LP ==> List P + PS ==> GeneralPolynomialSet(R,E,V,P) + PWT ==> Record(val : P, tower : TS) + BWT ==> Record(val : Boolean, tower : TS) + LpWT ==> Record(val : (List P), tower : TS) + Wip ==> Record(done: Split, todo: List LpWT) + Branch ==> Record(eq: List P, tower: TS, ineq: List P) + UBF ==> Union(Branch,"failed") + Split ==> List TS + iprintpack ==> InternalPrintPackage() + polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P) + quasicomppack ==> SquareFreeQuasiComponentPackage(R,E,V,P,TS) + regsetgcdpack ==> SquareFreeRegularTriangularSetGcdPackage(R,E,V,P,TS) + + Exports == with + + KrullNumber: (LP, Split) -> N + numberOfVariables: (LP, Split) -> N + algebraicDecompose: (P,TS) -> Record(done: Split, todo: List LpWT) + transcendentalDecompose: (P,TS,N) -> Record(done: Split, todo: List LpWT) + transcendentalDecompose: (P,TS) -> Record(done: Split, todo: List LpWT) + internalDecompose: (P,TS,N,B) -> Record(done: Split, todo: List LpWT) + internalDecompose: (P,TS,N) -> Record(done: Split, todo: List LpWT) + internalDecompose: (P,TS) -> Record(done: Split, todo: List LpWT) + decompose: (LP, Split, B, B) -> Split + decompose: (LP, Split, B, B, B, B, B) -> Split + upDateBranches: (LP,Split,List LpWT,Wip,N) -> List LpWT + convert: Record(val: List P,tower: TS) -> String + printInfo: (List Record(val: List P,tower: TS), N) -> Void + + Implementation == add + + KrullNumber(lp: LP, lts: Split): N == + ln: List N := [#(ts) for ts in lts] + n := #lp + reduce(max,ln) + + numberOfVariables(lp: LP, lts: Split): N == + lv: List V := variables([lp]$PS) + for ts in lts repeat lv := concat(variables(ts), lv) + # removeDuplicates(lv) + + algebraicDecompose(p: P, ts: TS): Record(done: Split, todo: List LpWT) == + ground? p => + error " in algebraicDecompose$REGSET: should never happen !" + v := mvar(p); n := #ts + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + ts_v := select(ts,v)::P + lgwt: List PWT + if mdeg(p) < mdeg(ts_v) + then + lgwt := stoseInternalLastSubResultant(ts_v,p,ts_v_-,true,false)$regsetgcdpack + else + lgwt := stoseInternalLastSubResultant(p,ts_v,ts_v_-,true,false)$regsetgcdpack + lts: Split := [] + llpwt: List LpWT := [] + for gwt in lgwt repeat + g := gwt.val; us := gwt.tower + zero? g => + error " in algebraicDecompose$REGSET: should never happen !!" + ground? g => "leave" + h := leadingCoefficient(g,v) + lus := augment(members(ts_v_+),augment(ts_v,us)$TS)$TS + lsfp := squareFreeFactors(h)$polsetpack + for f in lsfp repeat + ground? f => "leave" + for vs in lus repeat + llpwt := cons([[f,p],vs]$LpWT, llpwt) + n < #us => + error " in algebraicDecompose$REGSET: should never happen !!!" + mvar(g) = v => + lts := concat(augment(members(ts_v_+),augment(g,us)$TS)$TS,lts) + [lts,llpwt] + + transcendentalDecompose(p: P, ts: TS,bound: N): Record(done: Split, todo: List LpWT) == + lts: Split + if #ts < bound + then + lts := augment(p,ts)$TS + else + lts := [] + llpwt: List LpWT := [] + [lts,llpwt] + + transcendentalDecompose(p: P, ts: TS): Record(done: Split, todo: List LpWT) == + lts: Split:= augment(p,ts)$TS + llpwt: List LpWT := [] + [lts,llpwt] + + internalDecompose(p: P, ts: TS,bound: N,clos?:B): Record(done: Split, todo: List LpWT) == + clos? => internalDecompose(p,ts,bound) + internalDecompose(p,ts) + + internalDecompose(p: P, ts: TS,bound: N): Record(done: Split, todo: List LpWT) == + -- ASSUME p not constant + llpwt: List LpWT := [] + lts: Split := [] + -- EITHER mvar(p) is null + if (not zero? tail(p)) and (not ground? (lmp := leastMonomial(p))) + then + llpwt := cons([[mvar(p)::P],ts]$LpWT,llpwt) + p := (p exquo lmp)::P + ip := squareFreePart init(p); tp := tail p + p := mainPrimitivePart p + -- OR init(p) is null or not + lbwt: List BWT := stoseInvertible?_sqfreg(ip,ts)$regsetgcdpack + for bwt in lbwt repeat + bwt.val => + if algebraic?(mvar(p),bwt.tower) + then + rsl := algebraicDecompose(p,bwt.tower) + else + rsl := transcendentalDecompose(p,bwt.tower,bound) + lts := concat(rsl.done,lts) + llpwt := concat(rsl.todo,llpwt) + (not ground? ip) => + zero? tp => llpwt := cons([[ip],bwt.tower]$LpWT, llpwt) + (not ground? tp) => llpwt := cons([[ip,tp],bwt.tower]$LpWT, llpwt) + riv := removeZero(ip,bwt.tower) + (zero? riv) => + zero? tp => lts := cons(bwt.tower,lts) + (not ground? tp) => llpwt := cons([[tp],bwt.tower]$LpWT, llpwt) + llpwt := cons([[riv * mainMonomial(p) + tp],bwt.tower]$LpWT, llpwt) + [lts,llpwt] + + internalDecompose(p: P, ts: TS): Record(done: Split, todo: List LpWT) == + -- ASSUME p not constant + llpwt: List LpWT := [] + lts: Split := [] + -- EITHER mvar(p) is null + if (not zero? tail(p)) and (not ground? (lmp := leastMonomial(p))) + then + llpwt := cons([[mvar(p)::P],ts]$LpWT,llpwt) + p := (p exquo lmp)::P + ip := squareFreePart init(p); tp := tail p + p := mainPrimitivePart p + -- OR init(p) is null or not + lbwt: List BWT := stoseInvertible?_sqfreg(ip,ts)$regsetgcdpack + for bwt in lbwt repeat + bwt.val => + if algebraic?(mvar(p),bwt.tower) + then + rsl := algebraicDecompose(p,bwt.tower) + else + rsl := transcendentalDecompose(p,bwt.tower) + lts := concat(rsl.done,lts) + llpwt := concat(rsl.todo,llpwt) + (not ground? ip) => + zero? tp => llpwt := cons([[ip],bwt.tower]$LpWT, llpwt) + (not ground? tp) => llpwt := cons([[ip,tp],bwt.tower]$LpWT, llpwt) + riv := removeZero(ip,bwt.tower) + (zero? riv) => + zero? tp => lts := cons(bwt.tower,lts) + (not ground? tp) => llpwt := cons([[tp],bwt.tower]$LpWT, llpwt) + llpwt := cons([[riv * mainMonomial(p) + tp],bwt.tower]$LpWT, llpwt) + [lts,llpwt] + + decompose(lp: LP, lts: Split, clos?: B, info?: B): Split == + decompose(lp,lts,false,false,clos?,true,info?) + + convert(lpwt: LpWT): String == + ls: List String := ["<", string((#(lpwt.val))::Z), ",", string((#(lpwt.tower))::Z), ">" ] + concat ls + + printInfo(toSee: List LpWT, n: N): Void == + lpwt := first toSee + s: String := concat ["[", string((#toSee)::Z), " ", convert(lpwt)@String] + m: N := #(lpwt.val) + toSee := rest toSee + for lpwt in toSee repeat + m := m + #(lpwt.val) + s := concat [s, ",", convert(lpwt)@String] + s := concat [s, " -> |", string(m::Z), "|; {", string(n::Z),"}]"] + iprint(s)$iprintpack + void() + + decompose(lp: LP, lts: Split, cleanW?: B, sqfr?: B, clos?: B, rem?: B, info?: B): Split == + -- if cleanW? then REMOVE REDUNDANT COMPONENTS in lts + -- if sqfr? then SPLIT the system with SQUARE-FREE FACTORIZATION + -- if clos? then SOLVE in the closure sense + -- if rem? then REDUCE the current p by using remainder + -- if info? then PRINT info + empty? lp => lts + branches: List Branch := prepareDecompose(lp,lts,cleanW?,sqfr?)$quasicomppack + empty? branches => [] + toSee: List LpWT := [[br.eq,br.tower]$LpWT for br in branches] + toSave: Split := [] + if clos? then bound := KrullNumber(lp,lts) else bound := numberOfVariables(lp,lts) + while (not empty? toSee) repeat + if info? then printInfo(toSee,#toSave) + lpwt := first toSee; toSee := rest toSee + lp := lpwt.val; ts := lpwt.tower + empty? lp => + toSave := cons(ts, toSave) + p := first lp; lp := rest lp + if rem? and (not ground? p) and (not empty? ts) + then + p := remainder(p,ts).polnum + p := removeZero(p,ts) + zero? p => toSee := cons([lp,ts]$LpWT, toSee) + ground? p => "leave" + rsl := internalDecompose(p,ts,bound,clos?) + toSee := upDateBranches(lp,toSave,toSee,rsl,bound) + removeSuperfluousQuasiComponents(toSave)$quasicomppack + + upDateBranches(leq:LP,lts:Split,current:List LpWT,wip: Wip,n:N): List LpWT == + newBranches: List LpWT := wip.todo + newComponents: Split := wip.done + branches1, branches2: List LpWT + branches1 := []; branches2 := [] + for branch in newBranches repeat + us := branch.tower + #us > n => "leave" + newleq := sort(infRittWu?,concat(leq,branch.val)) + --foo := rewriteSetWithReduction(newleq,us,initiallyReduce,initiallyReduced?) + --any?(ground?,foo) => "leave" + branches1 := cons([newleq,us]$LpWT, branches1) + for us in newComponents repeat + #us > n => "leave" + subQuasiComponent?(us,lts)$quasicomppack => "leave" + --newleq := leq + --foo := rewriteSetWithReduction(newleq,us,initiallyReduce,initiallyReduced?) + --any?(ground?,foo) => "leave" + branches2 := cons([leq,us]$LpWT, branches2) + empty? branches1 => + empty? branches2 => current + concat(branches2, current) + branches := concat [branches2, branches1, current] + -- branches := concat(branches,current) + removeSuperfluousCases(branches)$quasicomppack + +@ +\section{domain SREGSET SquareFreeRegularTriangularSet} +<<domain SREGSET SquareFreeRegularTriangularSet>>= +)abbrev domain SREGSET SquareFreeRegularTriangularSet +++ Author: Marc Moreno Maza +++ Date Created: 08/25/1998 +++ Date Last Updated: 16/12/1998 +++ Basic Functions: +++ Related Constructors: +++ Also See: +++ AMS Classifications: +++ Keywords: +++ Description: +++ This domain provides an implementation of square-free regular chains. +++ Moreover, the operation \axiomOpFrom{zeroSetSplit}{SquareFreeRegularTriangularSetCategory} +++ is an implementation of a new algorithm for solving polynomial systems by +++ means of regular chains.\newline +++ References : +++ [1] M. MORENO MAZA "A new algorithm for computing triangular +++ decomposition of algebraic varieties" NAG Tech. Rep. 4/98. +++ Version: 2 + +SquareFreeRegularTriangularSet(R,E,V,P) : Exports == Implementation where + + R : GcdDomain + E : OrderedAbelianMonoidSup + V : OrderedSet + P : RecursivePolynomialCategory(R,E,V) + N ==> NonNegativeInteger + Z ==> Integer + B ==> Boolean + LP ==> List P + PtoP ==> P -> P + PS ==> GeneralPolynomialSet(R,E,V,P) + PWT ==> Record(val : P, tower : $) + BWT ==> Record(val : Boolean, tower : $) + LpWT ==> Record(val : (List P), tower : $) + Split ==> List $ + iprintpack ==> InternalPrintPackage() + polsetpack ==> PolynomialSetUtilitiesPackage(R,E,V,P) + quasicomppack ==> SquareFreeQuasiComponentPackage(R,E,V,P,$) + regsetgcdpack ==> SquareFreeRegularTriangularSetGcdPackage(R,E,V,P,$) + regsetdecomppack ==> SquareFreeRegularSetDecompositionPackage(R,E,V,P,$) + + Exports == SquareFreeRegularTriangularSetCategory(R,E,V,P) with + + internalAugment: (P,$,B,B,B,B,B) -> List $ + ++ \axiom{internalAugment(p,ts,b1,b2,b3,b4,b5)} + ++ is an internal subroutine, exported only for developement. + zeroSetSplit: (LP, B, B) -> Split + ++ \axiom{zeroSetSplit(lp,clos?,info?)} has the same specifications as + ++ \axiomOpFrom{zeroSetSplit}{RegularTriangularSetCategory} + ++ from \spadtype{RegularTriangularSetCategory} + ++ Moreover, if \axiom{clos?} then solves in the sense of the Zariski closure + ++ else solves in the sense of the regular zeros. If \axiom{info?} then + ++ do print messages during the computations. + zeroSetSplit: (LP, B, B, B, B) -> Split + ++ \axiom{zeroSetSplit(lp,b1,b2.b3,b4)} + ++ is an internal subroutine, exported only for developement. + internalZeroSetSplit: (LP, B, B, B) -> Split + ++ \axiom{internalZeroSetSplit(lp,b1,b2,b3)} + ++ is an internal subroutine, exported only for developement. + pre_process: (LP, B, B) -> Record(val: LP, towers: Split) + ++ \axiom{pre_process(lp,b1,b2)} + ++ is an internal subroutine, exported only for developement. + + Implementation == add + + Rep ==> LP + + rep(s:$):Rep == s pretend Rep + per(l:Rep):$ == l pretend $ + + copy ts == + per(copy(rep(ts))$LP) + empty() == + per([]) + empty?(ts:$) == + empty?(rep(ts)) + parts ts == + rep(ts) + members ts == + rep(ts) + map (f : PtoP, ts : $) : $ == + construct(map(f,rep(ts))$LP)$$ + map! (f : PtoP, ts : $) : $ == + construct(map!(f,rep(ts))$LP)$$ + member? (p,ts) == + member?(p,rep(ts))$LP + unitIdealIfCan() == + "failed"::Union($,"failed") + roughUnitIdeal? ts == + false + coerce(ts:$) : OutputForm == + lp : List(P) := reverse(rep(ts)) + brace([p::OutputForm for p in lp]$List(OutputForm))$OutputForm + mvar ts == + empty? ts => error "mvar$SREGSET: #1 is empty" + mvar(first(rep(ts)))$P + first ts == + empty? ts => "failed"::Union(P,"failed") + first(rep(ts))::Union(P,"failed") + last ts == + empty? ts => "failed"::Union(P,"failed") + last(rep(ts))::Union(P,"failed") + rest ts == + empty? ts => "failed"::Union($,"failed") + per(rest(rep(ts)))::Union($,"failed") + coerce(ts:$) : (List P) == + rep(ts) + + collectUpper (ts,v) == + empty? ts => ts + lp := rep(ts) + newlp : Rep := [] + while (not empty? lp) and (mvar(first(lp)) > v) repeat + newlp := cons(first(lp),newlp) + lp := rest lp + per(reverse(newlp)) + + collectUnder (ts,v) == + empty? ts => ts + lp := rep(ts) + while (not empty? lp) and (mvar(first(lp)) >= v) repeat + lp := rest lp + per(lp) + + construct(lp:List(P)) == + ts : $ := per([]) + empty? lp => ts + lp := sort(infRittWu?,lp) + while not empty? lp repeat + eif := extendIfCan(ts,first(lp)) + not (eif case $) => + error"in construct : List P -> $ from SREGSET : bad #1" + ts := eif::$ + lp := rest lp + ts + + extendIfCan(ts:$,p:P) == + ground? p => "failed"::Union($,"failed") + empty? ts => + p := squareFreePart primitivePart p + (per([p]))::Union($,"failed") + not (mvar(ts) < mvar(p)) => "failed"::Union($,"failed") + invertible?(init(p),ts)@Boolean => + lts: Split := augment(p,ts) + #lts ~= 1 => "failed"::Union($,"failed") + (first lts)::Union($,"failed") + "failed"::Union($,"failed") + + removeZero(p:P, ts:$): P == + (ground? p) or (empty? ts) => p + v := mvar(p) + ts_v_- := collectUnder(ts,v) + if algebraic?(v,ts) + then + q := lazyPrem(p,select(ts,v)::P) + zero? q => return q + zero? removeZero(q,ts_v_-) => return 0 + empty? ts_v_- => p + q: P := 0 + while positive? degree(p,v) repeat + q := removeZero(init(p),ts_v_-) * mainMonomial(p) + q + p := tail(p) + q + removeZero(p,ts_v_-) + + internalAugment(p:P,ts:$): $ == + -- ASSUME that adding p to ts DOES NOT require any split + ground? p => error "in internalAugment$SREGSET: ground? #1" + first(internalAugment(p,ts,false,false,false,false,false)) + + internalAugment(lp:List(P),ts:$): $ == + -- ASSUME that adding p to ts DOES NOT require any split + empty? lp => ts + internalAugment(rest lp, internalAugment(first lp, ts)) + + internalAugment(p:P,ts:$,rem?:B,red?:B,prim?:B,sqfr?:B,extend?:B): Split == + -- ASSUME p is not a constant + -- ASSUME mvar(p) is not algebraic w.r.t. ts + -- ASSUME init(p) invertible modulo ts + -- if rem? then REDUCE p by remainder + -- if prim? then REPLACE p by its main primitive part + -- if sqfr? then FACTORIZE SQUARE FREE p over R + -- if extend? DO NOT ASSUME every pol in ts_v_+ is invertible modulo ts + v := mvar(p) + ts_v_- := collectUnder(ts,v) + ts_v_+ := collectUpper(ts,v) + if rem? then p := remainder(p,ts_v_-).polnum + -- if rem? then p := reduceByQuasiMonic(p,ts_v_-) + if red? then p := removeZero(p,ts_v_-) + if prim? then p := mainPrimitivePart p + lts: Split + if sqfr? + then + lts: Split := [] + lsfp := squareFreeFactors(p)$polsetpack + for f in lsfp repeat + (ground? f) or (mvar(f) < v) => "leave" + lpwt := squareFreePart(f,ts_v_-) + for pwt in lpwt repeat + sfp := pwt.val; us := pwt.tower + lts := cons( per(cons(pwt.val, rep(pwt.tower))), lts) + else + lts: Split := [per(cons(p,rep(ts_v_-)))] + extend? => extend(members(ts_v_+),lts) + [per(concat(rep(ts_v_+),rep(us))) for us in lts] + + augment(p:P,ts:$): List $ == + ground? p => error "in augment$SREGSET: ground? #1" + algebraic?(mvar(p),ts) => error "in augment$SREGSET: bad #1" + -- ASSUME init(p) invertible modulo ts + -- DOES NOT ASSUME anything else. + -- THUS reduction, mainPrimitivePart and squareFree are NEEDED + internalAugment(p,ts,true,true,true,true,true) + + extend(p:P,ts:$): List $ == + ground? p => error "in extend$SREGSET: ground? #1" + v := mvar(p) + not (mvar(ts) < mvar(p)) => error "in extend$SREGSET: bad #1" + split: List($) := invertibleSet(init(p),ts) + lts: List($) := [] + for us in split repeat + lts := concat(augment(p,us),lts) + lts + + invertible?(p:P,ts:$): Boolean == + stoseInvertible?(p,ts)$regsetgcdpack + + invertible?(p:P,ts:$): List BWT == + stoseInvertible?_sqfreg(p,ts)$regsetgcdpack + + invertibleSet(p:P,ts:$): Split == + stoseInvertibleSet_sqfreg(p,ts)$regsetgcdpack + + lastSubResultant(p1:P,p2:P,ts:$): List PWT == + stoseLastSubResultant(p1,p2,ts)$regsetgcdpack + + squareFreePart(p:P, ts: $): List PWT == + stoseSquareFreePart(p,ts)$regsetgcdpack + + intersect(p:P, ts: $): List($) == decompose([p], [ts], false, false)$regsetdecomppack + + intersect(lp: LP, lts: List($)): List($) == decompose(lp, lts, false, false)$regsetdecomppack + -- SOLVE in the regular zero sense + -- and DO NOT PRINT info + + decompose(p:P, ts: $): List($) == decompose([p], [ts], true, false)$regsetdecomppack + + decompose(lp: LP, lts: List($)): List($) == decompose(lp, lts, true, false)$regsetdecomppack + -- SOLVE in the closure sense + -- and DO NOT PRINT info + + zeroSetSplit(lp:List(P)) == zeroSetSplit(lp,true,false) + -- by default SOLVE in the closure sense + -- and DO NOT PRINT info + + zeroSetSplit(lp:List(P), clos?: B) == zeroSetSplit(lp,clos?, false) + + zeroSetSplit(lp:List(P), clos?: B, info?: B) == + -- if clos? then SOLVE in the closure sense + -- if info? then PRINT info + -- by default USE hash-tables + -- and PREPROCESS the input system + zeroSetSplit(lp,true,clos?,info?,true) + + zeroSetSplit(lp:List(P),hash?:B,clos?:B,info?:B,prep?:B) == + -- if hash? then USE hash-tables + -- if info? then PRINT information + -- if clos? then SOLVE in the closure sense + -- if prep? then PREPROCESS the input system + if hash? + then + s1, s2, s3, dom1, dom2, dom3: String + e: String := empty()$String + if info? then (s1,s2,s3) := ("w","g","i") else (s1,s2,s3) := (e,e,e) + if info? + then + (dom1, dom2, dom3) := ("QCMPACK", "REGSETGCD: Gcd", "REGSETGCD: Inv Set") + else + (dom1, dom2, dom3) := (e,e,e) + startTable!(s1,"W",dom1)$quasicomppack + startTableGcd!(s2,"G",dom2)$regsetgcdpack + startTableInvSet!(s3,"I",dom3)$regsetgcdpack + lts := internalZeroSetSplit(lp,clos?,info?,prep?) + if hash? + then + stopTable!()$quasicomppack + stopTableGcd!()$regsetgcdpack + stopTableInvSet!()$regsetgcdpack + lts + + internalZeroSetSplit(lp:LP,clos?:B,info?:B,prep?:B) == + -- if info? then PRINT information + -- if clos? then SOLVE in the closure sense + -- if prep? then PREPROCESS the input system + if prep? + then + pp := pre_process(lp,clos?,info?) + lp := pp.val + lts := pp.towers + else + ts: $ := [[]] + lts := [ts] + lp := remove(zero?, lp) + any?(ground?, lp) => [] + empty? lp => lts + empty? lts => lts + lp := sort(infRittWu?,lp) + clos? => decompose(lp,lts, clos?, info?)$regsetdecomppack + -- IN DIM > 0 with clos? the following is not false ... + for p in lp repeat + lts := decompose([p],lts, clos?, info?)$regsetdecomppack + lts + + largeSystem?(lp:LP): Boolean == + -- Gonnet and Gerdt and not Wu-Wang.2 + #lp > 16 => true + #lp < 13 => false + lts: List($) := [] + (#lp :: Z - numberOfVariables(lp,lts)$regsetdecomppack :: Z) > 3 + + smallSystem?(lp:LP): Boolean == + -- neural, Vermeer, Liu, and not f-633 and not Hairer-2 + #lp < 5 + + mediumSystem?(lp:LP): Boolean == + -- f-633 and not Hairer-2 + lts: List($) := [] + (numberOfVariables(lp,lts)$regsetdecomppack :: Z - #lp :: Z) < 2 + +-- lin?(p:P):Boolean == ground?(init(p)) and one?(mdeg(p)) + lin?(p:P):Boolean == ground?(init(p)) and (mdeg(p) = 1) + + pre_process(lp:LP,clos?:B,info?:B): Record(val: LP, towers: Split) == + -- if info? then PRINT information + -- if clos? then SOLVE in the closure sense + ts: $ := [[]]; + lts: Split := [ts] + empty? lp => [lp,lts] + lp1: List P := [] + lp2: List P := [] + for p in lp repeat + ground? (tail p) => lp1 := cons(p, lp1) + lp2 := cons(p, lp2) + lts: Split := decompose(lp1,[ts],clos?,info?)$regsetdecomppack + probablyZeroDim?(lp)$polsetpack => + largeSystem?(lp) => return [lp2,lts] + if #lp > 7 + then + -- Butcher (8,8) + Wu-Wang.2 (13,16) + lp2 := crushedSet(lp2)$polsetpack + lp2 := remove(zero?,lp2) + any?(ground?,lp2) => return [lp2, lts] + lp3 := [p for p in lp2 | lin?(p)] + lp4 := [p for p in lp2 | not lin?(p)] + if clos? + then + lts := decompose(lp4,lts, clos?, info?)$regsetdecomppack + else + lp4 := sort(infRittWu?,lp4) + for p in lp4 repeat + lts := decompose([p],lts, clos?, info?)$regsetdecomppack + lp2 := lp3 + else + lp2 := crushedSet(lp2)$polsetpack + lp2 := remove(zero?,lp2) + any?(ground?,lp2) => return [lp2, lts] + if clos? + then + lts := decompose(lp2,lts, clos?, info?)$regsetdecomppack + else + lp2 := sort(infRittWu?,lp2) + for p in lp2 repeat + lts := decompose([p],lts, clos?, info?)$regsetdecomppack + lp2 := [] + return [lp2,lts] + smallSystem?(lp) => [lp2,lts] + mediumSystem?(lp) => [crushedSet(lp2)$polsetpack,lts] + lp3 := [p for p in lp2 | lin?(p)] + lp4 := [p for p in lp2 | not lin?(p)] + if clos? + then + lts := decompose(lp4,lts, clos?, info?)$regsetdecomppack + else + lp4 := sort(infRittWu?,lp4) + for p in lp4 repeat + lts := decompose([p],lts, clos?, info?)$regsetdecomppack + if clos? + then + lts := decompose(lp3,lts, clos?, info?)$regsetdecomppack + else + lp3 := sort(infRittWu?,lp3) + for p in lp3 repeat + lts := decompose([p],lts, clos?, info?)$regsetdecomppack + lp2 := [] + return [lp2,lts] + +@ +\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>> + +<<category SFRTCAT SquareFreeRegularTriangularSetCategory>> +<<package SFQCMPK SquareFreeQuasiComponentPackage>> +<<package SFRGCD SquareFreeRegularTriangularSetGcdPackage>> +<<package SRDCMPK SquareFreeRegularSetDecompositionPackage>> +<<domain SREGSET SquareFreeRegularTriangularSet>> +@ +\eject +\begin{thebibliography}{99} +\bibitem{1} nothing +\end{thebibliography} +\end{document} |