001/*
002 * $Id: ElementaryIntegrationCzichowski.java 5846 2018-06-24 13:18:52Z elbarbary
003 * $
004 */
005
006package edu.jas.integrate;
007
008
009import java.util.ArrayList;
010import java.util.Collections;
011import java.util.List;
012
013import org.apache.logging.log4j.LogManager;
014import org.apache.logging.log4j.Logger;
015
016import edu.jas.gb.GroebnerBaseAbstract;
017import edu.jas.gbufd.GBFactory;
018import edu.jas.poly.AlgebraicNumber;
019import edu.jas.poly.AlgebraicNumberRing;
020import edu.jas.poly.GenPolynomial;
021import edu.jas.poly.GenPolynomialRing;
022import edu.jas.poly.PolyUtil;
023import edu.jas.structure.GcdRingElem;
024import edu.jas.structure.RingFactory;
025import edu.jas.ufd.PolyUfdUtil;
026
027
028/**
029 * Method related to elementary integration. Czichowski integration of the
030 * logarithmic part.
031 * 
032 * @author Youssef Elbarbary
033 * @param <C> coefficient type
034 */
035
036public class ElementaryIntegrationCzichowski<C extends GcdRingElem<C>> extends ElementaryIntegration<C> {
037
038
039    private static final Logger logger = LogManager.getLogger(ElementaryIntegrationCzichowski.class);
040
041
042    /**
043     * Engine for Groebner basis.
044     */
045    public final GroebnerBaseAbstract<C> red;
046
047
048    /**
049     * Constructor.
050     */
051    public ElementaryIntegrationCzichowski(RingFactory<C> br) {
052        super(br);
053        red = GBFactory.<C> getImplementation(br);
054    }
055
056
057    /**
058     * Univariate GenPolynomial integration of the logaritmic part, Czichowski
059     * 
060     * @param A univariate GenPolynomial, deg(A) < deg(P).
061     * @param P univariate irreducible GenPolynomial. // gcd(A,P) == 1 automatic
062     * @return logarithmic part container.
063     */
064    @Override
065    public LogIntegral<C> integrateLogPart(GenPolynomial<C> A, GenPolynomial<C> P) {
066        if (P == null || P.isZERO()) {
067            throw new IllegalArgumentException("P == null or P == 0");
068        }
069        // System.out.println("\nP_base_algeb_part = " + P);
070        GenPolynomialRing<C> pfac = P.ring; // K[x]
071        if (pfac.nvar > 1) {
072            throw new IllegalArgumentException("only for univariate polynomials " + pfac);
073        }
074        if (!pfac.coFac.isField()) {
075            throw new IllegalArgumentException("only for field coefficients " + pfac);
076        }
077        List<C> cfactors = new ArrayList<C>();
078        List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>();
079        List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>();
080        List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>();
081
082        // P linear
083        if (P.degree(0) <= 1) {
084            cfactors.add(A.leadingBaseCoefficient());
085            cdenom.add(P);
086            return new LogIntegral<C>(A, P, cfactors, cdenom, afactors, adenom);
087        }
088
089        // deriviative
090        GenPolynomial<C> Pp = PolyUtil.<C> baseDeriviative(P);
091        // no: Pp = Pp.monic();
092        // System.out.println("Pp = " + Pp);
093
094        // Q[t]
095        String[] vars = new String[] { "t" };
096        GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(pfac.coFac, 1, pfac.tord, vars);
097        GenPolynomial<C> t = cfac.univariate(0);
098
099        // Q[x][t]
100        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(pfac, cfac); // sic
101        // System.out.println("rfac = " + rfac.toScript());
102
103        // transform polynomials to bi-variate polynomial
104        GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, A);
105        // System.out.println("Ac = " + Ac);
106        GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> introduceLowerVariable(rfac, P);
107        // System.out.println("Pc = " + Pc);
108        GenPolynomial<GenPolynomial<C>> Pcp = PolyUfdUtil.<C> introduceLowerVariable(rfac, Pp);
109        // System.out.println("Pcp = " + Pcp);
110
111        // Q[t][x]
112        GenPolynomialRing<GenPolynomial<C>> rfac1 = Pc.ring;
113        // System.out.println("rfac1 = " + rfac1.toScript());
114
115        // A - t P'
116        GenPolynomial<GenPolynomial<C>> tc = rfac1.getONE().multiply(t);
117        // System.out.println("tc = " + tc);
118        GenPolynomial<GenPolynomial<C>> At = Ac.subtract(tc.multiply(Pcp));
119        // System.out.println("At = " + At);
120
121        // Q[t][x] to Q[t,x]
122        GenPolynomialRing<C> dfac = pfac.distribute();
123        GenPolynomial<C> Atd = PolyUtil.distribute(dfac, At);
124        GenPolynomial<C> Pcd = PolyUtil.distribute(dfac, Pc);
125
126        // Groebner Basis
127        List<GenPolynomial<C>> myList = new ArrayList<GenPolynomial<C>>();
128        myList.add(Atd);
129        myList.add(Pcd);
130        List<GenPolynomial<C>> mGB = red.GB(myList);
131        Collections.sort(mGB); // OrderedPolynomialList
132
133        // Q[t,x] to Q[t][x]
134        List<GenPolynomial<GenPolynomial<C>>> gbList = PolyUtil.recursive(rfac1, mGB);
135
136        // Content & Primitive Part
137        int counter = 1;
138        for (GenPolynomial<GenPolynomial<C>> tmGB : gbList) {
139            if (counter == gbList.size()) {
140                continue;
141            }
142            GenPolynomial<C> content = ufd.recursiveContent(tmGB);
143
144            // Content of GB i+1
145            GenPolynomial<C> c = ufd.recursiveContent(gbList.get(counter));
146            GenPolynomial<C> Q = content.divide(c);
147
148            // Primitive Part of GB i+1
149            GenPolynomial<GenPolynomial<C>> ppS = ufd.baseRecursivePrimitivePart(gbList.get(counter));
150            // System.out.println("pp(S) = " + ppS);
151            counter++;
152
153            // vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) };
154            vars = pfac.newVars("z_");
155            pfac = pfac.copy();
156            @SuppressWarnings("unused")
157            String[] unused = pfac.setVars(vars);
158            if (Q.degreeMin() == 1) {
159                Q = Q.divide(t);
160            }
161            Q = pfac.copy(Q); // hack to exchange the variables
162            AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(Q);
163            logger.debug("afac = " + afac.toScript());
164            AlgebraicNumber<C> a = afac.getGenerator();
165            // no: a = a.negate();
166            // System.out.println("a = " + a);
167
168
169            // K(alpha)[x]
170            GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac,
171                            ppS.ring);
172            // System.out.println("pafac = " + pafac.toScript());
173
174            // convert to K(alpha)[x]
175            GenPolynomial<AlgebraicNumber<C>> Sa = PolyUtil.convertRecursiveToAlgebraicCoefficients(pafac,
176                            ppS);
177            // System.out.println("Sa = " + Sa);
178
179            afactors.add(a);
180            adenom.add(Sa);
181            // adenom.add(Sa.monic());
182        }
183        return new LogIntegral<C>(A, P, cfactors, cdenom, afactors, adenom);
184    }
185
186}