001/*
002 * $Id$
003 */
004
005package edu.jas.gbufd;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.List;
011import java.util.Map;
012
013import org.apache.logging.log4j.Logger;
014import org.apache.logging.log4j.LogManager; 
015
016import edu.jas.gb.Reduction;
017import edu.jas.gb.ReductionSeq;
018import edu.jas.poly.ExpVector;
019import edu.jas.poly.GenPolynomial;
020import edu.jas.poly.ModuleList;
021import edu.jas.poly.PolynomialList;
022import edu.jas.structure.GcdRingElem;
023import edu.jas.structure.RingElem;
024import edu.jas.vector.BasicLinAlg;
025import edu.jas.vector.GenVector;
026import edu.jas.vector.GenVectorModul;
027
028
029/**
030 * SyzygyAbstract class. Implements Syzygy computations and tests.
031 * @param <C> coefficient type
032 * @author Heinz Kredel
033 */
034
035public abstract class SyzygyAbstract<C extends GcdRingElem<C>> implements Syzygy<C> {
036
037
038    private static final Logger logger = LogManager.getLogger(SyzygyAbstract.class);
039
040
041    private static final boolean debug = logger.isDebugEnabled();
042
043
044    /**
045     * Reduction engine.
046     */
047    protected Reduction<C> red;
048
049
050    /**
051     * Linear algebra engine.
052     */
053    protected BasicLinAlg<GenPolynomial<C>> blas;
054
055
056    /**
057     * Constructor.
058     */
059    public SyzygyAbstract() {
060        red = new ReductionSeq<C>();
061        blas = new BasicLinAlg<GenPolynomial<C>>();
062    }
063
064
065    /**
066     * Syzygy module from Groebner base. F must be a Groebner base.
067     * @param F a Groebner base.
068     * @return syz(F), a basis for the module of syzygies for F.
069     */
070    public List<List<GenPolynomial<C>>> zeroRelations(List<GenPolynomial<C>> F) {
071        return zeroRelations(0, F);
072    }
073
074
075    /**
076     * Syzygy module from Groebner base. F must be a Groebner base.
077     * @param modv number of module variables.
078     * @param F a Groebner base.
079     * @return syz(F), a basis for the module of syzygies for F.
080     */
081    public List<List<GenPolynomial<C>>> zeroRelations(int modv, List<GenPolynomial<C>> F) {
082        List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>();
083        if (F == null) {
084            return Z;
085        }
086        GenVectorModul<GenPolynomial<C>> mfac = null;
087        int i = 0;
088        while (mfac == null && i < F.size()) {
089            GenPolynomial<C> p = F.get(i);
090            if (p != null) {
091                mfac = new GenVectorModul<GenPolynomial<C>>(p.ring, F.size());
092            }
093        }
094        if (mfac == null) {
095            return Z;
096        }
097        GenVector<GenPolynomial<C>> v = mfac.fromList(F);
098        //System.out.println("F = " + F + " v = " + v);
099        return zeroRelations(modv, v);
100    }
101
102
103    /**
104     * Syzygy module from Groebner base. v must be a Groebner base.
105     * @param modv number of module variables.
106     * @param v a Groebner base.
107     * @return syz(v), a basis for the module of syzygies for v.
108     */
109    public List<List<GenPolynomial<C>>> zeroRelations(int modv, GenVector<GenPolynomial<C>> v) {
110        List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>();
111        GenVectorModul<GenPolynomial<C>> mfac = v.modul;
112        List<GenPolynomial<C>> F = v.val;
113        GenVector<GenPolynomial<C>> S = mfac.getZERO();
114        GenPolynomial<C> pi, pj, s, h;
115        //zero = mfac.coFac.getZERO();
116        for (int i = 0; i < F.size(); i++) {
117            pi = F.get(i);
118            for (int j = i + 1; j < F.size(); j++) {
119                pj = F.get(j);
120                //logger.info("p{}, p{} = {}, {}", i, j, pi, pj);
121
122                if (!red.moduleCriterion(modv, pi, pj)) {
123                    continue;
124                }
125                // if ( ! red.criterion4( pi, pj ) ) { continue; }
126                List<GenPolynomial<C>> row = S.copy().val;
127
128                s = red.SPolynomial(row, i, pi, j, pj);
129                if (s.isZERO()) {
130                    Z.add(row);
131                    continue;
132                }
133
134                h = red.normalform(row, F, s);
135                if (!h.isZERO()) {
136                    throw new RuntimeException("Syzygy no GB");
137                }
138                if (debug) {
139                    logger.info("row = {}", row.size());
140                }
141                Z.add(row);
142            }
143        }
144        return Z;
145    }
146
147
148    /**
149     * Syzygy module from module Groebner base. M must be a module Groebner
150     * base.
151     * @param M a module Groebner base.
152     * @return syz(M), a basis for the module of syzygies for M.
153     */
154    public ModuleList<C> zeroRelations(ModuleList<C> M) {
155        ModuleList<C> N = M;
156        if (M == null || M.list == null) {
157            return N;
158        }
159        if (M.rows == 0 || M.cols == 0) {
160            return N;
161        }
162        GenPolynomial<C> zero = M.ring.getZERO();
163        //System.out.println("zero = " + zero);
164
165        //ModuleList<C> Np = null;
166        PolynomialList<C> F = M.getPolynomialList();
167        int modv = M.cols; // > 0  
168        //System.out.println("modv = " + modv);
169        List<List<GenPolynomial<C>>> G = zeroRelations(modv, F.list);
170        List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>();
171        for (int i = 0; i < G.size(); i++) {
172            //F = new PolynomialList(F.ring,(List)G.get(i));
173            List<GenPolynomial<C>> Gi = G.get(i);
174            List<GenPolynomial<C>> Zi = new ArrayList<GenPolynomial<C>>();
175            // System.out.println("\nG("+i+") = " + G.get(i));
176            for (int j = 0; j < Gi.size(); j++) {
177                //System.out.println("\nG("+i+","+j+") = " + Gi.get(j));
178                GenPolynomial<C> p = Gi.get(j);
179                if (p != null) {
180                    Map<ExpVector, GenPolynomial<C>> r = p.contract(M.ring);
181                    int s = 0;
182                    for (GenPolynomial<C> vi : r.values()) {
183                        Zi.add(vi);
184                        s++;
185                    }
186                    if (s == 0) {
187                        Zi.add(zero);
188                    } else if (s > 1) { // will not happen
189                        System.out.println("p = " + p);
190                        System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size());
191                        throw new RuntimeException("Map.size() > 1 = " + r.size());
192                    }
193                }
194            }
195            //System.out.println("\nZ("+i+") = " + Zi);
196            Z.add(Zi);
197        }
198        N = new ModuleList<C>(M.ring, Z);
199        //System.out.println("\n\nN = " + N);
200        return N;
201    }
202
203
204    /**
205     * Test if sysygy.
206     * @param Z list of sysygies.
207     * @param F a polynomial list.
208     * @return true, if Z is a list of syzygies for F, else false.
209     */
210
211    public boolean isZeroRelation(List<List<GenPolynomial<C>>> Z, List<GenPolynomial<C>> F) {
212        for (List<GenPolynomial<C>> row : Z) {
213            GenPolynomial<C> p = blas.scalarProduct(row, F);
214            if (p == null) {
215                continue;
216            }
217            if (!p.isZERO()) {
218                logger.info("is not ZeroRelation = {}", p.toString(p.ring.getVars()));
219                logger.info("row = {}", row);
220                //logger.info("F = {}", F);
221                return false;
222            }
223        }
224        return true;
225    }
226
227
228    /**
229     * Test if sysygy of modules.
230     * @param Z list of sysygies.
231     * @param F a module list.
232     * @return true, if Z is a list of syzygies for F, else false.
233     */
234
235    public boolean isZeroRelation(ModuleList<C> Z, ModuleList<C> F) {
236        if (Z == null || Z.list == null) {
237            return true;
238        }
239        for (List<GenPolynomial<C>> row : Z.list) {
240            List<GenPolynomial<C>> zr = blas.leftScalarProduct(row, F.list);
241            if (!blas.isZero(zr)) {
242                logger.info("is not ZeroRelation ({}) = {}", zr.size(), zr);
243                return false;
244            }
245        }
246        return true;
247    }
248
249
250    /**
251     * Syzygy module from arbitrary base.
252     * @param F a polynomial list.
253     * @return syz(F), a basis for the module of syzygies for F.
254     */
255    public List<List<GenPolynomial<C>>> zeroRelationsArbitrary(List<GenPolynomial<C>> F) {
256        return zeroRelationsArbitrary(0, F);
257    }
258
259
260    /**
261     * Syzygy module from arbitrary module base.
262     * @param M an arbitrary module base.
263     * @return syz(M), a basis for the module of syzygies for M.
264     */
265    public ModuleList<C> zeroRelationsArbitrary(ModuleList<C> M) {
266        ModuleList<C> N = M;
267        if (M == null || M.list == null) {
268            return N;
269        }
270        if (M.rows == 0 || M.cols == 0) {
271            return N;
272        }
273        GenPolynomial<C> zero = M.ring.getZERO();
274        //System.out.println("zero = " + zero);
275
276        //ModuleList<C> Np = null;
277        PolynomialList<C> F = M.getPolynomialList();
278        int modv = M.cols; // > 0  
279        //System.out.println("modv = " + modv);
280        List<List<GenPolynomial<C>>> G = zeroRelationsArbitrary(modv, F.list);
281        List<List<GenPolynomial<C>>> Z = new ArrayList<List<GenPolynomial<C>>>();
282        for (int i = 0; i < G.size(); i++) {
283            //F = new PolynomialList(F.ring,(List)G.get(i));
284            List<GenPolynomial<C>> Gi = G.get(i);
285            List<GenPolynomial<C>> Zi = new ArrayList<GenPolynomial<C>>();
286            // System.out.println("\nG("+i+") = " + G.get(i));
287            for (int j = 0; j < Gi.size(); j++) {
288                //System.out.println("\nG("+i+","+j+") = " + Gi.get(j));
289                GenPolynomial<C> p = Gi.get(j);
290                if (p != null) {
291                    Map<ExpVector, GenPolynomial<C>> r = p.contract(M.ring);
292                    int s = 0;
293                    for (GenPolynomial<C> vi : r.values()) {
294                        Zi.add(vi);
295                        s++;
296                    }
297                    if (s == 0) {
298                        Zi.add(zero);
299                    } else if (s > 1) { // will not happen
300                        System.out.println("p = " + p);
301                        System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size());
302                        throw new RuntimeException("Map.size() > 1 = " + r.size());
303                    }
304                }
305            }
306            //System.out.println("\nZ("+i+") = " + Zi);
307            Z.add(Zi);
308        }
309        N = new ModuleList<C>(M.ring, Z);
310        //System.out.println("\n\nN = " + N);
311        return N;
312    }
313
314}
315
316
317/**
318 * Container for module resolution components.
319 * @param <C> coefficient type
320 */
321class ResPart<C extends RingElem<C>> implements Serializable {
322
323
324    public final ModuleList<C> module;
325
326
327    public final ModuleList<C> GB;
328
329
330    public final ModuleList<C> syzygy;
331
332
333    /**
334     * ResPart.
335     * @param m a module list.
336     * @param g a module list GB.
337     * @param z a syzygy module list.
338     */
339    public ResPart(ModuleList<C> m, ModuleList<C> g, ModuleList<C> z) {
340        module = m;
341        GB = g;
342        syzygy = z;
343    }
344
345
346    /**
347     * toString.
348     */
349    @Override
350    public String toString() {
351        StringBuffer s = new StringBuffer("ResPart(\n");
352        s.append("module = " + module);
353        s.append("\n GB = " + GB);
354        s.append("\n syzygy = " + syzygy);
355        s.append(")");
356        return s.toString();
357    }
358}
359
360
361/**
362 * Container for polynomial resolution components.
363 */
364class ResPolPart<C extends RingElem<C>> implements Serializable {
365
366
367    public final PolynomialList<C> ideal;
368
369
370    public final PolynomialList<C> GB;
371
372
373    public final ModuleList<C> syzygy;
374
375
376    /**
377     * ResPolPart.
378     * @param m a polynomial list.
379     * @param g a polynomial list GB.
380     * @param z a syzygy module list.
381     */
382    public ResPolPart(PolynomialList<C> m, PolynomialList<C> g, ModuleList<C> z) {
383        ideal = m;
384        GB = g;
385        syzygy = z;
386    }
387
388
389    /**
390     * toString.
391     */
392    @Override
393    public String toString() {
394        StringBuffer s = new StringBuffer("ResPolPart(\n");
395        s.append("ideal = " + ideal);
396        s.append("\n GB = " + GB);
397        s.append("\n syzygy = " + syzygy);
398        s.append(")");
399        return s.toString();
400    }
401
402}