001/*
002 * $Id: RealRootTest.java 5310 2015-10-25 18:35:31Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import junit.framework.Test;
013import junit.framework.TestCase;
014import junit.framework.TestSuite;
015
016import edu.jas.arith.BigDecimal;
017import edu.jas.arith.BigRational;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.TermOrder;
021import edu.jas.structure.Power;
022
023
024/**
025 * RealRoot tests with JUnit.
026 * @author Heinz Kredel.
027 */
028
029public class RealRootTest extends TestCase {
030
031
032    /**
033     * main.
034     */
035    public static void main(String[] args) {
036        junit.textui.TestRunner.run(suite());
037    }
038
039
040    /**
041     * Constructs a <CODE>RealRootTest</CODE> object.
042     * @param name String.
043     */
044    public RealRootTest(String name) {
045        super(name);
046    }
047
048
049    /**
050     */
051    public static Test suite() {
052        TestSuite suite = new TestSuite(RealRootTest.class);
053        return suite;
054    }
055
056
057    TermOrder to = new TermOrder(TermOrder.INVLEX);
058
059
060    GenPolynomialRing<BigRational> dfac;
061
062
063    BigRational ai;
064
065
066    BigRational bi;
067
068
069    BigRational ci;
070
071
072    BigRational di;
073
074
075    BigRational ei;
076
077
078    BigRational eps;
079
080
081    GenPolynomial<BigRational> a;
082
083
084    GenPolynomial<BigRational> b;
085
086
087    GenPolynomial<BigRational> c;
088
089
090    GenPolynomial<BigRational> d;
091
092
093    GenPolynomial<BigRational> e;
094
095
096    int rl = 1;
097
098
099    int kl = 5;
100
101
102    int ll = 7;
103
104
105    int el = 7;
106
107
108    float q = 0.7f;
109
110
111    @Override
112    protected void setUp() {
113        a = b = c = d = e = null;
114        ai = bi = ci = di = ei = null;
115        String[] vars = new String[] { "x" };
116        dfac = new GenPolynomialRing<BigRational>(new BigRational(1), rl, to, vars);
117        // eps = new BigRational(1L,1000000L*1000000L*1000000L);
118        eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
119    }
120
121
122    @Override
123    protected void tearDown() {
124        a = b = c = d = e = null;
125        ai = bi = ci = di = ei = null;
126        dfac = null;
127        eps = null;
128    }
129
130
131    /**
132     * Test Sturm sequence.
133     * 
134     */
135    public void testSturmSequence() {
136        a = dfac.random(kl, ll, el, q);
137        //System.out.println("a = " + a);
138
139        RealRootsSturm<BigRational> rrs = new RealRootsSturm<BigRational>();
140
141        List<GenPolynomial<BigRational>> S = rrs.sturmSequence(a);
142        //System.out.println("S = " + S);
143
144        try {
145            b = a.remainder(S.get(0));
146        } catch (Exception e) {
147            fail("not S(0)|f " + e);
148        }
149        assertTrue("a mod S(0) == 0 ", b.isZERO());
150
151        assertTrue("S(-1) == 1 ", S.get(S.size() - 1).isConstant());
152    }
153
154
155    /**
156     * Test root bound.
157     * 
158     */
159    public void testRootBound() {
160        a = dfac.random(kl, ll, el, q);
161        //System.out.println("a = " + a);
162
163        RealRoots<BigRational> rr = new RealRootsSturm<BigRational>();
164
165        BigRational M = rr.realRootBound(a);
166
167        //System.out.println("M = " + M);
168        assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0);
169
170        a = a.monic();
171        //System.out.println("a = " + a);
172        M = rr.realRootBound(a);
173
174        //System.out.println("M = " + M);
175        assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0);
176    }
177
178
179    /**
180     * Test real root isolation.
181     * 
182     */
183    public void testRealRootIsolation() {
184        a = dfac.random(kl, ll * 2, el * 2, q);
185        //a = a.multiply( dfac.univariate(0) );
186        //System.out.println("a = " + a);
187
188        RealRoots<BigRational> rr = new RealRootsSturm<BigRational>();
189
190        List<Interval<BigRational>> R = rr.realRoots(a);
191        //System.out.println("R = " + R);
192        //assertTrue("#roots >= 0 ", R.size() >= 0);
193        assertTrue("#roots >= 0 ", R != null);
194    }
195
196
197    /**
198     * Test real root isolation Wilkinson polynomials.
199     * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n)
200     */
201    public void testRealRootIsolationWilkinson() {
202        final int N = 10;
203        d = dfac.getONE();
204        e = dfac.univariate(0);
205
206        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
207        a = d;
208        for (int i = 0; i < N; i++) {
209            c = dfac.fromInteger(i);
210            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
211            b = e.subtract(c);
212            a = a.multiply(b);
213        }
214        //System.out.println("a = " + a);
215
216        RealRoots<BigRational> rr = new RealRootsSturm<BigRational>();
217
218        List<Interval<BigRational>> R = rr.realRoots(a);
219        //System.out.println("R = " + R);
220
221        assertTrue("#roots = " + N + " ", R.size() == N);
222
223        //System.out.println("eps = " + eps);
224        //BigDecimal eps1 = new BigDecimal(eps);
225        //System.out.println("eps1 = " + eps1);
226
227        R = rr.refineIntervals(R, a, eps);
228        //System.out.println("R = " + R);
229        int i = 0;
230        for (Interval<BigRational> v : R) {
231            BigDecimal dd = v.toDecimal(); //.sum(eps1);
232            BigDecimal di = Rn.get(i++).toDecimal();
233            //System.out.println("v  = " + dd);
234            //System.out.println("vi = " + di);
235            assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
236        }
237    }
238
239
240    /**
241     * Test real root isolation Wilkinson polynomials inverse.
242     * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n)
243     */
244    public void testRealRootIsolationWilkinsonInverse() {
245        final int N = 9;
246        d = dfac.getONE();
247        e = dfac.univariate(0);
248
249        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
250        a = d;
251        for (int i = 1; i < N; i++) { // use only for i > 0, since reverse
252            c = dfac.fromInteger(i);
253            if (i != 0) {
254                c = d.divide(c);
255            }
256            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
257            b = e.subtract(c);
258            a = a.multiply(b);
259        }
260        //System.out.println("a = " + a);
261        //System.out.println("Rn = " + Rn);
262        Collections.reverse(Rn);
263        //System.out.println("Rn = " + Rn);
264
265        RealRoots<BigRational> rr = new RealRootsSturm<BigRational>();
266
267        List<Interval<BigRational>> R = rr.realRoots(a);
268        //System.out.println("R = " + R);
269
270        assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1));
271
272        //System.out.println("eps = " + eps);
273        //BigDecimal eps1 = new BigDecimal(eps);
274        //System.out.println("eps1 = " + eps1);
275
276        R = rr.refineIntervals(R, a, eps);
277        //System.out.println("R = " + R);
278        int i = 0;
279        for (Interval<BigRational> v : R) {
280            BigDecimal dd = v.toDecimal(); //.sum(eps1);
281            BigDecimal di = Rn.get(i++).toDecimal();
282            //System.out.println("v  = " + dd);
283            //System.out.println("vi = " + di);
284            assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
285        }
286    }
287
288
289    /**
290     * Test real algebraic number sign.
291     * 
292     */
293    public void testRealAlgebraicNumberSign() {
294        d = dfac.fromInteger(2);
295        e = dfac.univariate(0);
296
297        a = e.multiply(e);
298        // a = a.multiply(e).multiply(e).multiply(e);
299        a = a.subtract(d); // x^2 -2
300        //System.out.println("a = " + a);
301
302        RealRoots<BigRational> rr = new RealRootsSturm<BigRational>();
303
304        ai = new BigRational(1);
305        bi = new BigRational(2);
306        Interval<BigRational> iv = new Interval<BigRational>(ai, bi);
307        //System.out.println("iv = " + iv);
308        assertTrue("sign change", rr.signChange(iv, a));
309
310        b = dfac.random(kl, (int) a.degree() + 1, (int) a.degree(), 1.0f);
311        //b = dfac.getZERO();
312        //b = dfac.random(kl,ll,el,q);
313        //b = b.multiply(b);
314        //b = b.abs().negate();
315        //System.out.println("b = " + b);
316        if (b.isZERO()) {
317            int s = rr.realSign(iv, a, b);
318            assertTrue("algebraic sign", s == 0);
319            return;
320        }
321
322        int as = rr.realSign(iv, a, b);
323        //System.out.println("as = " + as);
324        // how to test?
325        int asn = rr.realSign(iv, a, b.negate());
326        //System.out.println("asn = " + asn);
327        assertTrue("algebraic sign", as != asn);
328
329        iv = new Interval<BigRational>(bi.negate(), ai.negate());
330        //System.out.println("iv = " + iv);
331        assertTrue("sign change", rr.signChange(iv, a));
332
333        int as1 = rr.realSign(iv, a, b);
334        //System.out.println("as1 = " + as1);
335        // how to test?
336        int asn1 = rr.realSign(iv, a, b.negate());
337        //System.out.println("asn1 = " + asn1);
338        assertTrue("algebraic sign", as1 != asn1);
339
340        assertTrue("algebraic sign", as * as1 == asn * asn1);
341    }
342
343
344    /**
345     * Test real root isolation and decimal refinement of Wilkinson polynomials.
346     * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n)
347     */
348    public void testRealRootIsolationDecimalWilkinson() {
349        final int N = 10;
350        d = dfac.getONE();
351        e = dfac.univariate(0);
352
353        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
354        a = d;
355        for (int i = 0; i < N; i++) {
356            c = dfac.fromInteger(i);
357            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
358            b = e.subtract(c);
359            a = a.multiply(b);
360        }
361        //System.out.println("a = " + a);
362
363        RealRootsAbstract<BigRational> rr = new RealRootsSturm<BigRational>();
364
365        List<Interval<BigRational>> R = rr.realRoots(a);
366        //System.out.println("R = " + R);
367
368        assertTrue("#roots = " + N + " ", R.size() == N);
369
370        eps = eps.multiply(new BigRational(100000));
371        //System.out.println("eps = " + eps);
372        BigDecimal eps1 = new BigDecimal(eps);
373        BigDecimal eps2 = eps1.multiply(new BigDecimal("100"));
374        //System.out.println("eps1 = " + eps1);
375        //System.out.println("eps2 = " + eps2);
376
377        try {
378            int i = 0;
379            for (Interval<BigRational> v : R) {
380                //System.out.println("v = " + v);
381                BigDecimal dd = rr.approximateRoot(v,a,eps);
382                BigDecimal di = Rn.get(i++).toDecimal();
383                //System.out.println("di = " + di);
384                //System.out.println("dd = " + dd);
385                assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0);
386            }
387        } catch (NoConvergenceException e) {
388            fail(e.toString());
389        }
390    }
391
392
393    /**
394     * Test real root isolation and decimal refinement of Wilkinson polynomials, inverse roots.
395     * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n)
396     */
397    public void testRealRootIsolationDecimalWilkinsonInverse() {
398        final int N = 10;
399        d = dfac.getONE();
400        e = dfac.univariate(0);
401
402        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
403        a = d;
404        for (int i = 1; i < N; i++) { // use only for i > 0, since reverse
405            c = dfac.fromInteger(i);
406            if (i != 0) {
407                c = d.divide(c);
408            }
409            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
410            b = e.subtract(c);
411            a = a.multiply(b);
412        }
413        //System.out.println("a = " + a);
414        //System.out.println("Rn = " + Rn);
415        Collections.reverse(Rn);
416        //System.out.println("Rn = " + Rn);
417
418        RealRootsAbstract<BigRational> rr = new RealRootsSturm<BigRational>();
419
420        List<Interval<BigRational>> R = rr.realRoots(a);
421        //System.out.println("R = " + R);
422
423        assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1));
424
425        eps = eps.multiply(new BigRational(1000000));
426        //System.out.println("eps = " + eps);
427        BigDecimal eps1 = new BigDecimal(eps);
428        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
429        //System.out.println("eps1 = " + eps1);
430        //System.out.println("eps2 = " + eps2);
431
432        try {
433            int i = 0;
434            for (Interval<BigRational> v : R) {
435                //System.out.println("v = " + v);
436                BigDecimal dd = rr.approximateRoot(v,a,eps);
437                BigDecimal di = Rn.get(i++).toDecimal();
438                //System.out.println("di = " + di);
439                //System.out.println("dd = " + dd);
440                assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0);
441            }
442        } catch (NoConvergenceException e) {
443            fail(e.toString());
444        }
445    }
446
447
448    /**
449     * Test real root isolation and decimal refinement of Wilkinson polynomials, all roots.
450     * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n)
451     */
452    public void testRealRootIsolationDecimalWilkinsonAll() {
453        final int N = 10; 
454        d = dfac.getONE();
455        e = dfac.univariate(0);
456
457        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
458        a = d;
459        for (int i = 0; i < N; i++) {
460            c = dfac.fromInteger(i);
461            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
462            b = e.subtract(c);
463            a = a.multiply(b);
464        }
465        //System.out.println("a = " + a);
466
467        RealRootsAbstract<BigRational> rr = new RealRootsSturm<BigRational>();
468
469        eps = eps.multiply(new BigRational(10000));
470        //System.out.println("eps = " + eps);
471        BigDecimal eps1 = new BigDecimal(eps);
472        BigDecimal eps2 = eps1.multiply(new BigDecimal("100"));
473        //System.out.println("eps1 = " + eps1);
474        //System.out.println("eps2 = " + eps2);
475
476        List<BigDecimal> R = null;
477        R = rr.approximateRoots(a,eps);
478        //System.out.println("R = " + R);
479        assertTrue("#roots = " + N + " ", R.size() == N);
480
481        int i = 0;
482        for (BigDecimal dd : R) {
483            //System.out.println("dd = " + dd);
484            BigDecimal di = Rn.get(i++).toDecimal();
485            //System.out.println("di = " + di);
486            assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0);
487        }
488        boolean t = rr.isApproximateRoot(R,a,eps);
489        assertTrue("some |a(dd)| < eps ", t);
490    }
491
492
493    /**
494     * Test real root isolation and decimal refinement of Wilkinson polynomials, inverse roots, all roots.
495     * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n)
496     */
497    public void testRealRootIsolationDecimalWilkinsonInverseAll() {
498        final int N = 10;
499        d = dfac.getONE();
500        e = dfac.univariate(0);
501
502        List<Interval<BigRational>> Rn = new ArrayList<Interval<BigRational>>(N);
503        a = d;
504        for (int i = 1; i < N; i++) { // use only for i > 0, since reverse
505            c = dfac.fromInteger(i);
506            if (i != 0) {
507                c = d.divide(c);
508            }
509            Rn.add(new Interval<BigRational>(c.leadingBaseCoefficient()));
510            b = e.subtract(c);
511            a = a.multiply(b);
512        }
513        //System.out.println("a = " + a);
514        //System.out.println("Rn = " + Rn);
515        Collections.reverse(Rn);
516        //System.out.println("Rn = " + Rn);
517
518        RealRootsAbstract<BigRational> rr = new RealRootsSturm<BigRational>();
519
520        eps = eps.multiply(new BigRational(1000000));
521        //System.out.println("eps = " + eps);
522        BigDecimal eps1 = new BigDecimal(eps);
523        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
524        //System.out.println("eps1 = " + eps1);
525        //System.out.println("eps2 = " + eps2);
526
527        List<BigDecimal> R = null;
528        R = rr.approximateRoots(a,eps);
529        //System.out.println("R = " + R);
530        assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1));
531
532        int i = 0;
533        for (BigDecimal dd : R) {
534            //System.out.println("dd = " + dd);
535            BigDecimal di = Rn.get(i++).toDecimal();
536            //System.out.println("di = " + di);
537            assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0);
538        }
539        boolean t = rr.isApproximateRoot(R,a,eps);
540        assertTrue("some |a(dd)| < eps ", t);
541    }
542
543}