001/* 002 * $Id: RootFactoryApp.java 5839 2018-05-20 20:30:09Z 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.AlgebraicNumberRing; 021import edu.jas.poly.AlgebraicNumber; 022import edu.jas.poly.PolyUtil; 023import edu.jas.poly.TermOrder; 024import edu.jas.root.Interval; 025import edu.jas.root.RealRootTuple; 026import edu.jas.root.AlgebraicRoots; 027import edu.jas.structure.GcdRingElem; 028import edu.jas.structure.RingFactory; 029import edu.jas.ufd.SquarefreeAbstract; 030import edu.jas.ufd.SquarefreeFactory; 031 032 033/** 034 * Roots factory. 035 * @author Heinz Kredel 036 */ 037public class RootFactoryApp { 038 039 040 private static final Logger logger = Logger.getLogger(RootFactoryApp.class); 041 042 043 private static final boolean debug = logger.isDebugEnabled(); 044 045 046 /** 047 * Is complex algebraic number a root of a polynomial. 048 * @param f univariate polynomial. 049 * @param r complex algebraic number. 050 * @return true, if f(r) == 0, else false; 051 */ 052 public static <C extends GcdRingElem<C> & Rational> boolean isRootRealCoeff(GenPolynomial<C> f, 053 Complex<RealAlgebraicNumber<C>> r) { 054 RingFactory<C> cfac = f.ring.coFac; 055 ComplexRing<C> ccfac = new ComplexRing<C>(cfac); 056 GenPolynomialRing<Complex<C>> facc = new GenPolynomialRing<Complex<C>>(ccfac, f.ring); 057 GenPolynomial<Complex<C>> fc = PolyUtil.<C> complexFromAny(facc, f); 058 return isRoot(fc, r); 059 } 060 061 062 /** 063 * Is complex algebraic number a root of a polynomial. 064 * @param f univariate polynomial. 065 * @param r complex algebraic number. 066 * @return true, if f(r) == 0, else false; 067 */ 068 public static <C extends GcdRingElem<C> & Rational> boolean isRoot(GenPolynomial<Complex<C>> f, 069 Complex<RealAlgebraicNumber<C>> r) { 070 ComplexRing<RealAlgebraicNumber<C>> cr = r.factory(); 071 GenPolynomialRing<Complex<RealAlgebraicNumber<C>>> cfac = new GenPolynomialRing<Complex<RealAlgebraicNumber<C>>>( 072 cr, f.factory()); 073 GenPolynomial<Complex<RealAlgebraicNumber<C>>> p; 074 p = PolyUtilApp.<C> convertToComplexRealCoefficients(cfac, f); 075 // test algebraic part 076 Complex<RealAlgebraicNumber<C>> a = PolyUtil.<Complex<RealAlgebraicNumber<C>>> evaluateMain(cr, p, r); 077 boolean t = a.isZERO(); 078 if (!t) { 079 logger.info("f(r) = " + a + ", f = " + f + ", r = " + r); 080 return t; 081 } 082 // test approximation? not working 083 return true; 084 } 085 086 087 /** 088 * Is complex algebraic number a root of a polynomial. 089 * @param f univariate polynomial. 090 * @param R list of complex algebraic numbers. 091 * @return true, if f(r) == 0 for all r in R, else false; 092 */ 093 public static <C extends GcdRingElem<C> & Rational> boolean isRoot(GenPolynomial<Complex<C>> f, 094 List<Complex<RealAlgebraicNumber<C>>> R) { 095 for (Complex<RealAlgebraicNumber<C>> r : R) { 096 boolean t = isRoot(f, r); 097 if (!t) { 098 return false; 099 } 100 } 101 return true; 102 } 103 104 105 /** 106 * Complex algebraic number roots. 107 * @param f univariate polynomial. 108 * @return a list of different complex algebraic numbers, with f(c) == 0 for 109 * c in roots. 110 */ 111 public static <C extends GcdRingElem<C> & Rational> List<Complex<RealAlgebraicNumber<C>>> complexAlgebraicNumbersComplex( 112 GenPolynomial<Complex<C>> f) { 113 GenPolynomialRing<Complex<C>> pfac = f.factory(); 114 if (pfac.nvar != 1) { 115 throw new IllegalArgumentException("only for univariate polynomials"); 116 } 117 ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac; 118 SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory.<Complex<C>> getImplementation(cfac); 119 Map<GenPolynomial<Complex<C>>, Long> F = engine.squarefreeFactors(f.monic()); 120 //System.out.println("S = " + F.keySet()); 121 List<Complex<RealAlgebraicNumber<C>>> list = new ArrayList<Complex<RealAlgebraicNumber<C>>>(); 122 for (Map.Entry<GenPolynomial<Complex<C>>,Long> me : F.entrySet()) { 123 GenPolynomial<Complex<C>> sp = me.getKey(); 124 if (sp.isConstant() || sp.isZERO()) { 125 continue; 126 } 127 List<Complex<RealAlgebraicNumber<C>>> ls = RootFactoryApp.<C> complexAlgebraicNumbersSquarefree(sp); 128 long m = me.getValue(); 129 for (long i = 0L; i < m; i++) { 130 list.addAll(ls); 131 } 132 } 133 return list; 134 } 135 136 137 /** 138 * Complex algebraic number roots. 139 * @param f univariate squarefree polynomial. 140 * @return a list of different complex algebraic numbers, with f(c) == 0 for 141 * c in roots. 142 */ 143 public static <C extends GcdRingElem<C> & Rational> 144 List<Complex<RealAlgebraicNumber<C>>> complexAlgebraicNumbersSquarefree( 145 GenPolynomial<Complex<C>> f) { 146 GenPolynomialRing<Complex<C>> pfac = f.factory(); 147 if (pfac.nvar != 1) { 148 throw new IllegalArgumentException("only for univariate polynomials"); 149 } 150 ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac; 151 TermOrder to = new TermOrder(TermOrder.INVLEX); 152 GenPolynomialRing<Complex<C>> tfac = new GenPolynomialRing<Complex<C>>(cfac, 2, to); //,vars); //tord? 153 //System.out.println("tfac = " + tfac); 154 GenPolynomial<Complex<C>> t = tfac.univariate(1, 1L).sum( 155 tfac.univariate(0, 1L).multiply(cfac.getIMAG())); 156 //System.out.println("t = " + t); // t = x + i y 157 GenPolynomialRing<C> rfac = new GenPolynomialRing<C>(cfac.ring, tfac); //tord? 158 //System.out.println("rfac = " + rfac); 159 List<Complex<RealAlgebraicNumber<C>>> list = new ArrayList<Complex<RealAlgebraicNumber<C>>>(); 160 GenPolynomial<Complex<C>> sp = f; 161 if (sp.isConstant() || sp.isZERO()) { 162 return list; 163 } 164 // substitute t = x + i y 165 GenPolynomial<Complex<C>> su = PolyUtil.<Complex<C>> substituteUnivariate(sp, t); 166 //System.out.println("su = " + su); 167 su = su.monic(); 168 //System.out.println("su = " + su); 169 GenPolynomial<C> re = PolyUtil.<C> realPartFromComplex(rfac, su); 170 GenPolynomial<C> im = PolyUtil.<C> imaginaryPartFromComplex(rfac, su); 171 if (debug) { 172 logger.debug("rfac = " + rfac.toScript()); 173 logger.debug("t = " + t + ", re = " + re.toScript() + ", im = " + im.toScript()); 174 } 175 List<GenPolynomial<C>> li = new ArrayList<GenPolynomial<C>>(2); 176 li.add(re); 177 li.add(im); 178 Ideal<C> id = new Ideal<C>(rfac, li); 179 //System.out.println("id = " + id); 180 List<IdealWithUniv<C>> idul = id.zeroDimRootDecomposition(); 181 182 IdealWithRealAlgebraicRoots<C> idr; 183 for (IdealWithUniv<C> idu : idul) { 184 //System.out.println("---idu = " + idu); 185 idr = PolyUtilApp.<C> realAlgebraicRoots(idu); 186 //System.out.println("---idr = " + idr); 187 for (List<edu.jas.root.RealAlgebraicNumber<C>> crr : idr.ran) { 188 //System.out.println("crr = " + crr); 189 RealRootTuple<C> root = new RealRootTuple<C>(crr); 190 //System.out.println("root = " + root); 191 RealAlgebraicRing<C> car = new RealAlgebraicRing<C>(idu, root); 192 //System.out.println("car = " + car); 193 List<RealAlgebraicNumber<C>> gens = car.generators(); 194 //System.out.println("gens = " + gens); 195 int sg = gens.size(); 196 RealAlgebraicNumber<C> rre = gens.get(sg - 2); 197 RealAlgebraicNumber<C> rim = gens.get(sg - 1); 198 ComplexRing<RealAlgebraicNumber<C>> cring = new ComplexRing<RealAlgebraicNumber<C>>(car); 199 Complex<RealAlgebraicNumber<C>> crn = new Complex<RealAlgebraicNumber<C>>(cring, rre, rim); 200 //System.out.println("crn = " + crn + " in " + crn.ring); 201 // refine intervals if necessary, not meaningful 202 list.add(crn); 203 } 204 } 205 return list; 206 } 207 208 209 /* approximation ? 210 List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex(GenPolynomial<Complex<C>> f, BigRational eps) 211 */ 212 213 214 /** 215 * Root reduce of real and complex algebraic numbers. 216 * @param a container of real and complex algebraic numbers. 217 * @param b container of real and complex algebraic numbers. 218 * @return container of real and complex algebraic numbers 219 * of the primitive element of a and b. 220 */ 221 public static <C extends GcdRingElem<C> & Rational> 222 AlgebraicRootsPrimElem<C> rootReduce(AlgebraicRoots<C> a, AlgebraicRoots<C> b) { 223 return rootReduce(a.getAlgebraicRing(), b.getAlgebraicRing()); 224 } 225 226 227 /** 228 * Root reduce of real and complex algebraic numbers. 229 * @param a polynomial. 230 * @param b polynomial. 231 * @return container of real and complex algebraic numbers 232 * of the primitive element of a and b. 233 */ 234 public static <C extends GcdRingElem<C> & Rational> 235 AlgebraicRootsPrimElem<C> rootReduce(GenPolynomial<C> a, GenPolynomial<C> b) { 236 AlgebraicNumberRing<C> anr = new AlgebraicNumberRing<C>(a); 237 AlgebraicNumberRing<C> bnr = new AlgebraicNumberRing<C>(b); 238 return rootReduce(anr, bnr); 239 } 240 241 242 /** 243 * Root reduce of real and complex algebraic numbers. 244 * @param a algebraic number ring. 245 * @param b algebraic number ring. 246 * @return container of real and complex algebraic numbers 247 * of the primitive element of a and b. 248 */ 249 public static <C extends GcdRingElem<C> & Rational> 250 AlgebraicRootsPrimElem<C> rootReduce(AlgebraicNumberRing<C> a, AlgebraicNumberRing<C> b) { 251 PrimitiveElement<C> pe = PolyUtilApp.<C>primitiveElement(a, b); 252 AlgebraicRoots<C> ar = edu.jas.root.RootFactory.<C>algebraicRoots(pe.primitiveElem.modul); 253 return new AlgebraicRootsPrimElem<C>(ar, pe); 254 } 255 256 257 /** 258 * Roots of unity of real and complex algebraic numbers. 259 * @param ar container of real and complex algebraic numbers with primitive element. 260 * @return container of real and complex algebraic numbers which are roots 261 * of unity. 262 */ 263 public static <C extends GcdRingElem<C> & Rational> 264 AlgebraicRootsPrimElem<C> rootsOfUnity(AlgebraicRootsPrimElem<C> ar) { 265 AlgebraicRoots<C> ur = edu.jas.root.RootFactory.rootsOfUnity(ar); 266 if (ar.pelem == null) { 267 return new AlgebraicRootsPrimElem<C>(ur, ar.pelem); 268 } 269 List<AlgebraicNumber<C>> al = new ArrayList<AlgebraicNumber<C>>(); 270 long d = ar.pelem.primitiveElem.modul.degree(); 271 AlgebraicNumber<C> c = ar.pelem.A; 272 AlgebraicNumber<C> m = c.ring.getONE(); 273 for (long i = 1; i <= d; i++) { 274 m = m.multiply(c); 275 if (m.isRootOfUnity()) { 276 if (!al.contains(m)) { 277 al.add(m); 278 } 279 } 280 } 281 c = ar.pelem.B; 282 m = c.ring.getONE(); 283 for (long i = 1; i <= d; i++) { 284 m = m.multiply(c); 285 if (m.isRootOfUnity()) { 286 if (!al.contains(m)) { 287 al.add(m); 288 } 289 } 290 } 291 return new AlgebraicRootsPrimElem<C>(ur, ar.pelem, al); 292 } 293 294}