001/*
002 * $Id: RealAlgebraicTest.java 4039 2012-07-25 14:35:06Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import junit.framework.Test;
012import junit.framework.TestCase;
013import junit.framework.TestSuite;
014
015import org.apache.log4j.BasicConfigurator;
016
017import edu.jas.arith.BigDecimal;
018import edu.jas.arith.BigRational;
019import edu.jas.poly.GenPolynomial;
020import edu.jas.poly.GenPolynomialRing;
021import edu.jas.structure.NotInvertibleException;
022import edu.jas.structure.Power;
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, dd.subtract(dd1).abs().compareTo(epsd) <= 0);
364        assertTrue("mag(a+b) = mag(a)+mag(b): " + ed + ", " + ed1, 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        epsr = dfac.coFac.getONE().multiply(eps);
411        //System.out.println("epsr = " + epsr);
412
413        R = rrr.refineIntervals(R, ar, epsr);
414        //System.out.println("R = " + R);
415        for (Interval<RealAlgebraicNumber<BigRational>> v : R) {
416            BigDecimal dd = v.toDecimal(); //.sum(eps1);
417            System.out.println("v = " + dd);
418            // assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
419        }
420    }
421
422
423    /**
424     * Test real root isolation for Wilkinson like polynomials.
425     * product_{i=1..n}( x - i * alpha )
426     * 
427     */
428    public void testRealRootIsolationWilkinson() {
429        //System.out.println();
430        GenPolynomialRing<RealAlgebraicNumber<BigRational>> dfac;
431        dfac = new GenPolynomialRing<RealAlgebraicNumber<BigRational>>(fac, 1);
432
433        GenPolynomial<RealAlgebraicNumber<BigRational>> ar, br, cr, dr, er;
434
435        RealRoots<RealAlgebraicNumber<BigRational>> rrr = new RealRootsSturm<RealAlgebraicNumber<BigRational>>();
436
437        final int N = 3;
438        dr = dfac.getONE();
439        er = dfac.univariate(0);
440
441        List<Interval<RealAlgebraicNumber<BigRational>>> Rn = new ArrayList<Interval<RealAlgebraicNumber<BigRational>>>(
442                N);
443        ar = dr;
444        for (int i = 0; i < N; i++) {
445            cr = dfac.fromInteger(i).multiply(alpha); // i * alpha
446            Rn.add(new Interval<RealAlgebraicNumber<BigRational>>(cr.leadingBaseCoefficient()));
447            br = er.subtract(cr); // ( x - i * alpha )
448            ar = ar.multiply(br);
449        }
450        //System.out.println("ar = " + ar);
451
452        List<Interval<RealAlgebraicNumber<BigRational>>> R = rrr.realRoots(ar);
453        //System.out.println("R = " + R);
454
455        assertTrue("#roots = " + N + " ", R.size() == N);
456
457        BigRational eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
458        //BigRational eps = Power.positivePower(new BigRational(1L,10L),10);
459        //System.out.println("eps = " + eps);
460        //BigDecimal eps1 = new BigDecimal(eps);
461        //System.out.println("eps1 = " + eps1);
462        RealAlgebraicNumber<BigRational> epsr = dfac.coFac.getONE().multiply(eps);
463        //System.out.println("epsr = " + epsr);
464
465        R = rrr.refineIntervals(R, ar, epsr);
466        //System.out.println("R = " + R);
467        int i = 0;
468        for (Interval<RealAlgebraicNumber<BigRational>> v : R) {
469            BigDecimal dd = v.toDecimal();//.sum(eps1);
470            BigDecimal di = Rn.get(i++).toDecimal();
471            //System.out.println("v  = " + dd);
472            //System.out.println("vi = " + di);
473            assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0);
474        }
475    }
476
477}