001 /* 002 * $Id: RootFactory.java 3665 2011-06-13 11:08:16Z kredel $ 003 */ 004 005 package edu.jas.application; 006 007 008 import java.util.ArrayList; 009 import java.util.List; 010 import java.util.Set; 011 import java.util.Map; 012 013 import org.apache.log4j.Logger; 014 015 import edu.jas.arith.Rational; 016 import edu.jas.poly.Complex; 017 import edu.jas.poly.ComplexRing; 018 import edu.jas.poly.GenPolynomial; 019 import edu.jas.poly.GenPolynomialRing; 020 import edu.jas.poly.PolyUtil; 021 import edu.jas.poly.TermOrder; 022 import edu.jas.root.ComplexRoots; 023 import edu.jas.root.ComplexRootsSturm; 024 import edu.jas.root.RealRootTuple; 025 import edu.jas.root.Interval; 026 import edu.jas.structure.GcdRingElem; 027 import edu.jas.structure.RingFactory; 028 import edu.jas.ufd.SquarefreeAbstract; 029 import edu.jas.ufd.SquarefreeFactory; 030 031 032 /** 033 * Roots factory. 034 * @author Heinz Kredel 035 */ 036 public class RootFactory { 037 038 039 private static final Logger logger = Logger.getLogger(RootFactory.class); 040 041 042 //private static boolean debug = logger.isDebugEnabled(); 043 044 045 /** 046 * Is complex algebraic number a root of a polynomial. 047 * @param f univariate polynomial. 048 * @param r complex algebraic number. 049 * @return true, if f(r) == 0, else false; 050 */ 051 public static <C extends GcdRingElem<C> & Rational> 052 boolean isRoot(GenPolynomial<Complex<C>> f, Complex<RealAlgebraicNumber<C>> r) { 053 ComplexRing<RealAlgebraicNumber<C>> cr = r.factory(); 054 GenPolynomialRing<Complex<RealAlgebraicNumber<C>>> cfac 055 = new GenPolynomialRing<Complex<RealAlgebraicNumber<C>>>(cr,f.factory()); 056 GenPolynomial<Complex<RealAlgebraicNumber<C>>> p; 057 p = PolyUtilApp.<C> convertToComplexRealCoefficients(cfac,f); 058 //System.out.println("p = " + p); 059 // test algebraic part 060 Complex<RealAlgebraicNumber<C>> a = PolyUtil.<Complex<RealAlgebraicNumber<C>>> evaluateMain(cr,p,r); 061 boolean t = a.isZERO(); 062 if ( !t ) { 063 logger.info("p(r) = " + a + ", p = " + f + ", r = " + r); 064 return t; 065 } 066 // test real part 067 RealAlgebraicRing<C> rring = (RealAlgebraicRing<C>)cr.ring; 068 RealRootTuple<C> rroot = rring.getRoot(); 069 List<edu.jas.root.RealAlgebraicNumber<C>> rlist = rroot.tuple; 070 //System.out.println("rlist = " + rlist); 071 Interval<C> vr = rlist.get(0).ring.getRoot(); 072 Interval<C> vi = rlist.get(1).ring.getRoot(); 073 ComplexRing<C> ccfac = new ComplexRing<C>((RingFactory<C>)vr.left.factory()); 074 Complex<C> sw = new Complex<C>(ccfac,vr.left,vi.left); 075 Complex<C> ne = new Complex<C>(ccfac,vr.right,vi.right); 076 Complex<C> epsw = PolyUtil.<Complex<C>> evaluateMain(ccfac, f, sw); 077 Complex<C> epne = PolyUtil.<Complex<C>> evaluateMain(ccfac, f, ne); 078 int rootre = (epsw.getRe().signum()*epne.getRe().signum()); 079 int rootim = (epsw.getIm().signum()*epne.getIm().signum()); 080 t = (rootre <= 0 && rootim <= 0); 081 if ( !t ) { 082 logger.debug("vr = " + vr + ", vi = " + vi); 083 logger.info("sw = " + sw + ", ne = " + ne); 084 //System.out.println("root(re) = " + rootre + ", root(im) = " + rootim); 085 logger.info("p(root): p = " + f + ", epsw = " + epsw + ", epne = " + epne); 086 return t; 087 } 088 //System.out.println("r = " + r.getRe().magnitude() + " i " + r.getIm().magnitude()); 089 return t; 090 } 091 092 093 /** 094 * Is complex algebraic number a root of a polynomial. 095 * @param f univariate polynomial. 096 * @param R list of complex algebraic numbers. 097 * @return true, if f(r) == 0 for all r in R, else false; 098 */ 099 public static <C extends GcdRingElem<C> & Rational> 100 boolean isRoot(GenPolynomial<Complex<C>> f, List<Complex<RealAlgebraicNumber<C>>> R) { 101 for ( Complex<RealAlgebraicNumber<C>> r : R ) { 102 boolean t = isRoot(f,r); 103 if ( !t ) { 104 return false; 105 } 106 } 107 return true; 108 } 109 110 111 /** 112 * Complex algebraic number roots. 113 * @param f univariate polynomial. 114 * @return a list of different complex algebraic numbers, with f(c) == 0 for c in roots. 115 */ 116 public static <C extends GcdRingElem<C> & Rational> 117 List<Complex<RealAlgebraicNumber<C>>> complexAlgebraicNumbersComplex(GenPolynomial<Complex<C>> f) { 118 GenPolynomialRing<Complex<C>> pfac = f.factory(); 119 if (pfac.nvar != 1) { 120 throw new IllegalArgumentException("only for univariate polynomials"); 121 } 122 ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac; 123 ComplexRoots<C> cr = new ComplexRootsSturm<C>(cfac); 124 SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory.<Complex<C>> getImplementation(cfac); 125 Map<GenPolynomial<Complex<C>>,Long> F = engine.squarefreeFactors(f.monic()); 126 Set<GenPolynomial<Complex<C>>> S = F.keySet(); 127 //System.out.println("S = " + S); 128 List<Complex<RealAlgebraicNumber<C>>> list = new ArrayList<Complex<RealAlgebraicNumber<C>>>(); 129 for (GenPolynomial<Complex<C>> sp : S) { 130 if (sp.isConstant() || sp.isZERO()) { 131 continue; 132 } 133 List<Complex<RealAlgebraicNumber<C>>> ls = RootFactory.<C> complexAlgebraicNumbersSquarefree(sp); 134 long m = F.get(sp); 135 for (long i = 0L; i < m; i++) { 136 list.addAll(ls); 137 } 138 } 139 return list; 140 } 141 142 143 /** 144 * Complex algebraic number roots. 145 * @param f univariate squarefree polynomial. 146 * @return a list of different complex algebraic numbers, with f(c) == 0 for c in roots. 147 */ 148 public static <C extends GcdRingElem<C> & Rational> 149 List<Complex<RealAlgebraicNumber<C>>> complexAlgebraicNumbersSquarefree(GenPolynomial<Complex<C>> f) { 150 GenPolynomialRing<Complex<C>> pfac = f.factory(); 151 if (pfac.nvar != 1) { 152 throw new IllegalArgumentException("only for univariate polynomials"); 153 } 154 ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac; 155 ComplexRoots<C> cr = new ComplexRootsSturm<C>(cfac); 156 TermOrder to = new TermOrder(TermOrder.INVLEX); 157 GenPolynomialRing<Complex<C>> tfac = new GenPolynomialRing<Complex<C>>(cfac, 2, to); //,vars); //tord? 158 //System.out.println("tfac = " + tfac); 159 GenPolynomial<Complex<C>> t = tfac.univariate(1, 1L).sum( 160 tfac.univariate(0, 1L).multiply(cfac.getIMAG())); 161 //System.out.println("t = " + t); // t = x + i y 162 163 GenPolynomialRing<C> rfac = new GenPolynomialRing<C>(cfac.ring, tfac); //tord? 164 //System.out.println("rfac = " + rfac); 165 166 List<Complex<RealAlgebraicNumber<C>>> list = new ArrayList<Complex<RealAlgebraicNumber<C>>>(); 167 GenPolynomial<Complex<C>> sp = f; 168 if (sp.isConstant() || sp.isZERO()) { 169 return list; 170 } 171 GenPolynomial<Complex<C>> su = PolyUtil.<Complex<C>> substituteUnivariate(sp, t); 172 //System.out.println("su = " + su); 173 su = su.monic(); 174 //System.out.println("su = " + su); 175 GenPolynomial<C> re = PolyUtil.<C> realPartFromComplex(rfac, su); 176 GenPolynomial<C> im = PolyUtil.<C> imaginaryPartFromComplex(rfac, su); 177 if ( logger.isInfoEnabled() ) { 178 logger.debug("rfac = " + rfac.toScript()); 179 logger.info("t = " + t); 180 logger.info("re = " + re.toScript()); 181 logger.info("im = " + im.toScript()); 182 } 183 List<GenPolynomial<C>> li = new ArrayList<GenPolynomial<C>>(2); 184 li.add(re); 185 li.add(im); 186 Ideal<C> id = new Ideal<C>(rfac, li); 187 //System.out.println("id = " + id); 188 189 List<IdealWithUniv<C>> idul = id.zeroDimRootDecomposition(); 190 191 IdealWithRealAlgebraicRoots<C, C> idr; 192 for (IdealWithUniv<C> idu : idul) { 193 //System.out.println("---idu = " + idu); 194 idr = PolyUtilApp.<C, C> realAlgebraicRoots(idu); 195 //System.out.println("---idr = " + idr); 196 for (List<edu.jas.root.RealAlgebraicNumber<C>> crr : idr.ran) { 197 //System.out.println("crr = " + crr); 198 RealRootTuple<C> root = new RealRootTuple<C>(crr); 199 //System.out.println("root = " + root); 200 RealAlgebraicRing<C> car = new RealAlgebraicRing<C>(idu, root); 201 //System.out.println("car = " + car); 202 List<RealAlgebraicNumber<C>> gens = car.generators(); 203 //System.out.println("gens = " + gens); 204 int sg = gens.size(); 205 RealAlgebraicNumber<C> rre = gens.get(sg-2); 206 RealAlgebraicNumber<C> rim = gens.get(sg-1); 207 ComplexRing<RealAlgebraicNumber<C>> cring = new ComplexRing<RealAlgebraicNumber<C>>(car); 208 Complex<RealAlgebraicNumber<C>> crn = new Complex<RealAlgebraicNumber<C>>(cring,rre,rim); 209 //System.out.println("crn = " + crn.toScript()); 210 211 boolean it; 212 int count = 0; 213 do { // refine intervals if necessary 214 Interval<C> vr = crr.get(0).ring.getRoot(); 215 Interval<C> vi = crr.get(1).ring.getRoot(); 216 ComplexRing<C> ccfac = new ComplexRing<C>((RingFactory<C>)vr.left.factory()); 217 Complex<C> sw = new Complex<C>(ccfac,vr.left,vi.left); 218 Complex<C> ne = new Complex<C>(ccfac,vr.right,vi.right); 219 Complex<C> epsw = PolyUtil.<Complex<C>> evaluateMain(ccfac, f, sw); 220 Complex<C> epne = PolyUtil.<Complex<C>> evaluateMain(ccfac, f, ne); 221 int rootre = (epsw.getRe().signum()*epne.getRe().signum()); 222 int rootim = (epsw.getIm().signum()*epne.getIm().signum()); 223 it = (rootre <= 0 && rootim <= 0); 224 if ( !it ) { 225 logger.info("refine intervals: vr = " + vr + ", vi = " + vi); 226 //System.out.println("crn = " + crn.getRe().magnitude() + " i " + crn.getIm().magnitude()); 227 //System.out.println("sw = " + sw + ", ne = " + ne); 228 //System.out.println("epsw = " + epsw + ", epne = " + epne); 229 //System.out.println("root(re) = " + rootre + ", root(im) = " + rootim); 230 crn.getRe().ring.realRing.halfInterval(); 231 //System.out.println("crn.re = " + crn.getRe().ring.realRing); 232 crn.getIm().ring.realRing.halfInterval(); 233 //System.out.println("crn.im = " + crn.getIm().ring.realRing); 234 //edu.jas.root.RealAlgebraicRing<C> rrr; 235 //rrr = (edu.jas.root.RealAlgebraicRing<C>) crn.getRe().ring.realRing.algebraic.ring.coFac; 236 //rrr.halfInterval(); 237 //System.out.println("rrr.re = " + rrr); 238 //rrr = (edu.jas.root.RealAlgebraicRing<C>) crn.getIm().ring.realRing.algebraic.ring.coFac; 239 //rrr.halfInterval(); 240 //System.out.println("rrr.im = " + rrr); 241 if ( count++ > 2 ) { 242 //throw new RuntimeException("no roots of " + f); 243 logger.info("break in root refinement of " + f); 244 it = true; 245 } 246 } 247 } while ( !it ); 248 list.add(crn); 249 } 250 } 251 return list; 252 } 253 254 255 /* todo 256 * Complex algebraic numbers. 257 * @param f univariate polynomial. 258 * @param eps rational precision. 259 * @return a list of different complex algebraic numbers. 260 public static <C extends GcdRingElem<C> & Rational> 261 List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex(GenPolynomial<Complex<C>> f, BigRational eps) { 262 } 263 */ 264 265 }