001/*
002 * $Id: SolvableGroebnerBasePseudoSeq.java 5841 2018-05-20 21:26:13Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.gb.OrderedPairlist;
015import edu.jas.gb.Pair;
016import edu.jas.gb.PairList;
017import edu.jas.gb.SolvableExtendedGB;
018import edu.jas.gb.SolvableGroebnerBaseAbstract;
019import edu.jas.poly.GenSolvablePolynomial;
020import edu.jas.poly.GenSolvablePolynomialRing;
021// import edu.jas.poly.GenPolynomialRing;
022import edu.jas.poly.PolynomialList;
023import edu.jas.structure.GcdRingElem;
024import edu.jas.structure.RingFactory;
025import edu.jas.ufd.GCDFactory;
026import edu.jas.ufd.GreatestCommonDivisorAbstract;
027import edu.jas.ufd.GreatestCommonDivisorFake;
028
029
030/**
031 * Solvable Groebner Base with pseudo reduction sequential algorithm. Implements
032 * coefficient fraction free Groebner bases. Coefficients can for example be
033 * integers or (commutative) univariate polynomials.
034 * @param <C> coefficient type
035 * @author Heinz Kredel
036 * 
037 * @see edu.jas.application.GBAlgorithmBuilder
038 * @see edu.jas.gbufd.GBFactory
039 */
040
041public class SolvableGroebnerBasePseudoSeq<C extends GcdRingElem<C>> extends SolvableGroebnerBaseAbstract<C> {
042
043
044    private static final Logger logger = Logger.getLogger(SolvableGroebnerBasePseudoSeq.class);
045
046
047    private static final boolean debug = logger.isDebugEnabled();
048
049
050    /**
051     * Greatest common divisor engine for coefficient content and primitive
052     * parts.
053     */
054    protected final GreatestCommonDivisorAbstract<C> engine;
055
056
057    /**
058     * Pseudo reduction engine.
059     */
060    protected final SolvablePseudoReduction<C> sred;
061
062
063    /**
064     * Coefficient ring factory.
065     */
066    protected final RingFactory<C> cofac;
067
068
069    /**
070     * Constructor.
071     * @param rf coefficient ring factory.
072     */
073    public SolvableGroebnerBasePseudoSeq(RingFactory<C> rf) {
074        this(new SolvablePseudoReductionSeq<C>(), rf, new OrderedPairlist<C>());
075    }
076
077
078    /**
079     * Constructor.
080     * @param rf coefficient ring factory.
081     * @param pl pair selection strategy
082     */
083    public SolvableGroebnerBasePseudoSeq(RingFactory<C> rf, PairList<C> pl) {
084        this(new SolvablePseudoReductionSeq<C>(), rf, pl);
085    }
086
087
088    /**
089     * Constructor.
090     * @param red pseudo reduction engine. <b>Note:</b> red must be an instance
091     *            of PseudoReductionSeq.
092     * @param rf coefficient ring factory.
093     * @param pl pair selection strategy
094     */
095    public SolvableGroebnerBasePseudoSeq(SolvablePseudoReduction<C> red, RingFactory<C> rf, PairList<C> pl) {
096        super(red, pl);
097        this.sred = red;
098        cofac = rf;
099        if (!cofac.isCommutative()) {
100            logger.warn("right reduction not correct for " + cofac.toScript());
101            engine = new GreatestCommonDivisorFake<C>(); // only for Ore conditions
102            // TODO check that also coeffTable is empty for recursive solvable poly ring
103            //System.out.println("stack trace = "); 
104            //Exception e = new RuntimeException("get stack trace");
105            //e.printStackTrace();
106        } else {
107            //engine = GCDFactory.<C> getImplementation(rf);
108            engine = GCDFactory.<C> getProxy(rf);
109        }
110    }
111
112
113    /**
114     * Left Groebner base using pairlist class.
115     * @param modv module variable number.
116     * @param F polynomial list.
117     * @return GB(F) a Groebner base of F.
118     */
119    @Override
120    public List<GenSolvablePolynomial<C>> leftGB(int modv, List<GenSolvablePolynomial<C>> F) {
121        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(F);
122        G = PolynomialList.<C> castToSolvableList(engine.basePrimitivePart(PolynomialList.<C> castToList(G)));
123        if (G.size() <= 1) {
124            return G;
125        }
126        GenSolvablePolynomialRing<C> ring = G.get(0).ring;
127        if (ring.coFac.isField()) { // remove ?
128            throw new IllegalArgumentException("coefficients from a field");
129        }
130        PairList<C> pairlist = strategy.create(modv, ring);
131        pairlist.put(PolynomialList.<C> castToList(G));
132
133        Pair<C> pair;
134        GenSolvablePolynomial<C> pi, pj, S, H;
135        while (pairlist.hasNext()) {
136            pair = pairlist.removeNext();
137            if (pair == null)
138                continue;
139
140            pi = (GenSolvablePolynomial<C>) pair.pi;
141            pj = (GenSolvablePolynomial<C>) pair.pj;
142            if (debug) {
143                logger.debug("pi    = " + pi);
144                logger.debug("pj    = " + pj);
145            }
146
147            S = sred.leftSPolynomial(pi, pj);
148            if (S.isZERO()) {
149                pair.setZero();
150                continue;
151            }
152            if (debug) {
153                logger.debug("ht(S) = " + S.leadingExpVector());
154            }
155
156            H = sred.leftNormalform(G, S);
157            if (H.isZERO()) {
158                pair.setZero();
159                continue;
160            }
161            if (debug) {
162                logger.debug("ht(H) = " + H.leadingExpVector());
163            }
164            H = (GenSolvablePolynomial<C>) engine.basePrimitivePart(H);
165            H = (GenSolvablePolynomial<C>) H.abs();
166            if (H.isConstant()) {
167                G.clear();
168                G.add(H);
169                return G; // since no threads are activated
170            }
171            if (logger.isDebugEnabled()) {
172                logger.debug("H = " + H);
173            }
174            if (H.length() > 0) {
175                G.add(H);
176                pairlist.put(H);
177            }
178        }
179        logger.debug("#sequential list = " + G.size());
180        G = leftMinimalGB(G);
181        logger.info("" + pairlist);
182        return G;
183    }
184
185
186    /**
187     * Minimal ordered Solvable Groebner basis.
188     * @param Gp a Solvable Groebner base.
189     * @return a reduced Solvable Groebner base of Gp.
190     */
191    @Override
192    public List<GenSolvablePolynomial<C>> leftMinimalGB(List<GenSolvablePolynomial<C>> Gp) {
193        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(Gp);
194        if (G.size() <= 1) {
195            return G;
196        }
197        // remove top reducible polynomials
198        GenSolvablePolynomial<C> a;
199        List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(G.size());
200        while (G.size() > 0) {
201            a = G.remove(0);
202            if (sred.isTopReducible(G, a) || sred.isTopReducible(F, a)) {
203                // drop polynomial 
204                if (debug) {
205                    System.out.println("dropped " + a);
206                    List<GenSolvablePolynomial<C>> ff;
207                    ff = new ArrayList<GenSolvablePolynomial<C>>(G);
208                    ff.addAll(F);
209                    a = sred.leftNormalform(ff, a);
210                    if (!a.isZERO()) {
211                        System.out.println("error, nf(a) " + a);
212                    }
213                }
214            } else {
215                F.add(a);
216            }
217        }
218        G = F;
219        if (G.size() <= 1) {
220            return G;
221        }
222        Collections.reverse(G); // important for lex GB
223        // reduce remaining polynomials
224        int len = G.size();
225        int i = 0;
226        while (i < len) {
227            a = G.remove(0);
228            //System.out.println("doing " + a.length());
229            a = sred.leftNormalform(G, a);
230            a = (GenSolvablePolynomial<C>) engine.basePrimitivePart(a); //a.monic(); not possible
231            a = (GenSolvablePolynomial<C>) a.abs();
232            //a = sred.normalform( F, a );
233            G.add(a); // adds as last
234            i++;
235        }
236        return G;
237    }
238
239
240    /**
241     * Twosided Solvable Groebner base using pairlist class.
242     * @param modv number of module variables.
243     * @param Fp solvable polynomial list.
244     * @return tsGB(Fp) a twosided Groebner base of Fp.
245     */
246    @Override
247    public List<GenSolvablePolynomial<C>> twosidedGB(int modv, List<GenSolvablePolynomial<C>> Fp) {
248        List<GenSolvablePolynomial<C>> G = normalizeZerosOnes(Fp);
249        G = PolynomialList.<C> castToSolvableList(engine.basePrimitivePart(PolynomialList.<C> castToList(G)));
250        if (G.size() < 1) { // two-sided!
251            return G;
252        }
253        //System.out.println("G = " + G);
254        GenSolvablePolynomialRing<C> ring = G.get(0).ring; // assert != null
255        if (ring.coFac.isField()) { // remove ?
256            throw new IllegalArgumentException("coefficients from a field");
257        }
258        // add also coefficient generators
259        List<GenSolvablePolynomial<C>> X;
260        X = PolynomialList.castToSolvableList(ring.generators(modv)); 
261        logger.info("right multipliers = " + X);
262        List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(G.size() * (1 + X.size()));
263        F.addAll(G);
264        logger.info("right multipy: F = " + F);
265        GenSolvablePolynomial<C> p, x, q;
266        for (int i = 0; i < F.size(); i++) { // F changes
267            p = F.get(i);
268            for (int j = 0; j < X.size(); j++) {
269                x = X.get(j);
270                q = p.multiply(x);
271                logger.info("right multipy: p = " + p + ", x = " + x + ", q = " + q);
272                q = sred.leftNormalform(F, q);
273                if (!q.isZERO()) {
274                    q = (GenSolvablePolynomial<C>) engine.basePrimitivePart(q);
275                    q = (GenSolvablePolynomial<C>) q.abs();
276                    logger.info("right multipy: red(q) = " + q);
277                    F.add(q);
278                }
279            }
280        }
281        G = F;
282        //System.out.println("G generated = " + G);
283        PairList<C> pairlist = strategy.create(modv, ring);
284        pairlist.put(PolynomialList.<C> castToList(G));
285
286        Pair<C> pair;
287        GenSolvablePolynomial<C> pi, pj, S, H;
288        while (pairlist.hasNext()) {
289            pair = pairlist.removeNext();
290            if (pair == null) {
291                continue;
292            }
293
294            pi = (GenSolvablePolynomial<C>) pair.pi;
295            pj = (GenSolvablePolynomial<C>) pair.pj;
296            if (debug) {
297                logger.debug("pi    = " + pi);
298                logger.debug("pj    = " + pj);
299            }
300
301            S = sred.leftSPolynomial(pi, pj);
302            if (S.isZERO()) {
303                pair.setZero();
304                continue;
305            }
306            if (debug) {
307                logger.debug("ht(S) = " + S.leadingExpVector());
308            }
309
310            H = sred.leftNormalform(G, S);
311            if (H.isZERO()) {
312                pair.setZero();
313                continue;
314            }
315            if (debug) {
316                logger.debug("ht(H) = " + H.leadingExpVector());
317            }
318
319            H = (GenSolvablePolynomial<C>) engine.basePrimitivePart(H);
320            H = (GenSolvablePolynomial<C>) H.abs();
321            if (H.isONE()) {
322                G.clear();
323                G.add(H);
324                return G; // since no threads are activated
325            }
326            if (debug) {
327                logger.debug("H = " + H);
328            }
329            if (H.length() > 0) {
330                G.add(H);
331                pairlist.put(H);
332                for (int j = 0; j < X.size(); j++) {
333                    x = X.get(j);
334                    p = H.multiply(x);
335                    p = sred.leftNormalform(G, p);
336                    if (!p.isZERO()) {
337                        p = (GenSolvablePolynomial<C>) engine.basePrimitivePart(p);
338                        p = (GenSolvablePolynomial<C>) p.abs();
339                        if (p.isONE()) {
340                            G.clear();
341                            G.add(p);
342                            return G; // since no threads are activated
343                        }
344                        G.add(p);
345                        pairlist.put(p);
346                    }
347                }
348            }
349        }
350        logger.debug("#sequential list = " + G.size());
351        G = leftMinimalGB(G);
352        logger.info("" + pairlist);
353        return G;
354    }
355
356
357    /**
358     * Solvable Extended Groebner base using critical pair class.
359     * @param modv module variable number.
360     * @param F solvable polynomial list.
361     * @return a container for an extended left Groebner base of F. <b>Note:
362     *         </b> not implemented;
363     */
364    //@SuppressWarnings("unchecked")
365    @Override
366    public SolvableExtendedGB<C> extLeftGB(int modv, List<GenSolvablePolynomial<C>> F) {
367        throw new UnsupportedOperationException(); // TODO
368    }
369
370}