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