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