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.Rational;
013import edu.jas.poly.Complex;
014import edu.jas.poly.ComplexRing;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.poly.PolyUtil;
018// import edu.jas.root.RealAlgebraicNumber;
019import edu.jas.structure.GcdRingElem;
020
021
022/**
023 * Container for Ideals together with univariate polynomials and complex
024 * algebraic roots.
025 * @author Heinz Kredel
026 */
027public class IdealWithComplexAlgebraicRoots<D extends GcdRingElem<D> & Rational> extends IdealWithUniv<D> {
028
029
030    /**
031     * The list of complex algebraic roots.
032     */
033    public final List<List<Complex<RealAlgebraicNumber<D>>>> can;
034
035
036    /**
037     * The list of decimal approximations of the complex algebraic roots.
038     */
039    protected List<List<Complex<BigDecimal>>> droots = null;
040
041
042    /**
043     * Constructor not for use.
044     */
045    protected IdealWithComplexAlgebraicRoots() {
046        throw new IllegalArgumentException("do not use this constructor");
047    }
048
049
050    /**
051     * Constructor.
052     * @param id the ideal
053     * @param up the list of univariate polynomials
054     * @param cr the list of complex algebraic roots
055     */
056    public IdealWithComplexAlgebraicRoots(Ideal<D> id, List<GenPolynomial<D>> up,
057                    List<List<Complex<RealAlgebraicNumber<D>>>> cr) {
058        super(id, up);
059        can = cr;
060    }
061
062
063    /**
064     * Constructor.
065     * @param iu the ideal with univariate polynomials
066     * @param cr the list of real algebraic roots
067     */
068    public IdealWithComplexAlgebraicRoots(IdealWithUniv<D> iu,
069                    List<List<Complex<RealAlgebraicNumber<D>>>> cr) {
070        super(iu.ideal, iu.upolys);
071        can = cr;
072    }
073
074
075    /**
076     * String representation of the ideal.
077     * @see java.lang.Object#toString()
078     */
079    @Override
080    public String toString() {
081        StringBuffer sb = new StringBuffer(super.toString() + "\ncomplex roots:\n");
082        sb.append("[");
083        boolean f1 = true;
084        for (List<Complex<RealAlgebraicNumber<D>>> lr : can) {
085            if (!f1) {
086                sb.append(", ");
087            } else {
088                f1 = false;
089            }
090            sb.append("[");
091            boolean f2 = true;
092            for (Complex<RealAlgebraicNumber<D>> rr : lr) {
093                if (!f2) {
094                    sb.append(", ");
095                } else {
096                    f2 = false;
097                }
098                sb.append(rr.ring.toScript());
099            }
100            sb.append("]");
101        }
102        sb.append("]");
103        if (droots != null) {
104            sb.append("\ndecimal complex root approximation:\n");
105            for (List<Complex<BigDecimal>> d : droots) {
106                sb.append(d.toString());
107                sb.append("\n");
108            }
109        }
110        return sb.toString();
111    }
112
113
114    /**
115     * Get a scripting compatible string representation.
116     * @return script compatible representation for this Element.
117     * @see edu.jas.structure.Element#toScript()
118     */
119    @Override
120    public String toScript() {
121        // Python case
122        return super.toScript() + ",  " + can.toString();
123    }
124
125
126    /**
127     * Get decimal approximation of the complex root tuples.
128     */
129    public synchronized List<List<Complex<BigDecimal>>> decimalApproximation() {
130        if (this.droots != null) {
131            return droots;
132        }
133        List<List<Complex<BigDecimal>>> rroots = new ArrayList<List<Complex<BigDecimal>>>();
134        ComplexRing<BigDecimal> cfac = new ComplexRing<BigDecimal>(new BigDecimal());
135        for (List<Complex<RealAlgebraicNumber<D>>> rri : this.can) {
136            List<Complex<BigDecimal>> r = new ArrayList<Complex<BigDecimal>>();
137            for (Complex<RealAlgebraicNumber<D>> rr : rri) {
138                BigDecimal dr = new BigDecimal(rr.getRe().magnitude());
139                BigDecimal di = new BigDecimal(rr.getIm().magnitude());
140                Complex<BigDecimal> d = new Complex<BigDecimal>(cfac, dr, di);
141                r.add(d);
142            }
143            rroots.add(r);
144        }
145        droots = rroots;
146        return rroots;
147    }
148
149
150    /**
151     * compute decimal approximation of the complex root tuples.
152     */
153    public void doDecimalApproximation() {
154        List<List<Complex<BigDecimal>>> unused = decimalApproximation();
155        if (unused.isEmpty()) { // use for findbugs
156            System.out.println("unused is empty");
157        }
158        return;
159    }
160
161
162    /**
163     * Is decimal approximation of the complex roots.
164     * @return true, if the decimal complex roots approximate the complex roots.
165     */
166    public synchronized boolean isDecimalApproximation() {
167        doDecimalApproximation();
168        if (droots == null || droots.size() == 0) {
169            return true;
170        }
171        if (upolys == null || upolys.size() == 0) {
172            return true;
173        }
174        Complex<BigDecimal> dd = droots.get(0).get(0);
175        ComplexRing<BigDecimal> dr = dd.ring;
176        Complex<BigDecimal> c = new Complex<BigDecimal>(dr,
177                        new BigDecimal("0.15").power(BigDecimal.DEFAULT_PRECISION / 2));
178        c = c.norm();
179        //System.out.println("eps: c = " + c);
180        Complex<BigDecimal> cc = new Complex<BigDecimal>(dr,
181                        new BigDecimal("0.1").power(BigDecimal.DEFAULT_PRECISION / 3));
182        cc = cc.norm();
183
184        ComplexRing<D> cr = new ComplexRing<D>(ideal.list.ring.coFac);
185        List<GenPolynomial<Complex<BigDecimal>>> upds = new ArrayList<GenPolynomial<Complex<BigDecimal>>>(
186                        upolys.size());
187        for (GenPolynomial<D> up : upolys) {
188            GenPolynomialRing<D> pfac = up.ring;
189            GenPolynomialRing<Complex<D>> cpfac = new GenPolynomialRing<Complex<D>>(cr, pfac);
190            GenPolynomialRing<Complex<BigDecimal>> dpfac = new GenPolynomialRing<Complex<BigDecimal>>(dr,
191                            cpfac);
192            GenPolynomial<Complex<D>> upc = PolyUtil.<D> complexFromAny(cpfac, up);
193            GenPolynomial<Complex<BigDecimal>> upd = PolyUtil.<D> complexDecimalFromRational(dpfac, upc);
194            //System.out.println("upd = " + upd);
195            upds.add(upd);
196        }
197        for (List<Complex<BigDecimal>> rr : droots) {
198            int i = 0;
199            for (GenPolynomial<Complex<BigDecimal>> upd : upds) {
200                Complex<BigDecimal> d = rr.get(i++);
201                Complex<BigDecimal> z = PolyUtil.<Complex<BigDecimal>> evaluateMain(dr, upd, d);
202                z = z.norm();
203                //System.out.println("z = " + z + ", d = " + d);
204                if (z.getRe().compareTo(c.getRe()) >= 0) {
205                    //System.out.println("no root: z = " + z + ", c = " + c);
206                    if (z.getRe().compareTo(cc.getRe()) >= 0) {
207                        System.out.println("no root: z = " + z + ", cc = " + cc);
208                        return false;
209                    }
210                }
211            }
212            //System.out.println();
213        }
214
215        GenPolynomialRing<D> pfac = ideal.list.ring;
216        cr = new ComplexRing<D>(pfac.coFac);
217        GenPolynomialRing<Complex<D>> cpfac = new GenPolynomialRing<Complex<D>>(cr, pfac);
218        GenPolynomialRing<Complex<BigDecimal>> dpfac = new GenPolynomialRing<Complex<BigDecimal>>(dr, cpfac);
219        List<GenPolynomial<D>> ips = ideal.list.list;
220        c = new Complex<BigDecimal>(dr, new BigDecimal("0.15").power(BigDecimal.DEFAULT_PRECISION / 2 - 1));
221        for (GenPolynomial<D> ip : ips) {
222            GenPolynomial<Complex<D>> ipc = PolyUtil.<D> complexFromAny(cpfac, ip);
223            GenPolynomial<Complex<BigDecimal>> ipd = PolyUtil.<D> complexDecimalFromRational(dpfac, ipc);
224            //System.out.println("ipd = " + ipd);
225            for (List<Complex<BigDecimal>> rr : droots) {
226                Complex<BigDecimal> z = PolyUtil.<Complex<BigDecimal>> evaluateAll(dr, ipd, rr);
227                z = z.norm();
228                //System.out.println("z = " + z + ", rr = " + rr);
229                if (z.getRe().compareTo(c.getRe()) >= 0) {
230                    //System.out.println("no root: z = " + z + ", c = " + c);
231                    if (z.getRe().compareTo(cc.getRe()) >= 0) {
232                        System.out.println("no root: z = " + z + ", cc = " + cc);
233                        System.out.println("ipd = " + ipd + ", rr = " + rr);
234                        return false;
235                    }
236                }
237            }
238            //System.out.println();
239        }
240        return true;
241    }
242
243}