001/*
002 * $Id: RealAlgebraicTest.java 5688 2017-01-03 08:45:09Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.log4j.BasicConfigurator;
012
013import edu.jas.arith.BigDecimal;
014import edu.jas.arith.BigRational;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.structure.NotInvertibleException;
018import edu.jas.structure.Power;
019
020import junit.framework.Test;
021import junit.framework.TestCase;
022import junit.framework.TestSuite;
023
024
025/**
026 * RealAlgebraicNumber Test using JUnit.
027 * @author Heinz Kredel
028 */
029
030public class RealAlgebraicTest extends TestCase {
031
032
033    /**
034     * main.
035     */
036    public static void main(String[] args) {
037        BasicConfigurator.configure();
038        junit.textui.TestRunner.run(suite());
039    }
040
041
042    /**
043     * Constructs a <CODE>RealAlgebraicTest</CODE> object.
044     * @param name String.
045     */
046    public RealAlgebraicTest(String name) {
047        super(name);
048    }
049
050
051    /**
052     * suite.
053     */
054    public static Test suite() {
055        TestSuite suite = new TestSuite(RealAlgebraicTest.class);
056        return suite;
057    }
058
059
060    //private final static int bitlen = 100;
061
062    RealAlgebraicRing<BigRational> fac;
063
064
065    GenPolynomialRing<BigRational> mfac;
066
067
068    RealAlgebraicNumber<BigRational> a;
069
070
071    RealAlgebraicNumber<BigRational> b;
072
073
074    RealAlgebraicNumber<BigRational> c;
075
076
077    RealAlgebraicNumber<BigRational> d;
078
079
080    RealAlgebraicNumber<BigRational> e;
081
082
083    RealAlgebraicNumber<BigRational> alpha;
084
085
086    int rl = 1;
087
088
089    int kl = 10;
090
091
092    int ll = 10;
093
094
095    int el = ll;
096
097
098    float q = 0.5f;
099
100
101    @Override
102    protected void setUp() {
103        a = b = c = d = e = null;
104        BigRational l = new BigRational(1);
105        BigRational r = new BigRational(2);
106        Interval<BigRational> positiv = new Interval<BigRational>(l, r);
107        String[] vars = new String[] { "alpha" };
108        mfac = new GenPolynomialRing<BigRational>(new BigRational(1), rl, vars);
109        GenPolynomial<BigRational> mo = mfac.univariate(0, 2);
110        mo = mo.subtract(mfac.fromInteger(2)); // alpha^2 -2 
111        fac = new RealAlgebraicRing<BigRational>(mo, positiv);
112        alpha = fac.getGenerator();
113    }
114
115
116    @Override
117    protected void tearDown() {
118        a = b = c = d = e = null;
119        fac = null;
120        alpha = null;
121    }
122
123
124    /**
125     * Test constructor and toString.
126     * 
127     */
128    public void testConstruction() {
129        c = fac.getONE();
130        //System.out.println("c = " + c);
131        //System.out.println("c.getVal() = " + c.getVal());
132        assertTrue("length( c ) = 1", c.number.getVal().length() == 1);
133        assertTrue("isZERO( c )", !c.isZERO());
134        assertTrue("isONE( c )", c.isONE());
135
136        d = fac.getZERO();
137        //System.out.println("d = " + d);
138        //System.out.println("d.getVal() = " + d.getVal());
139        assertTrue("length( d ) = 0", d.number.getVal().length() == 0);
140        assertTrue("isZERO( d )", d.isZERO());
141        assertTrue("isONE( d )", !d.isONE());
142    }
143
144
145    /**
146     * Test random polynomial.
147     * 
148     */
149    public void testRandom() {
150        for (int i = 0; i < 7; i++) {
151            a = fac.random(el);
152            //System.out.println("a = " + a);
153            if (a.isZERO() || a.isONE()) {
154                continue;
155            }
156            // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q );
157            assertTrue("length( a" + i + " ) <> 0", a.number.getVal().length() >= 0);
158            assertTrue(" not isZERO( a" + i + " )", !a.isZERO());
159            assertTrue(" not isONE( a" + i + " )", !a.isONE());
160        }
161    }
162
163
164    /**
165     * Test addition.
166     * 
167     */
168    public void testAddition() {
169        a = fac.random(ll);
170        b = fac.random(ll);
171
172        c = a.sum(b);
173        d = c.subtract(b);
174        assertEquals("a+b-b = a", a, d);
175
176        c = a.sum(b);
177        d = b.sum(a);
178        assertEquals("a+b = b+a", c, d);
179
180        c = fac.random(ll);
181        d = c.sum(a.sum(b));
182        e = c.sum(a).sum(b);
183        assertEquals("c+(a+b) = (c+a)+b", d, e);
184
185
186        c = a.sum(fac.getZERO());
187        d = a.subtract(fac.getZERO());
188        assertEquals("a+0 = a-0", c, d);
189
190        c = fac.getZERO().sum(a);
191        d = fac.getZERO().subtract(a.negate());
192        assertEquals("0+a = 0+(-a)", c, d);
193    }
194
195
196    /**
197     * Test object multiplication.
198     * 
199     */
200    public void testMultiplication() {
201        a = fac.random(ll);
202        assertTrue("not isZERO( a )", !a.isZERO());
203
204        b = fac.random(ll);
205        assertTrue("not isZERO( b )", !b.isZERO());
206
207        c = b.multiply(a);
208        d = a.multiply(b);
209        assertTrue("not isZERO( c )", !c.isZERO());
210        assertTrue("not isZERO( d )", !d.isZERO());
211
212        //System.out.println("a = " + a);
213        //System.out.println("b = " + b);
214        e = d.subtract(c);
215        assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO());
216
217        assertTrue("a*b = b*a", c.equals(d));
218        assertEquals("a*b = b*a", c, d);
219
220        c = fac.random(ll);
221        //System.out.println("c = " + c);
222        d = a.multiply(b.multiply(c));
223        e = (a.multiply(b)).multiply(c);
224
225        //System.out.println("d = " + d);
226        //System.out.println("e = " + e);
227
228        //System.out.println("d-e = " + d.subtract(c) );
229
230        assertEquals("a(bc) = (ab)c", d, e);
231        assertTrue("a(bc) = (ab)c", d.equals(e));
232
233        c = a.multiply(fac.getONE());
234        d = fac.getONE().multiply(a);
235        assertEquals("a*1 = 1*a", c, d);
236
237
238        c = a.inverse();
239        d = c.multiply(a);
240        //System.out.println("a = " + a);
241        //System.out.println("c = " + c);
242        //System.out.println("d = " + d);
243        assertEquals("a*1/a = 1", fac.getONE(), d);
244
245        try {
246            a = fac.getZERO().inverse();
247        } catch (NotInvertibleException expected) {
248            return;
249        }
250        fail("0 invertible");
251    }
252
253
254    /**
255     * Test distributive law.
256     * 
257     */
258    public void testDistributive() {
259        a = fac.random(ll);
260        b = fac.random(ll);
261        c = fac.random(ll);
262
263        d = a.multiply(b.sum(c));
264        e = a.multiply(b).sum(a.multiply(c));
265
266        assertEquals("a(b+c) = ab+ac", d, e);
267    }
268
269
270    /**
271     * Test sign of real algebraic numbers.
272     * 
273     */
274    public void testSignum() {
275        a = fac.random(ll);
276        b = fac.random(ll);
277        c = fac.random(ll);
278
279        int sa = a.signum();
280        int sb = b.signum();
281        int sc = c.signum();
282
283        d = a.multiply(b);
284        e = a.multiply(c);
285
286        int sd = d.signum();
287        int se = e.signum();
288
289        assertEquals("sign(a*b) = sign(a)*sign(b) ", sa * sb, sd);
290        assertEquals("sign(a*c) = sign(a)*sign(c) ", sa * sc, se);
291
292        b = a.negate();
293        sb = b.signum();
294        assertEquals("sign(-a) = -sign(a) ", -sa, sb);
295    }
296
297
298    /**
299     * Test compareTo of real algebraic numbers.
300     * 
301     */
302    public void testCompare() {
303        a = fac.random(ll).abs();
304        b = a.sum(fac.getONE());
305        c = b.sum(fac.getONE());
306
307        int ab = a.compareTo(b);
308        int bc = b.compareTo(c);
309        int ac = a.compareTo(c);
310
311        assertTrue("a < a+1 ", ab < 0);
312        assertTrue("a+1 < a+2 ", bc < 0);
313        assertTrue("a < a+2 ", ac < 0);
314
315        a = a.negate();
316        b = a.sum(fac.getONE());
317        c = b.sum(fac.getONE());
318
319        ab = a.compareTo(b);
320        bc = b.compareTo(c);
321        ac = a.compareTo(c);
322
323        assertTrue("a < a+1 ", ab < 0);
324        assertTrue("a+1 < a+2 ", bc < 0);
325        assertTrue("a < a+2 ", ac < 0);
326    }
327
328
329    /**
330     * Test arithmetic of magnitude of real algebraic numbers.
331     * 
332     */
333    public void testMagnitude() {
334        a = fac.random(ll);
335        b = fac.random(ll);
336        c = fac.random(ll);
337
338        //BigDecimal ad = new BigDecimal(a.magnitude());
339        //BigDecimal bd = new BigDecimal(b.magnitude());
340        //BigDecimal cd = new BigDecimal(c.magnitude());
341
342        d = a.multiply(b);
343        e = a.sum(b);
344
345        BigDecimal dd = new BigDecimal(d.magnitude());
346        BigDecimal ed = new BigDecimal(e.magnitude());
347
348        BigDecimal dd1 = new BigDecimal(a.magnitude().multiply(b.magnitude()));
349        BigDecimal ed1 = new BigDecimal(a.magnitude().sum(b.magnitude()));
350
351        //System.out.println("ad  = " + ad);
352        //System.out.println("bd  = " + bd);
353        //System.out.println("cd  = " + cd);
354        //System.out.println("dd  = " + dd);
355        //System.out.println("dd1 = " + dd1);
356        //System.out.println("ed  = " + ed);
357        //System.out.println("ed1 = " + ed1);
358
359        //BigRational eps = Power.positivePower(new BigRational(1L,10L),BigDecimal.DEFAULT_PRECISION);
360        BigRational eps = Power.positivePower(new BigRational(1L, 10L), 8);
361        BigDecimal epsd = new BigDecimal(eps);
362
363        assertTrue("mag(a*b) = mag(a)*mag(b): " + dd + ", " + dd1,
364                        dd.subtract(dd1).abs().compareTo(epsd) <= 0);
365        assertTrue("mag(a+b) = mag(a)+mag(b): " + ed + ", " + ed1,
366                        ed.subtract(ed1).abs().compareTo(epsd) <= 0);
367
368
369        d = a.divide(b);
370        e = a.subtract(b);
371
372        dd = new BigDecimal(d.magnitude());
373        ed = new BigDecimal(e.magnitude());
374
375        dd1 = new BigDecimal(a.magnitude().divide(b.magnitude()));
376        ed1 = new BigDecimal(a.magnitude().subtract(b.magnitude()));
377
378        //System.out.println("dd  = " + dd);
379        //System.out.println("dd1 = " + dd1);
380        //System.out.println("ed  = " + ed);
381        //System.out.println("ed1 = " + ed1);
382
383        assertTrue("mag(a/b) = mag(a)/mag(b)", dd.subtract(dd1).abs().compareTo(epsd) <= 0);
384        assertTrue("mag(a-b) = mag(a)-mag(b)", ed.subtract(ed1).abs().compareTo(epsd) <= 0);
385    }
386
387
388    /**
389     * Test real root isolation. Tests nothing.
390     */
391    public void notestRealRootIsolation() {
392        System.out.println();
393        GenPolynomialRing<RealAlgebraicNumber<BigRational>> dfac;
394        dfac = new GenPolynomialRing<RealAlgebraicNumber<BigRational>>(fac, 1);
395
396        GenPolynomial<RealAlgebraicNumber<BigRational>> ar;
397        //RealAlgebraicNumber<BigRational> epsr;
398
399        ar = dfac.random(3, 5, 7, q);
400        System.out.println("ar = " + ar);
401
402        RealRoots<RealAlgebraicNumber<BigRational>> rrr = new RealRootsSturm<RealAlgebraicNumber<BigRational>>();
403
404        List<Interval<RealAlgebraicNumber<BigRational>>> R = rrr.realRoots(ar);
405        System.out.println("R = " + R);
406
407        //assertTrue("#roots >= 0 ", R.size() >= 0 );
408
409        BigRational eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
410        //BigRational eps = Power.positivePower(new BigRational(1L,10L),10);
411
412        R = rrr.refineIntervals(R, ar, eps);
413        //System.out.println("R = " + R);
414        for (Interval<RealAlgebraicNumber<BigRational>> v : R) {
415            BigDecimal dd = v.toDecimal(); //.sum(eps1);
416            System.out.println("v = " + dd);
417            // assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
418        }
419    }
420
421
422    /**
423     * Test real root isolation for Wilkinson like polynomials.
424     * product_{i=1..n}( x - i * alpha )
425     * 
426     */
427    public void testRealRootIsolationWilkinson() {
428        //System.out.println();
429        GenPolynomialRing<RealAlgebraicNumber<BigRational>> dfac;
430        dfac = new GenPolynomialRing<RealAlgebraicNumber<BigRational>>(fac, 1);
431
432        GenPolynomial<RealAlgebraicNumber<BigRational>> ar, br, cr, dr, er;
433
434        RealRoots<RealAlgebraicNumber<BigRational>> rrr = new RealRootsSturm<RealAlgebraicNumber<BigRational>>();
435
436        final int N = 3;
437        dr = dfac.getONE();
438        er = dfac.univariate(0);
439
440        List<Interval<RealAlgebraicNumber<BigRational>>> Rn = new ArrayList<Interval<RealAlgebraicNumber<BigRational>>>(
441                        N);
442        ar = dr;
443        for (int i = 0; i < N; i++) {
444            cr = dfac.fromInteger(i).multiply(alpha); // i * alpha
445            Rn.add(new Interval<RealAlgebraicNumber<BigRational>>(cr.leadingBaseCoefficient()));
446            br = er.subtract(cr); // ( x - i * alpha )
447            ar = ar.multiply(br);
448        }
449        //System.out.println("ar = " + ar);
450
451        List<Interval<RealAlgebraicNumber<BigRational>>> R = rrr.realRoots(ar);
452        //System.out.println("R = " + R);
453
454        assertTrue("#roots = " + N + " ", R.size() == N);
455
456        BigRational eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
457        //BigRational eps = Power.positivePower(new BigRational(1L,10L),10);
458        //System.out.println("eps = " + eps);
459
460        R = rrr.refineIntervals(R, ar, eps);
461        //System.out.println("R = " + R);
462        int i = 0;
463        for (Interval<RealAlgebraicNumber<BigRational>> v : R) {
464            BigDecimal dd = v.toDecimal();//.sum(eps1);
465            BigDecimal di = Rn.get(i++).toDecimal();
466            //System.out.println("v  = " + dd);
467            //System.out.println("vi = " + di);
468            assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
469        }
470    }
471
472}