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