001/*
002 * $Id: SyzygySeq.java 5267 2015-07-27 17:57:50Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.Iterator;
010import java.util.List;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.gb.ExtendedGB;
015import edu.jas.gb.GroebnerBaseAbstract;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.poly.ModuleList;
019import edu.jas.poly.PolynomialList;
020import edu.jas.structure.GcdRingElem;
021import edu.jas.structure.RingFactory;
022
023
024/**
025 * SyzygySeq class. Implements Syzygy computations and tests.
026 * @param <C> coefficient type
027 * @author Heinz Kredel
028 */
029
030public class SyzygySeq<C extends GcdRingElem<C>> extends SyzygyAbstract<C> {
031
032
033    private static final Logger logger = Logger.getLogger(SyzygySeq.class);
034
035
036    private final boolean debug = logger.isDebugEnabled();
037
038
039    /**
040     * Groebner base engine.
041     */
042    protected GroebnerBaseAbstract<C> bb;
043
044
045    /*
046     * Module Groebner base engine.
047    //protected ModGroebnerBaseAbstract<C> mbb;
048     */
049
050
051    /**
052     * Constructor.
053     * @param cf coefficient ring.
054     */
055    public SyzygySeq(RingFactory<C> cf) {
056        super();
057        bb = GBFactory.getImplementation(cf);
058        //mbb = new ModGroebnerBaseSeq<C>(cf);
059    }
060
061
062    /**
063     * Resolution of a module. Only with direct GBs.
064     * @param M a module list of a Groebner basis.
065     * @return a resolution of M.
066     */
067    public List<ResPart<C>> resolution(ModuleList<C> M) {
068        List<ResPart<C>> R = new ArrayList<ResPart<C>>();
069        ModuleList<C> MM = M;
070        ModuleList<C> GM;
071        ModuleList<C> Z;
072        //ModGroebnerBase<C> mbb = new ModGroebnerBaseSeq<C>(M.ring.coFac);
073        //assert cf == M.ring.coFac;
074        while (true) {
075            GM = bb.GB(MM);
076            Z = zeroRelations(GM);
077            R.add(new ResPart<C>(MM, GM, Z));
078            if (Z == null || Z.list == null || Z.list.size() == 0) {
079                break;
080            }
081            MM = Z;
082        }
083        return R;
084    }
085
086
087    /**
088     * Resolution of a polynomial list. Only with direct GBs.
089     * @param F a polynomial list of a Groebner basis.
090     * @return a resolution of F.
091     */
092    @SuppressWarnings("unchecked")
093    public List // <ResPart<C>|ResPolPart<C>>
094    resolution(PolynomialList<C> F) {
095        List<List<GenPolynomial<C>>> Z;
096        ModuleList<C> Zm;
097        List<GenPolynomial<C>> G;
098        PolynomialList<C> Gl;
099
100        //GroebnerBase<C> gb = GBFactory.getImplementation(F.ring.coFac);
101        //assert cf == F.ring.coFac;
102        G = bb.GB(F.list);
103        Z = zeroRelations(G);
104        Gl = new PolynomialList<C>(F.ring, G);
105        Zm = new ModuleList<C>(F.ring, Z);
106
107        List R = resolution(Zm); //// <ResPart<C>|ResPolPart<C>>
108        R.add(0, new ResPolPart<C>(F, Gl, Zm));
109        return R;
110    }
111
112
113    /**
114     * Resolution of a polynomial list.
115     * @param F a polynomial list of an arbitrary basis.
116     * @return a resolution of F.
117     */
118    @SuppressWarnings("unchecked")
119    public List // <ResPart<C>|ResPolPart<C>>
120    resolutionArbitrary(PolynomialList<C> F) {
121        List<List<GenPolynomial<C>>> Z;
122        ModuleList<C> Zm;
123        //List<GenPolynomial<C>> G;
124        PolynomialList<C> Gl = null;
125
126        //G = bb.GB(F.list);
127        Z = zeroRelationsArbitrary(F.list);
128        //Gl = new PolynomialList<C>(F.ring, F.list);
129        Zm = new ModuleList<C>(F.ring, Z);
130
131        List R = resolutionArbitrary(Zm); //// <ResPart<C>|ResPolPart<C>>
132        R.add(0, new ResPolPart<C>(F, Gl, Zm));
133        return R;
134    }
135
136
137    /**
138     * Resolution of a module.
139     * @param M a module list of an arbitrary basis.
140     * @return a resolution of M.
141     */
142    public List<ResPart<C>> resolutionArbitrary(ModuleList<C> M) {
143        List<ResPart<C>> R = new ArrayList<ResPart<C>>();
144        ModuleList<C> MM = M;
145        ModuleList<C> GM = null;
146        ModuleList<C> Z;
147        while (true) {
148            //GM = bb.GB(MM);
149            Z = zeroRelationsArbitrary(MM);
150            R.add(new ResPart<C>(MM, GM, Z));
151            if (Z == null || Z.list == null || Z.list.size() == 0) {
152                break;
153            }
154            MM = Z;
155        }
156        return R;
157    }
158
159
160    /**
161     * Syzygy module from arbitrary base.
162     * @param modv number of module variables.
163     * @param F a polynomial list.
164     * @return syz(F), a basis for the module of syzygies for F.
165     */
166    public List<List<GenPolynomial<C>>> zeroRelationsArbitrary(int modv, List<GenPolynomial<C>> F) {
167        if (F == null) {
168            return new ArrayList<List<GenPolynomial<C>>>();
169            //return zeroRelations(modv, F);
170        }
171        if (F.size() <= 1) {
172            return zeroRelations(modv, F);
173        }
174        //GroebnerBase<C> gb = GBFactory.getImplementation(F.get(0).ring.coFac);
175        // assert cf == F.get(0).ring.coFac;
176        final int lenf = F.size();
177        ExtendedGB<C> exgb = bb.extGB(F);
178        if (debug) {
179            logger.debug("exgb = " + exgb);
180            if (!bb.isReductionMatrix(exgb)) {
181                logger.error("is reduction matrix ? false");
182            }
183        }
184        List<GenPolynomial<C>> G = exgb.G;
185        List<List<GenPolynomial<C>>> G2F = exgb.G2F;
186        List<List<GenPolynomial<C>>> F2G = exgb.F2G;
187
188        List<List<GenPolynomial<C>>> sg = zeroRelations(modv, G);
189        GenPolynomialRing<C> ring = G.get(0).ring;
190        ModuleList<C> S = new ModuleList<C>(ring, sg);
191        if (debug) {
192            logger.debug("syz = " + S);
193            if (!isZeroRelation(sg, G)) {
194                logger.error("is syzygy ? false");
195            }
196        }
197        List<List<GenPolynomial<C>>> sf;
198        sf = new ArrayList<List<GenPolynomial<C>>>(sg.size());
199        //List<GenPolynomial<C>> row;
200        for (List<GenPolynomial<C>> r : sg) {
201            Iterator<GenPolynomial<C>> it = r.iterator();
202            Iterator<List<GenPolynomial<C>>> jt = G2F.iterator();
203
204            List<GenPolynomial<C>> rf;
205            rf = new ArrayList<GenPolynomial<C>>(lenf);
206            for (int m = 0; m < lenf; m++) {
207                rf.add(ring.getZERO());
208            }
209            while (it.hasNext() && jt.hasNext()) {
210                GenPolynomial<C> si = it.next();
211                List<GenPolynomial<C>> ai = jt.next();
212                //System.out.println("si = " + si);
213                //System.out.println("ai = " + ai);
214                if (si == null || ai == null) {
215                    continue;
216                }
217                List<GenPolynomial<C>> pi = blas.scalarProduct(si, ai);
218                //System.out.println("pi = " + pi);
219                rf = blas.vectorAdd(rf, pi);
220            }
221            if (it.hasNext() || jt.hasNext()) {
222                logger.error("zeroRelationsArbitrary wrong sizes");
223            }
224            //System.out.println("\nrf = " + rf + "\n");
225            sf.add(rf);
226        }
227        List<List<GenPolynomial<C>>> M;
228        M = new ArrayList<List<GenPolynomial<C>>>(lenf);
229        for (List<GenPolynomial<C>> r : F2G) {
230            Iterator<GenPolynomial<C>> it = r.iterator();
231            Iterator<List<GenPolynomial<C>>> jt = G2F.iterator();
232
233            List<GenPolynomial<C>> rf;
234            rf = new ArrayList<GenPolynomial<C>>(lenf);
235            for (int m = 0; m < lenf; m++) {
236                rf.add(ring.getZERO());
237            }
238            while (it.hasNext() && jt.hasNext()) {
239                GenPolynomial<C> si = it.next();
240                List<GenPolynomial<C>> ai = jt.next();
241                //System.out.println("si = " + si);
242                //System.out.println("ai = " + ai);
243                if (si == null || ai == null) {
244                    continue;
245                }
246                List<GenPolynomial<C>> pi = blas.scalarProduct(ai, si);
247                //System.out.println("pi = " + pi);
248                rf = blas.vectorAdd(rf, pi);
249            }
250            if (it.hasNext() || jt.hasNext()) {
251                logger.error("zeroRelationsArbitrary wrong sizes");
252            }
253            //System.out.println("\nMg Mf = " + rf + "\n");
254            M.add(rf);
255        }
256        //ModuleList<C> ML = new ModuleList<C>( ring, M );
257        //System.out.println("syz ML = " + ML);
258        // debug only:
259        /* not true in general
260        List<GenPolynomial<C>> F2 = new ArrayList<GenPolynomial<C>>( F.size() );
261        for ( List<GenPolynomial<C>> rr: M ) {
262            GenPolynomial<C> rrg = blas.scalarProduct( F, rr );
263            F2.add( rrg );
264        }
265        PolynomialList<C> pF = new PolynomialList<C>( ring, F );
266        PolynomialList<C> pF2 = new PolynomialList<C>( ring, F2 );
267        if ( ! pF.equals( pF2 ) ) {
268           logger.error("is FAB = F ? false");
269        }
270        */
271        int sflen = sf.size();
272        List<List<GenPolynomial<C>>> M2;
273        M2 = new ArrayList<List<GenPolynomial<C>>>(lenf);
274        int i = 0;
275        for (List<GenPolynomial<C>> ri : M) {
276            List<GenPolynomial<C>> r2i;
277            r2i = new ArrayList<GenPolynomial<C>>(ri.size());
278            int j = 0;
279            for (GenPolynomial<C> rij : ri) {
280                GenPolynomial<C> p = null;
281                if (i == j) {
282                    p = ring.getONE().subtract(rij);
283                } else {
284                    if (rij != null) {
285                        p = rij.negate();
286                    }
287                }
288                r2i.add(p);
289                j++;
290            }
291            M2.add(r2i);
292            if (!blas.isZero(r2i)) {
293                sf.add(r2i);
294            }
295            i++;
296        }
297        if (debug) {
298            ModuleList<C> M2L = new ModuleList<C>(ring, M2);
299            logger.debug("syz M2L = " + M2L);
300            ModuleList<C> SF = new ModuleList<C>(ring, sf);
301            logger.debug("syz sf = " + SF);
302            logger.debug("#syz " + sflen + ", " + sf.size());
303            if (!isZeroRelation(sf, F)) {
304                logger.error("is syz sf ? false");
305            }
306        }
307        return sf;
308    }
309
310}