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