001/*
002 * $Id$
003 */
004
005package edu.jas.application;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import edu.jas.arith.BigDecimal;
012import edu.jas.arith.BigRational;
013import edu.jas.kern.ComputerThreads;
014import edu.jas.poly.Complex;
015import edu.jas.poly.ComplexRing;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.poly.PolyUtil;
019import edu.jas.poly.TermOrder;
020import edu.jas.structure.Power;
021import edu.jas.ufd.Squarefree;
022import edu.jas.ufd.SquarefreeFactory;
023
024import junit.framework.Test;
025import junit.framework.TestCase;
026import junit.framework.TestSuite;
027
028
029/**
030 * RootUtil tests with JUnit.
031 * @author Heinz Kredel
032 */
033
034public class ComplexRootTest extends TestCase {
035
036
037    /**
038     * main.
039     */
040    public static void main(String[] args) {
041
042        junit.textui.TestRunner.run(suite());
043        ComputerThreads.terminate();
044    }
045
046
047    /**
048     * Constructs a <CODE>ComplexRootTest</CODE> object.
049     * @param name String.
050     */
051    public ComplexRootTest(String name) {
052        super(name);
053    }
054
055
056    /**
057     */
058    public static Test suite() {
059        TestSuite suite = new TestSuite(ComplexRootTest.class);
060        return suite;
061    }
062
063
064    TermOrder to = new TermOrder(TermOrder.INVLEX);
065
066
067    GenPolynomialRing<BigRational> rfac;
068
069
070    GenPolynomialRing<Complex<BigRational>> dfac;
071
072
073    ComplexRing<BigRational> cfac;
074
075
076    BigRational eps;
077
078
079    Complex<BigRational> ceps;
080
081
082    BigDecimal deps;
083
084
085    GenPolynomial<Complex<BigRational>> a, b, c, d, e;
086
087
088    int rl = 1;
089
090
091    int kl = 3;
092
093
094    int ll = 3;
095
096
097    int el = 5;
098
099
100    float q = 0.7f;
101
102
103    @Override
104    protected void setUp() {
105        a = b = c = d = e = null;
106        cfac = new ComplexRing<BigRational>(new BigRational(1));
107        String[] vars = new String[] { "z" };
108        dfac = new GenPolynomialRing<Complex<BigRational>>(cfac, to, vars);
109        rfac = new GenPolynomialRing<BigRational>(new BigRational(1), to, vars);
110        eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
111        ceps = new Complex<BigRational>(cfac, eps);
112        deps = new BigDecimal(
113                        Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION - 2));
114    }
115
116
117    @Override
118    protected void tearDown() {
119        a = b = c = d = e = null;
120        dfac = null;
121        cfac = null;
122        eps = null;
123    }
124
125
126    /**
127     * Test complex roots, imaginary.
128     */
129    public void testComplexRootsImag() {
130        //Complex<BigRational> I = cfac.getIMAG(); 
131        //a = dfac.parse("z^3 - i2"); 
132        //a = dfac.random(ll+1).monic();
133        //a = dfac.parse("z^7 - 2 z");
134        a = dfac.parse("z^6 - i3");
135        //System.out.println("a = " + a);
136
137        List<Complex<RealAlgebraicNumber<BigRational>>> roots;
138        roots = RootFactoryApp.<BigRational> complexAlgebraicNumbersComplex(a);
139        //System.out.println("a = " + a);
140        //System.out.println("roots = " + roots);
141        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
142        for (Complex<RealAlgebraicNumber<BigRational>> root : roots) {
143            //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " + root.getIm().decimalMagnitude() + " i");
144            assertTrue("f(r) == 0: " + root, RootFactoryApp.<BigRational> isRoot(a, root));
145        }
146    }
147
148
149    /*
150     * Test complex roots, random polynomial.
151     */
152    public void testComplexRootsRand() {
153        //Complex<BigRational> I = cfac.getIMAG(); 
154        a = dfac.random(2, ll, el, 0.37f).monic();
155        if (a.isZERO() || a.isONE()) {
156            a = dfac.parse("z^6 - i3");
157        }
158        //a = dfac.parse("z^3 - ( 1600/6123i-280/2041 )"); // fail, todo
159        //a = dfac.parse("z^3 - ( 1600/6123 )"); // fail, shows only one root
160        //a = dfac.parse("z^3 - ( 16/32i-280/2041 )"); // okay, 3 roots
161        Squarefree<Complex<BigRational>> sqf = SquarefreeFactory
162                        .<Complex<BigRational>> getImplementation(cfac);
163        a = sqf.squarefreePart(a);
164        //System.out.println("a = " + a);
165        List<Complex<RealAlgebraicNumber<BigRational>>> roots;
166        roots = RootFactoryApp.<BigRational> complexAlgebraicNumbersComplex(a);
167        //roots = RootFactoryApp.<BigRational> complexAlgebraicNumbersSquarefree(a);
168        //System.out.println("a = " + a);
169        //System.out.println("roots = " + roots);
170        assertTrue("#roots - deg(a): " + (roots.size() - a.degree(0)) + ", a = " + a,
171                        roots.size() == a.degree(0));
172        for (Complex<RealAlgebraicNumber<BigRational>> root : roots) {
173            //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " + root.getIm().decimalMagnitude() + " i");
174            assertTrue("f(r) == 0: " + root, RootFactoryApp.<BigRational> isRoot(a, root));
175        }
176    }
177
178
179    /**
180     * Test polynomial with complex roots.
181     */
182    public void testPolynomialComplexRoots() {
183        a = dfac.parse("z^3 - 2");
184        //System.out.println("a = " + a);
185        List<Complex<RealAlgebraicNumber<BigRational>>> roots = RootFactoryApp
186                        .<BigRational> complexAlgebraicNumbersComplex(a);
187        //System.out.println("a = " + a);
188        //System.out.println("roots = " + roots);
189        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
190        for (Complex<RealAlgebraicNumber<BigRational>> car : roots) {
191            //System.out.println("car = " + car);
192            RealAlgebraicRing<BigRational> rfac = car.getRe().ring;
193            rfac.setField(true); // ?? to check
194            assertTrue("isField(rfac) ", rfac.isField());
195            assertTrue("f(r) == 0: " + car, RootFactoryApp.<BigRational> isRoot(a, car));
196        }
197        Complex<RealAlgebraicNumber<BigRational>> root = roots.get(2); // 0,1,2)
198        //System.out.println("a = " + a);
199        //System.out.println("root = " + root.getRe().decimalMagnitude() + " + "
200        //                  + root.getIm().decimalMagnitude() + " i");
201        //System.out.println("root = " + root.getRe() + " + " + root.getIm() + " i");
202        //String vre = root.getRe().toString().replace("{", "").replace("}", "").trim();
203        //String vim = root.getIm().toString().replace("{", "").replace("}", "").trim();
204        //System.out.println("vre = " + vre);
205        //System.out.println("vim = " + vim);
206        //String IM = root.ring.getIMAG().toString().replace("{", "").replace("}", "").replace(" ", "").trim();
207        //System.out.println("IM  = " + IM);
208
209        GenPolynomialRing<Complex<RealAlgebraicNumber<BigRational>>> cring = new GenPolynomialRing<Complex<RealAlgebraicNumber<BigRational>>>(
210                        root.ring, to, new String[] { "t" });
211        //List<GenPolynomial<Complex<RealAlgebraicNumber<BigRational>>>> gens = cring.generators();
212        //System.out.println("gens  = " + gens);
213
214        GenPolynomial<Complex<RealAlgebraicNumber<BigRational>>> cpol;
215        //cpol = cring.random(1, 4, 4, q);
216
217        //cpol = cring.univariate(0,3L).subtract(cring.fromInteger(2L));
218        //cpol = cring.univariate(0,3L).subtract(gens.get(2));
219        //cpol = cring.univariate(0,5L).subtract(cring.univariate(0,2L).multiply(root));
220        //cpol = cring.univariate(0,4L).subtract(root);
221        //cpol = cring.univariate(0,4L).subtract(root.multiply(root));
222        //cpol = cring.univariate(0,3L).subtract(cring.univariate(0,1L).multiply(root).sum(root.multiply(root)));
223        cpol = cring.univariate(0, 2L).subtract(root.multiply(root)); // okay
224        //cpol = cring.univariate(0,3L).subtract(root.multiply(root)); // okay
225        //cpol = cring.univariate(0,3L).subtract(root.multiply(root).multiply(root)); // not much sense r^3 = 2
226        ///String vpol = vre + " + " + IM + " " + vim;
227        //String vpol = " 3 + " + IM + " * 3 ";
228        //String vpol = " 3i3 ";
229        //String vpol = IM + " " + vim;
230        //String vpol = " 2 ";// + vre; // + " " + IM;
231        //String vpol = vre; // + " " + IM;
232        //System.out.println("vpol = " + vpol);
233        //cpol = cring.univariate(0, 3L).subtract(cring.parse(vpol));
234        cpol = cpol.monic();
235        //System.out.println("cpol = " + cpol);
236        //long dd = cpol.degree(0);
237        Squarefree<Complex<RealAlgebraicNumber<BigRational>>> sen = SquarefreeFactory
238                        .<Complex<RealAlgebraicNumber<BigRational>>> getImplementation(root.ring);
239        cpol = sen.squarefreePart(cpol);
240        //if (cpol.degree(0) < dd) {
241        //System.out.println("cpol = " + cpol);
242        //}
243        //System.out.println("cpol = " + cpol);
244
245        // new version with recursion: with real factorization
246        long t1 = System.currentTimeMillis();
247        List<Complex<RealAlgebraicNumber<RealAlgebraicNumber<BigRational>>>> croots = RootFactoryApp
248                        .<RealAlgebraicNumber<BigRational>> complexAlgebraicNumbersComplex(cpol);
249        t1 = System.currentTimeMillis() - t1;
250        assertTrue("nonsense " + t1, t1 >= 0L);
251        //System.out.println("\na = " + a.toScript());
252        //System.out.println("root = " + root.getRe().decimalMagnitude() + " + "
253        //                             + root.getIm().decimalMagnitude() + " i");
254        //System.out.println("a = " + a);
255        //System.out.println("root = " + root.getRe().decimalMagnitude() + " + "
256        //                  + root.getIm().decimalMagnitude() + " i");
257        //System.out.println("root = " + root.getRe() + " + (" + root.getIm() + ") i");
258        //System.out.println("root.ring = " + root.ring);
259        //System.out.println("cpol      = " + cpol);
260        //System.out.println("cpol.ring = " + cpol.ring);
261        //System.out.println("croots = " + croots);
262        for (Complex<RealAlgebraicNumber<RealAlgebraicNumber<BigRational>>> croot : croots) {
263            //System.out.println("croot = " + croot);
264            //System.out.println("croot = " + croot.getRe() + " + ( " + croot.getIm() + ") i");
265            //System.out.println("croot.ring = " + croot.ring); //magnitude());
266            //System.out.println("croot = " + croot.getRe().decimalMagnitude() + " + "
267            //                              + croot.getIm().decimalMagnitude() + " i");
268            assertTrue("f(r) == 0: " + croot,
269                            RootFactoryApp.<RealAlgebraicNumber<BigRational>> isRoot(cpol, croot));
270        }
271        assertTrue("#croots == deg(cpol) " + croots.size() + " != " + cpol.degree(0),
272                        croots.size() == cpol.degree(0));
273
274
275        // existing version with winding number and recursion: but only one step
276        long t2 = System.currentTimeMillis();
277        List<edu.jas.root.ComplexAlgebraicNumber<RealAlgebraicNumber<BigRational>>> coroots = edu.jas.root.RootFactory
278                        .<RealAlgebraicNumber<BigRational>> complexAlgebraicNumbersComplex(cpol);
279        t2 = System.currentTimeMillis() - t2;
280        assertTrue("nonsense " + t2, t2 >= 0L);
281        //System.out.println("\ncpol = " + cpol);
282        //System.out.println("root = " + root.getRe() + " + (" + root.getIm() + ") i");
283        //System.out.println("root = " + root.getRe().decimalMagnitude() + " + "
284        //                             + root.getIm().decimalMagnitude() + " i");
285        for (edu.jas.root.ComplexAlgebraicNumber<RealAlgebraicNumber<BigRational>> cr2 : coroots) {
286            //System.out.println("r2.ring = " + cr2.ring); //magnitude());
287            assertTrue("f(r) == 0: " + cr2, edu.jas.root.RootFactory
288                            .<RealAlgebraicNumber<BigRational>> isRootComplex(cpol, cr2));
289        }
290
291        // decimal for comparison
292        long t3 = System.currentTimeMillis();
293        for (Complex<RealAlgebraicNumber<RealAlgebraicNumber<BigRational>>> croot : croots) {
294            String crs = croot.getRe().decimalMagnitude() + " + " + croot.getIm().decimalMagnitude() + " i";
295            //System.out.println("croot = " + crs);
296            assertFalse("crs not empty", crs.length() == 0); // java-5
297        }
298        t3 = System.currentTimeMillis() - t3;
299        assertTrue("nonsense " + t3, t3 >= 0L);
300        long t4 = System.currentTimeMillis();
301        for (edu.jas.root.ComplexAlgebraicNumber<RealAlgebraicNumber<BigRational>> cr2 : coroots) {
302            String crs = cr2.decimalMagnitude().toString();
303            //System.out.println("r2.dec  = " + crs);
304            assertFalse("crs not empty", crs.length() == 0); // java-5
305        }
306        t4 = System.currentTimeMillis() - t4;
307        assertTrue("nonsense " + t4, t4 >= 0L);
308        assertTrue("#coroots == deg(cpol) ", coroots.size() == cpol.degree(0));
309        //System.out.println("time, real ideal = " + t1 + "+" + t3 + ", complex winding = " + t2 + "+" + t4 + " milliseconds");
310    }
311
312
313    /**
314     * Test 0-dim ideal with complex roots.
315     */
316    public void testIdealComplexRoots() {
317        String[] vars = new String[] { "x", "z" };
318        rfac = new GenPolynomialRing<BigRational>(new BigRational(1), to, vars);
319        GenPolynomial<BigRational> ar, br;
320        ar = rfac.parse("z^3 - 2");
321        br = rfac.parse("x^2 - 3");
322        //System.out.println("ar = " + ar + ", deg(ar) = " + ar.degree(1));
323        //System.out.println("br = " + br + ", deg(br) = " + br.degree(0));
324        List<GenPolynomial<BigRational>> M;
325        M = new ArrayList<GenPolynomial<BigRational>>();
326        M.add(ar);
327        M.add(br);
328        //System.out.println("M = " + M);
329
330        Ideal<BigRational> I = new Ideal<BigRational>(rfac, M);
331        //System.out.println("I = " + I);
332
333        List<List<Complex<BigDecimal>>> roots = PolyUtilApp.<BigRational> complexRootTuples(I, eps);
334        //System.out.println("roots = " + roots);
335        assertEquals("#roots == deg(a)*deg(b) ", roots.size(), ar.degree(1) * br.degree(0));
336
337        a = PolyUtil.<BigRational> toComplex(dfac, ar);
338        b = PolyUtil.<BigRational> toComplex(dfac, br);
339        GenPolynomialRing<Complex<BigDecimal>> pfac;
340        pfac = new GenPolynomialRing<Complex<BigDecimal>>(new ComplexRing<BigDecimal>(new BigDecimal(1)),
341                        rfac);
342        GenPolynomial<Complex<BigDecimal>> ac, bc;
343        ac = PolyUtil.<BigRational> complexDecimalFromRational(pfac, a);
344        bc = PolyUtil.<BigRational> complexDecimalFromRational(pfac, b);
345        List<GenPolynomial<Complex<BigDecimal>>> Mc;
346        Mc = new ArrayList<GenPolynomial<Complex<BigDecimal>>>();
347        Mc.add(ac);
348        Mc.add(bc);
349        //System.out.println("Mc = " + Mc);
350        assertTrue("isComplexRoots: " + roots, PolyUtilApp.<BigRational> isComplexRoots(Mc, roots, deps));
351    }
352
353
354    /**
355     * Test 0-dim ideal with real roots.
356     */
357    public void testIdealRealRoots() {
358        String[] vars = new String[] { "x", "z" };
359        rfac = new GenPolynomialRing<BigRational>(new BigRational(1), to, vars);
360        GenPolynomial<BigRational> ar, br;
361        ar = rfac.parse("z^3 - 2");
362        br = rfac.parse("x^2 - 3");
363        //System.out.println("ar = " + ar + ", deg(ar) = " + ar.degree(1));
364        //System.out.println("br = " + br + ", deg(br) = " + br.degree(0));
365
366        List<GenPolynomial<BigRational>> M;
367        M = new ArrayList<GenPolynomial<BigRational>>();
368        M.add(ar);
369        M.add(br);
370        //System.out.println("M = " + M);
371
372        Ideal<BigRational> I = new Ideal<BigRational>(rfac, M);
373        //System.out.println("I = " + I);
374
375        List<List<BigDecimal>> roots = PolyUtilApp.<BigRational> realRootTuples(I, eps);
376        //System.out.println("roots = " + roots);
377        assertEquals("#roots == deg(a)*deg(b) ", roots.size(), 2);
378
379        GenPolynomialRing<BigDecimal> pfac;
380        pfac = new GenPolynomialRing<BigDecimal>(new BigDecimal(1), rfac);
381        List<GenPolynomial<BigDecimal>> Md;
382        Md = new ArrayList<GenPolynomial<BigDecimal>>();
383        Md.add(PolyUtil.<BigRational> decimalFromRational(pfac, ar));
384        Md.add(PolyUtil.<BigRational> decimalFromRational(pfac, br));
385        //System.out.println("Md = " + Md);
386        assertTrue("isRealRoots: " + roots, PolyUtilApp.<BigRational> isRealRoots(Md, roots, deps));
387    }
388
389}