aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/realzero.spad.pamphlet
diff options
context:
space:
mode:
Diffstat (limited to 'src/algebra/realzero.spad.pamphlet')
-rw-r--r--src/algebra/realzero.spad.pamphlet347
1 files changed, 347 insertions, 0 deletions
diff --git a/src/algebra/realzero.spad.pamphlet b/src/algebra/realzero.spad.pamphlet
new file mode 100644
index 00000000..27374130
--- /dev/null
+++ b/src/algebra/realzero.spad.pamphlet
@@ -0,0 +1,347 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra realzero.spad}
+\author{Andy Neff}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{package REAL0 RealZeroPackage}
+<<package REAL0 RealZeroPackage>>=
+)abbrev package REAL0 RealZeroPackage
+++ Author: Andy Neff
+++ Date Created:
+++ Date Last Updated:
+++ Basic Functions:
+++ Related Constructors: UnivariatePolynomial, RealZeroPackageQ
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ This package provides functions for finding the real zeros
+++ of univariate polynomials over the integers to arbitrary user-specified
+++ precision. The results are returned as a list of
+++ isolating intervals which are expressed as records with "left" and "right" rational number
+++ components.
+
+RealZeroPackage(Pol): T == C where
+ Pol: UnivariatePolynomialCategory Integer
+ RN ==> Fraction Integer
+ Interval ==> Record(left : RN, right : RN)
+ isoList ==> List(Interval)
+ T == with
+ -- next two functions find isolating intervals
+ realZeros: (Pol) -> isoList
+ ++ realZeros(pol) returns a list of isolating intervals for
+ ++ all the real zeros of the univariate polynomial pol.
+ realZeros: (Pol, Interval) -> isoList
+ ++ realZeros(pol, range) returns a list of isolating intervals
+ ++ for all the real zeros of the univariate polynomial pol which
+ ++ lie in the interval expressed by the record range.
+ -- next two functions return intervals smaller then tolerence
+ realZeros: (Pol, RN) -> isoList
+ ++ realZeros(pol, eps) returns a list of intervals of length less
+ ++ than the rational number eps for all the real roots of the
+ ++ polynomial pol.
+ realZeros: (Pol, Interval, RN) -> isoList
+ ++ realZeros(pol, int, eps) returns a list of intervals of length
+ ++ less than the rational number eps for all the real roots of the
+ ++ polynomial pol which lie in the interval expressed by the
+ ++ record int.
+ refine: (Pol, Interval, RN) -> Interval
+ ++ refine(pol, int, eps) refines the interval int containing
+ ++ exactly one root of the univariate polynomial pol to size less
+ ++ than the rational number eps.
+ refine: (Pol, Interval, Interval) -> Union(Interval,"failed")
+ ++ refine(pol, int, range) takes a univariate polynomial pol and
+ ++ and isolating interval int containing exactly one real
+ ++ root of pol; the operation returns an isolating interval which
+ ++ is contained within range, or "failed" if no such isolating interval exists.
+ midpoint: Interval -> RN
+ ++ midpoint(int) returns the midpoint of the interval int.
+ midpoints: isoList -> List RN
+ ++ midpoints(isolist) returns the list of midpoints for the list
+ ++ of intervals isolist.
+ C == add
+ --Local Functions
+ makeSqfr: Pol -> Pol
+ ReZeroSqfr: (Pol) -> isoList
+ PosZero: (Pol) -> isoList
+ Zero1: (Pol) -> isoList
+ transMult: (Integer, Pol) -> Pol
+ transMultInv: (Integer, Pol) -> Pol
+ transAdd1: (Pol) -> Pol
+ invert: (Pol) -> Pol
+ minus: (Pol) -> Pol
+ negate: Interval -> Interval
+ rootBound: (Pol) -> Integer
+ var: (Pol) -> Integer
+
+ negate(int : Interval):Interval == [-int.right,-int.left]
+
+ midpoint(i : Interval):RN == (1/2)*(i.left + i.right)
+
+ midpoints(li : isoList) : List RN ==
+ [midpoint x for x in li]
+
+ makeSqfr(F : Pol):Pol ==
+ sqfr := squareFree F
+ F := */[s.factor for s in factors(sqfr)]
+
+ realZeros(F : Pol) ==
+ ReZeroSqfr makeSqfr F
+
+ realZeros(F : Pol, rn : RN) ==
+ F := makeSqfr F
+ [refine(F,int,rn) for int in ReZeroSqfr(F)]
+
+ realZeros(F : Pol, bounds : Interval) ==
+ F := makeSqfr F
+ [rint::Interval for int in ReZeroSqfr(F) |
+ (rint:=refine(F,int,bounds)) case Interval]
+
+ realZeros(F : Pol, bounds : Interval, rn : RN) ==
+ F := makeSqfr F
+ [refine(F,int,rn) for int in realZeros(F,bounds)]
+
+ ReZeroSqfr(F : Pol) ==
+ F = 0 => error "ReZeroSqfr: zero polynomial"
+ L : isoList := []
+ degree(F) = 0 => L
+ if (r := minimumDegree(F)) > 0 then
+ L := [[0,0]$Interval]
+ tempF := F exquo monomial(1, r)
+ if not (tempF case "failed") then
+ F := tempF
+ J:isoList := [negate int for int in reverse(PosZero(minus(F)))]
+ K : isoList := PosZero(F)
+ append(append(J, L), K)
+
+ PosZero(F : Pol) == --F is square free, primitive
+ --and F(0) ^= 0; returns isoList for positive
+ --roots of F
+
+ b : Integer := rootBound(F)
+ F := transMult(b,F)
+ L : isoList := Zero1(F)
+ int : Interval
+ L := [[b*int.left, b*int.right]$Interval for int in L]
+
+ Zero1(F : Pol) == --returns isoList for roots of F in (0,1)
+ J : isoList
+ K : isoList
+ L : isoList
+ L := []
+ (v := var(transAdd1(invert(F)))) = 0 => []
+ v = 1 => L := [[0,1]$Interval]
+ G : Pol := transMultInv(2, F)
+ H : Pol := transAdd1(G)
+ if minimumDegree H > 0 then
+ -- H has a root at 0 => F has one at 1/2, and G at 1
+ L := [[1/2,1/2]$Interval]
+ Q : Pol := monomial(1, 1)
+ tempH : Union(Pol, "failed") := H exquo Q
+ if not (tempH case "failed") then H := tempH
+ Q := Q + monomial(-1, 0)
+ tempG : Union(Pol, "failed") := G exquo Q
+ if not (tempG case "failed") then G := tempG
+ int : Interval
+ J := [[(int.left+1)* (1/2),(int.right+1) * (1/2)]$Interval
+ for int in Zero1(H)]
+ K := [[int.left * (1/2), int.right * (1/2)]$Interval
+ for int in Zero1(G)]
+ append(append(J, L), K)
+
+ rootBound(F : Pol) == --returns power of 2 that is a bound
+ --for the positive roots of F
+ if leadingCoefficient(F) < 0 then F := -F
+ lcoef := leadingCoefficient(F)
+ F := reductum(F)
+ i : Integer := 0
+ while not (F = 0) repeat
+ if (an := leadingCoefficient(F)) < 0 then i := i - an
+ F := reductum(F)
+ b : Integer := 1
+ while (b * lcoef) <= i repeat
+ b := 2 * b
+ b
+
+ transMult(c : Integer, F : Pol) ==
+ --computes Pol G such that G(x) = F(c*x)
+ G : Pol := 0
+ while not (F = 0) repeat
+ n := degree(F)
+ G := G + monomial((c**n) * leadingCoefficient(F), n)
+ F := reductum(F)
+ G
+
+ transMultInv(c : Integer, F : Pol) ==
+ --computes Pol G such that G(x) = (c**n) * F(x/c)
+ d := degree(F)
+ cc : Integer := 1
+ G : Pol := monomial(leadingCoefficient F,d)
+ while (F:=reductum(F)) ^= 0 repeat
+ n := degree(F)
+ cc := cc*(c**(d-n):NonNegativeInteger)
+ G := G + monomial(cc * leadingCoefficient(F), n)
+ d := n
+ G
+
+-- otransAdd1(F : Pol) ==
+-- --computes Pol G such that G(x) = F(x+1)
+-- G : Pol := F
+-- n : Integer := 1
+-- while (F := differentiate(F)) ^= 0 repeat
+-- if not ((tempF := F exquo n) case "failed") then F := tempF
+-- G := G + F
+-- n := n + 1
+-- G
+
+ transAdd1(F : Pol) ==
+ --computes Pol G such that G(x) = F(x+1)
+ n := degree F
+ v := vectorise(F, n+1)
+ for i in 0..(n-1) repeat
+ for j in (n-i)..n repeat
+ qsetelt_!(v,j, qelt(v,j) + qelt(v,(j+1)))
+ ans : Pol := 0
+ for i in 0..n repeat
+ ans := ans + monomial(qelt(v,(i+1)),i)
+ ans
+
+
+ minus(F : Pol) ==
+ --computes Pol G such that G(x) = F(-x)
+ G : Pol := 0
+ while not (F = 0) repeat
+ n := degree(F)
+ coef := leadingCoefficient(F)
+ odd? n =>
+ G := G + monomial(-coef, n)
+ F := reductum(F)
+ G := G + monomial(coef, n)
+ F := reductum(F)
+ G
+
+ invert(F : Pol) ==
+ --computes Pol G such that G(x) = (x**n) * F(1/x)
+ G : Pol := 0
+ n := degree(F)
+ while not (F = 0) repeat
+ G := G + monomial(leadingCoefficient(F),
+ (n-degree(F))::NonNegativeInteger)
+ F := reductum(F)
+ G
+
+ var(F : Pol) == --number of sign variations in coefs of F
+ i : Integer := 0
+ LastCoef : Boolean
+ next : Boolean
+ LastCoef := leadingCoefficient(F) < 0
+ while not ((F := reductum(F)) = 0) repeat
+ next := leadingCoefficient(F) < 0
+ if ((not LastCoef) and next) or
+ ((not next) and LastCoef) then i := i+1
+ LastCoef := next
+ i
+
+ refine(F : Pol, int : Interval, bounds : Interval) ==
+ lseg := min(int.right,bounds.right) - max(int.left,bounds.left)
+ lseg < 0 => "failed"
+ lseg = 0 =>
+ pt :=
+ int.left = bounds.right => int.left
+ int.right
+ elt(transMultInv(denom(pt),F),numer pt) = 0 => [pt,pt]
+ "failed"
+ lseg = int.right - int.left => int
+ refine(F, refine(F, int, lseg), bounds)
+
+ refine(F : Pol, int : Interval, eps : RN) ==
+ a := int.left
+ b := int.right
+ a=b => [a,b]$Interval
+ an : Integer := numer(a)
+ ad : Integer := denom(a)
+ bn : Integer := numer(b)
+ bd : Integer := denom(b)
+ xfl : Boolean := false
+ if (u:=elt(transMultInv(ad, F), an)) = 0 then
+ F := (F exquo (monomial(ad,1)-monomial(an,0)))::Pol
+ u:=elt(transMultInv(ad, F), an)
+ if (v:=elt(transMultInv(bd, F), bn)) = 0 then
+ F := (F exquo (monomial(bd,1)-monomial(bn,0)))::Pol
+ v:=elt(transMultInv(bd, F), bn)
+ u:=elt(transMultInv(ad, F), an)
+ if u > 0 then (F:=-F;v:=-v)
+ if v < 0 then
+ error [int, "is not a valid isolation interval for", F]
+ if eps <= 0 then error "precision must be positive"
+ while (b - a) >= eps repeat
+ mid : RN := (b + a) * (1/2)
+ midn : Integer := numer(mid)
+ midd : Integer := denom(mid)
+ (v := elt(transMultInv(midd, F), midn)) < 0 =>
+ a := mid
+ an := midn
+ ad := midd
+ v > 0 =>
+ b := mid
+ bn := midn
+ bd := midd
+ v = 0 =>
+ a := mid
+ b := mid
+ an := midn
+ ad := midd
+ xfl := true
+ [a, b]$Interval
+
+@
+\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 REAL0 RealZeroPackage>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}