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