001/*
002 * $Id: ElementaryIntegrationLazard.java 5872 2018-07-20 16:01:46Z kredel $
003 */
004
005package edu.jas.integrate;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.Map.Entry;
011import java.util.SortedMap;
012
013import org.apache.logging.log4j.Logger;
014import org.apache.logging.log4j.LogManager; 
015
016import edu.jas.poly.AlgebraicNumber;
017import edu.jas.poly.AlgebraicNumberRing;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.PolyUtil;
021import edu.jas.structure.GcdRingElem;
022import edu.jas.structure.RingFactory;
023import edu.jas.ufd.GCDFactory;
024import edu.jas.ufd.GreatestCommonDivisorAbstract;
025import edu.jas.ufd.GreatestCommonDivisorSubres;
026import edu.jas.ufd.PolyUfdUtil;
027
028
029/**
030 * Method related to elementary integration. Lazard-Rioboo-Trager integration of
031 * the logarithmic part.
032 * 
033 * @author Youssef Elbarbary
034 * @param <C> coefficient type
035 */
036
037public class ElementaryIntegrationLazard<C extends GcdRingElem<C>> extends ElementaryIntegration<C> {
038
039
040    private static final Logger logger = LogManager.getLogger(ElementaryIntegrationLazard.class);
041
042
043    /**
044     * Constructor.
045     */
046    public ElementaryIntegrationLazard(RingFactory<C> br) {
047        super(br);
048    }
049
050
051    /**
052     * Univariate GenPolynomial integration of the logaritmic part, Lazard -
053     * Rioboo - Trager
054     * 
055     * @param A univariate GenPolynomial, deg(A) < deg(P).
056     * @param P univariate irreducible GenPolynomial. // gcd(A,P) == 1 automatic
057     * @return logarithmic part container.
058     */
059    @Override
060    public LogIntegral<C> integrateLogPart(GenPolynomial<C> A, GenPolynomial<C> P) {
061        if (P == null || P.isZERO()) {
062            throw new IllegalArgumentException("P == null or P == 0");
063        }
064        // System.out.println("\nP_base_algeb_part = " + P);
065        GenPolynomialRing<C> pfac = P.ring; // K[x]
066        if (pfac.nvar > 1) {
067            throw new IllegalArgumentException("only for univariate polynomials " + pfac);
068        }
069        if (!pfac.coFac.isField()) {
070            throw new IllegalArgumentException("only for field coefficients " + pfac);
071        }
072        List<C> cfactors = new ArrayList<C>();
073        List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>();
074        List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>();
075        List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>();
076
077        // P linear
078        if (P.degree(0) <= 1) {
079            cfactors.add(A.leadingBaseCoefficient());
080            cdenom.add(P);
081            return new LogIntegral<C>(A, P, cfactors, cdenom, afactors, adenom);
082        }
083
084        // deriviative
085        GenPolynomial<C> Pp = PolyUtil.<C> baseDeriviative(P);
086        // no: Pp = Pp.monic();
087        // System.out.println("\nP = " + P);
088
089        // Q[t]
090        String[] vars = new String[] { "t" };
091        GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(pfac.coFac, 1, pfac.tord, vars);
092        GenPolynomial<C> t = cfac.univariate(0);
093        // System.out.println("t = " + t);
094
095        // Q[x][t]
096        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(pfac, cfac); // sic
097        // System.out.println("rfac = " + rfac.toScript());
098
099        // transform polynomials to bi-variate polynomial
100        GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, A);
101        GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> introduceLowerVariable(rfac, P);
102        GenPolynomial<GenPolynomial<C>> Pcp = PolyUfdUtil.<C> introduceLowerVariable(rfac, Pp);
103
104        // Q[t][x]
105        GenPolynomialRing<GenPolynomial<C>> rfac1 = Pc.ring;
106        // System.out.println("rfac1 = " + rfac1.toScript());
107
108        // A - t P'
109        GenPolynomial<GenPolynomial<C>> tc = rfac1.getONE().multiply(t);
110        // System.out.println("tc = " + tc);
111        GenPolynomial<GenPolynomial<C>> At = Ac.subtract(tc.multiply(Pcp));
112        // System.out.println("A - tP' = " + At);
113
114        GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>();
115        // = GCDFactory.<C>getImplementation( cfac.coFac );
116        GreatestCommonDivisorAbstract<AlgebraicNumber<C>> aengine = null;
117
118        // Subresultant von A - t P'
119        List<GenPolynomial<GenPolynomial<C>>> RcList = engine.recursiveUnivariateSubResultantList(Pc,
120                        At); // returning
121        GenPolynomial<GenPolynomial<C>> Rc = RcList.get(RcList.size() - 1); // just getting R
122        //System.out.println("R = " + Rc);
123
124        // SquareFree(R)
125        SortedMap<GenPolynomial<C>, Long> resSquareFree = sqf.squarefreeFactors(Rc.leadingBaseCoefficient());
126        if (logger.isInfoEnabled()) {
127            logger.info("SquareFree(R) = " + resSquareFree);
128        }
129            
130        // First Loop
131        SortedMap<GenPolynomial<C>, Long> sfactors = null;
132        GenPolynomial<AlgebraicNumber<C>> Sa = null;
133        GenPolynomial<GenPolynomial<C>> S = null;
134        GenPolynomial<C> Q = null;
135        for (Entry<GenPolynomial<C>, Long> qi : resSquareFree.entrySet()) {
136            Q = qi.getKey();
137            // System.out.println("\nr(t) = " + r);
138            if (Q.isConstant()) {
139                continue;
140            }
141            if (Q.degreeMin() == 1) {
142                Q = Q.divide(t);
143            }
144            vars = pfac.newVars("z_");
145            pfac = pfac.copy();
146            @SuppressWarnings("unused")
147            String[] unused = pfac.setVars(vars);
148            GenPolynomial<C> qi2 = pfac.copy(Q); // hack to exchange the variables
149            // System.out.println("r(z_) = " + r);
150            AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(qi2);
151            if (logger.isDebugEnabled()) {
152                logger.debug("afac = " + afac.toScript());
153            }
154            AlgebraicNumber<C> a = afac.getGenerator();
155            // no: a = a.negate();
156            // System.out.println("a = " + a);
157
158            // K(alpha)[x]
159            GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac,
160                            Pc.ring);
161
162            // 1Condition 2Condition i = deg(D) + Check condition again!
163            if (qi2.degree() > 0) {
164                if (qi.getValue() == Pc.degree()) {
165                    GenPolynomial<C> sExp = P;
166                    // convert to K(alpha)[x]
167                    Sa = PolyUtil.<C> convertToAlgebraicCoefficients(pafac, sExp);
168                    afactors.add(a);
169                    adenom.add(Sa);
170                    return new LogIntegral<C>(A, P, cfactors, cdenom, afactors, adenom);
171                }
172                int countj = 1;
173                // RcList.remove(RcList.size()-1);
174                for (GenPolynomial<GenPolynomial<C>> Ri : RcList) {
175                    if (qi.getValue() == Ri.degree()) {
176                        S = Ri;
177                        // convert to K(alpha)[x]
178                        Sa = PolyUtil.convertRecursiveToAlgebraicCoefficients(pafac, S);
179                        sfactors = sqf.squarefreeFactors(S.leadingBaseCoefficient());
180                        if (logger.isInfoEnabled()) {
181                            logger.info("SquareFree(S)" + sfactors);
182                        }
183                    }
184                }
185                for (GenPolynomial<C> ai : sfactors.keySet()) {
186                    GenPolynomial<AlgebraicNumber<C>> aiC = PolyUtil.<C> convertToAlgebraicCoefficients(pafac,
187                                    ai);
188                    GenPolynomial<AlgebraicNumber<C>> qiC = PolyUtil.<C> convertToAlgebraicCoefficients(pafac,
189                                    qi2);
190                    if (aengine == null) {
191                        aengine = GCDFactory.<AlgebraicNumber<C>> getImplementation(afac);
192                    }
193                    GenPolynomial<AlgebraicNumber<C>> gcd = aengine.baseGcd(aiC, qiC);
194                    gcd = gcd.power(countj);
195                    Sa = (Sa.divide(gcd));
196                    countj++;
197                    if (Sa.isZERO() || a.isZERO()) {
198                        System.out.println("warning constant Sa ignored");
199                        continue;
200                    }
201                }
202                //System.out.println("S = " + Sa);
203                afactors.add(a);
204                adenom.add(Sa.monic());
205                // adenom.add(Sa.monic());
206            }
207        }
208        return new LogIntegral<C>(A, P, cfactors, cdenom, afactors, adenom);
209    }
210}