001/*
002 * $Id: SolvableIdeal.java 5839 2018-05-20 20:30:09Z kredel $
003 */
004
005package edu.jas.application;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.List;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.gb.SolvableExtendedGB;
015import edu.jas.gb.SolvableGroebnerBaseAbstract;
016import edu.jas.gb.SolvableReduction;
017import edu.jas.gb.SolvableReductionSeq;
018import edu.jas.gbufd.PolyGBUtil;
019import edu.jas.gbufd.SGBFactory;
020import edu.jas.gbufd.SolvableSyzygyAbstract;
021import edu.jas.gbufd.SolvableSyzygySeq;
022import edu.jas.poly.GenSolvablePolynomial;
023import edu.jas.poly.GenSolvablePolynomialRing;
024import edu.jas.poly.PolyUtil;
025import edu.jas.poly.PolynomialList;
026import edu.jas.structure.GcdRingElem;
027import edu.jas.structure.NotInvertibleException;
028
029
030/**
031 * Solvable Ideal implements some methods for ideal arithmetic, for example sum,
032 * intersection, quotient. <b>Note:</b> only left ideals at the moment.
033 * @author Heinz Kredel
034 */
035public class SolvableIdeal<C extends GcdRingElem<C>> implements Comparable<SolvableIdeal<C>>, Serializable {
036
037
038    private static final Logger logger = Logger.getLogger(SolvableIdeal.class);
039
040
041    private static final boolean debug = logger.isDebugEnabled();
042
043
044    /**
045     * Side variant of ideal.
046     */
047    public static enum Side {
048        left, right, twosided
049    }
050
051
052    /**
053     * The data structure is a PolynomialList.
054     */
055    protected PolynomialList<C> list;
056
057
058    /**
059     * Indicator if list is a Groebner Base.
060     */
061    protected boolean isGB;
062
063
064    /**
065     * Indicator of side of Groebner Base.
066     */
067    protected Side sided;
068
069
070    /**
071     * Indicator if test has been performed if this is a Groebner Base.
072     */
073    protected boolean testGB;
074
075
076    /**
077     * Indicator if list has optimized term order.
078     */
079    protected boolean isTopt;
080
081
082    /**
083     * Groebner base engine.
084     */
085    protected final SolvableGroebnerBaseAbstract<C> bb;
086
087
088    /**
089     * Reduction engine.
090     */
091    protected final SolvableReduction<C> red;
092
093
094    /**
095     * Constructor.
096     * @param ring solvable polynomial ring
097     */
098    public SolvableIdeal(GenSolvablePolynomialRing<C> ring) {
099        this(ring, new ArrayList<GenSolvablePolynomial<C>>());
100    }
101
102
103    /**
104     * Constructor.
105     * @param ring solvable polynomial ring
106     * @param F list of solvable polynomials
107     */
108    public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F) {
109        this(new PolynomialList<C>(ring, F));
110    }
111
112
113    /**
114     * Constructor.
115     * @param ring solvable polynomial ring
116     * @param F list of solvable polynomials
117     * @param gb true if F is known to be a Groebner Base, else false
118     */
119    public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb) {
120        this(new PolynomialList<C>(ring, F), gb);
121    }
122
123
124    /**
125     * Constructor.
126     * @param ring solvable polynomial ring
127     * @param F list of solvable polynomials
128     * @param gb true if F is known to be a Groebner Base, else false
129     * @param topt true if term order is optimized, else false
130     */
131    public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb,
132                    boolean topt) {
133        this(new PolynomialList<C>(ring, F), gb, topt);
134    }
135
136
137    /**
138     * Constructor.
139     * @param ring solvable polynomial ring
140     * @param F list of solvable polynomials
141     * @param s side variant of ideal or Groebner Base
142     */
143    public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, Side s) {
144        this(new PolynomialList<C>(ring, F), false, false, s);
145    }
146
147
148    /**
149     * Constructor.
150     * @param ring solvable polynomial ring
151     * @param F list of solvable polynomials
152     * @param gb true if F is known to be a Groebner Base, else false
153     * @param s side variant of ideal or Groebner Base
154     */
155    public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb,
156                    Side s) {
157        this(new PolynomialList<C>(ring, F), gb, false, s);
158    }
159
160
161    /**
162     * Constructor.
163     * @param list solvable polynomial list
164     */
165    public SolvableIdeal(PolynomialList<C> list) {
166        this(list, false);
167    }
168
169
170    /**
171     * Constructor.
172     * @param list solvable polynomial list
173     * @param bb Groebner Base engine
174     * @param red Reduction engine
175     */
176    public SolvableIdeal(PolynomialList<C> list, SolvableGroebnerBaseAbstract<C> bb,
177                    SolvableReduction<C> red) {
178        this(list, false, bb, red);
179    }
180
181
182    /**
183     * Constructor.
184     * @param list solvable polynomial list
185     * @param gb true if list is known to be a Groebner Base, else false
186     */
187    public SolvableIdeal(PolynomialList<C> list, boolean gb) {
188        //this(list, gb, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>());
189        this(list, gb, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>());
190    }
191
192
193    /**
194     * Constructor.
195     * @param list solvable polynomial list
196     * @param gb true if list is known to be a Groebner Base, else false
197     * @param topt true if term order is optimized, else false
198     */
199    public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt) {
200        //this(list, gb, topt, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>());
201        this(list, gb, topt, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>());
202    }
203
204
205    /**
206     * Constructor.
207     * @param list solvable polynomial list
208     * @param gb true if list is known to be a Groebner Base, else false
209     * @param s side variant of ideal or Groebner Base
210     */
211    public SolvableIdeal(PolynomialList<C> list, boolean gb, Side s) {
212        //this(list, gb, false, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>());
213        this(list, gb, false, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>(),
214                        s);
215    }
216
217
218    /**
219     * Constructor.
220     * @param list solvable polynomial list
221     * @param gb true if list is known to be a Groebner Base, else false
222     * @param topt true if term order is optimized, else false
223     * @param s side variant of ideal or Groebner Base
224     */
225    public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, Side s) {
226        //this(list, gb, topt, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>());
227        this(list, gb, topt, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>(), s);
228    }
229
230
231    /**
232     * Constructor.
233     * @param list solvable polynomial list
234     * @param gb true if list is known to be a Groebner Base, else false
235     * @param bb Groebner Base engine
236     * @param red Reduction engine
237     */
238    public SolvableIdeal(PolynomialList<C> list, boolean gb, SolvableGroebnerBaseAbstract<C> bb,
239                    SolvableReduction<C> red) {
240        this(list, gb, false, bb, red);
241    }
242
243
244    /**
245     * Constructor.
246     * @param list solvable polynomial list
247     * @param gb true if list is known to be a Groebner Base, else false
248     * @param bb Groebner Base engine
249     */
250    public SolvableIdeal(PolynomialList<C> list, boolean gb, SolvableGroebnerBaseAbstract<C> bb) {
251        this(list, gb, false, bb, bb.sred);
252    }
253
254
255    /**
256     * Constructor.
257     * @param list solvable polynomial list
258     * @param gb true if list is known to be a Groebner Base, else false
259     * @param topt true if term order is optimized, else false
260     * @param bb Groebner Base engine
261     */
262    public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt,
263                    SolvableGroebnerBaseAbstract<C> bb) {
264        this(list, gb, topt, bb, bb.sred);
265    }
266
267
268    /**
269     * Constructor.
270     * @param list solvable polynomial list
271     * @param gb true if list is known to be a Groebner Base, else false
272     * @param topt true if term order is optimized, else false
273     * @param bb Groebner Base engine
274     * @param red Reduction engine
275     */
276    public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract<C> bb,
277                    SolvableReduction<C> red) {
278        this(list, gb, topt, bb, red, Side.left);
279    }
280
281
282    /**
283     * Constructor.
284     * @param list solvable polynomial list
285     * @param gb true if list is known to be a Groebner Base, else false
286     * @param topt true if term order is optimized, else false
287     * @param bb Groebner Base engine
288     * @param red Reduction engine
289     * @param s side variant of ideal or Groebner Base
290     */
291    public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract<C> bb,
292                    SolvableReduction<C> red, Side s) {
293        if (list == null || list.list == null) {
294            throw new IllegalArgumentException("list and list.list may not be null");
295        }
296        this.list = list;
297        this.isGB = gb;
298        this.isTopt = topt;
299        this.testGB = (gb ? true : false); // ??
300        this.bb = bb;
301        this.red = red;
302        if (s == null) {
303            s = Side.left; // default
304        }
305        this.sided = s;
306    }
307
308
309    /**
310     * Clone this.
311     * @return a copy of this.
312     */
313    public SolvableIdeal<C> copy() {
314        return new SolvableIdeal<C>(list.copy(), isGB, isTopt, bb, red, sided);
315    }
316
317
318    /**
319     * Get the List of GenSolvablePolynomials.
320     * @return (cast) list.list
321     */
322    public List<GenSolvablePolynomial<C>> getList() {
323        return list.getSolvableList();
324    }
325
326
327    /**
328     * Get the GenSolvablePolynomialRing.
329     * @return (cast) list.ring
330     */
331    public GenSolvablePolynomialRing<C> getRing() {
332        return list.getSolvableRing();
333    }
334
335
336    /**
337     * Get the zero ideal.
338     * @return ideal(0)
339     */
340    public SolvableIdeal<C> getZERO() {
341        List<GenSolvablePolynomial<C>> z = new ArrayList<GenSolvablePolynomial<C>>(0);
342        PolynomialList<C> pl = new PolynomialList<C>(getRing(), z);
343        return new SolvableIdeal<C>(pl, true, isTopt, bb, red, sided);
344    }
345
346
347    /**
348     * Get the one ideal.
349     * @return ideal(1)
350     */
351    public SolvableIdeal<C> getONE() {
352        List<GenSolvablePolynomial<C>> one = new ArrayList<GenSolvablePolynomial<C>>(1);
353        one.add(getRing().getONE());
354        PolynomialList<C> pl = new PolynomialList<C>(getRing(), one);
355        return new SolvableIdeal<C>(pl, true, isTopt, bb, red, sided);
356    }
357
358
359    /**
360     * String representation of the solvable ideal.
361     * @see java.lang.Object#toString()
362     */
363    @Override
364    public String toString() {
365        return list.toString() + " # " + sided;
366    }
367
368
369    /**
370     * Get a scripting compatible string representation.
371     * @return script compatible representation for this Element.
372     * @see edu.jas.structure.Element#toScript()
373     */
374    public String toScript() {
375        // any script case
376        return list.toScript() + " # " + sided;
377    }
378
379
380    /**
381     * Comparison with any other object. <b>Note:</b> If not both ideals are
382     * Groebner Bases, then false may be returned even the ideals are equal.
383     * @see java.lang.Object#equals(java.lang.Object)
384     */
385    @Override
386    @SuppressWarnings("unchecked")
387    public boolean equals(Object b) {
388        if (!(b instanceof SolvableIdeal)) {
389            logger.warn("equals no Ideal");
390            return false;
391        }
392        SolvableIdeal<C> B = null;
393        try {
394            B = (SolvableIdeal<C>) b;
395        } catch (ClassCastException ignored) {
396            return false;
397        }
398        //if ( isGB && B.isGB ) {
399        //   return list.equals( B.list ); requires also monic polys
400        //} else { // compute GBs ?
401        return this.contains(B) && B.contains(this);
402        //}
403    }
404
405
406    /**
407     * SolvableIdeal comparison.
408     * @param L other solvable ideal.
409     * @return compareTo() of polynomial lists.
410     */
411    public int compareTo(SolvableIdeal<C> L) {
412        return list.compareTo(L.list);
413    }
414
415
416    /**
417     * Hash code for this solvable ideal.
418     * @see java.lang.Object#hashCode()
419     */
420    @Override
421    public int hashCode() {
422        int h;
423        h = list.hashCode();
424        if (isGB) {
425            h = h << 1;
426        }
427        if (testGB) {
428            h += 1;
429        }
430        return h;
431    }
432
433
434    /**
435     * Test if ZERO ideal.
436     * @return true, if this is the 0 ideal, else false
437     */
438    public boolean isZERO() {
439        return list.isZERO();
440    }
441
442
443    /**
444     * Test if ONE is contained in the ideal. To test for a proper ideal use
445     * <code>! id.isONE()</code>.
446     * @return true, if this is the 1 ideal, else false
447     */
448    public boolean isONE() {
449        return list.isONE();
450    }
451
452
453    /**
454     * Test if this is a left Groebner base.
455     * @return true, if this is a left Groebner base, else false
456     */
457    public boolean isGB() {
458        if (testGB && sided == Side.left) {
459            return isGB;
460        }
461        logger.warn("isLeftGB computing");
462        boolean igb = bb.isLeftGB(getList());
463        if (sided != Side.left) {
464            logger.warn("wrong usage for is left sided GB: " + sided);
465            //sided = Side.left;
466        } else {
467            isGB = igb;
468            testGB = true;
469        }
470        return igb;
471    }
472
473
474    /**
475     * Do Groebner Base. compute the left Groebner Base for this ideal.
476     */
477    @SuppressWarnings("unchecked")
478    public void doGB() {
479        if (isGB && sided == Side.left) {
480            return;
481        }
482        if (isGB && sided == Side.twosided) {
483            return;
484        }
485        if (sided == Side.right) {
486            logger.warn("wrong usage for left sided GB: " + sided);
487            throw new IllegalArgumentException("wrong usage for left sided GB: " + sided);
488        }
489        List<GenSolvablePolynomial<C>> G = getList();
490        if (sided == Side.left) {
491            logger.info("leftGB computing = " + G);
492            G = bb.leftGB(G);
493        }
494        if (sided == Side.twosided) {
495            logger.info("twosidedGB computing = " + G);
496            G = bb.twosidedGB(G);
497        }
498        //if (isTopt) {
499        //    List<Integer> perm = ((OptimizedPolynomialList<C>) list).perm;
500        //    list = new OptimizedPolynomialList<C>(perm, getRing(), G);
501        //} else {
502        //}
503        list = new PolynomialList<C>(getRing(), G);
504        isGB = true;
505        testGB = true;
506        //sided = Side.left;
507        return;
508    }
509
510
511    /**
512     * Groebner Base. Get a left Groebner Base for this ideal.
513     * @return leftGB(this)
514     */
515    public SolvableIdeal<C> GB() {
516        if (isGB && sided == Side.left) {
517            return this;
518        }
519        doGB();
520        return this;
521    }
522
523
524    /**
525     * Test if this is a twosided Groebner base.
526     * @return true, if this is a twosided Groebner base, else false
527     */
528    public boolean isTwosidedGB() {
529        if (testGB && sided == Side.twosided) {
530            return isGB;
531        }
532        logger.warn("isTwosidedGB computing");
533        isGB = bb.isTwosidedGB(getList());
534        testGB = true;
535        sided = Side.twosided;
536        return isGB;
537    }
538
539
540    /**
541     * Groebner Base. Get a twosided Groebner Base for this ideal.
542     * @return twosidedGB(this)
543     */
544    public SolvableIdeal<C> twosidedGB() {
545        if (isGB && sided == Side.twosided) {
546            return this;
547        }
548        //logger.warn("GB computing");
549        List<GenSolvablePolynomial<C>> G = getList();
550        logger.info("twosidedGB computing = " + G);
551        G = bb.twosidedGB(G);
552        PolynomialList<C> li = new PolynomialList<C>(getRing(), G);
553        SolvableIdeal<C> tsgb = new SolvableIdeal<C>(li, true, true, bb, red, Side.twosided);
554        return tsgb;
555    }
556
557
558    /**
559     * Test if this is a right Groebner base.
560     * @return true, if this is a right Groebner base, else false
561     */
562    public boolean isRightGB() {
563        if (testGB && sided == Side.right) {
564            return isGB;
565        }
566        if (isGB && sided == Side.twosided) {
567            return true;
568        }
569        logger.warn("isRightGB computing");
570        isGB = bb.isRightGB(getList());
571        testGB = true;
572        sided = Side.right;
573        return isGB;
574    }
575
576
577    /**
578     * Groebner Base. Get a right Groebner Base for this ideal.
579     * @return rightGB(this)
580     */
581    public SolvableIdeal<C> rightGB() {
582        if (isGB && sided == Side.twosided) {
583            return this;
584        }
585        if (isGB && sided == Side.right) {
586            return this;
587        }
588        //logger.warn("GB computing");
589        List<GenSolvablePolynomial<C>> G = getList();
590        logger.info("rightGB computing = " + G);
591        G = bb.rightGB(G);
592        PolynomialList<C> li = new PolynomialList<C>(getRing(), G);
593        SolvableIdeal<C> rgb = new SolvableIdeal<C>(li, true, true, bb, red, Side.right);
594        return rgb;
595    }
596
597
598    /**
599     * Solvable ideal containment. Test if B is contained in this ideal. Note:
600     * this is eventually modified to become a Groebner Base.
601     * @param B solvable ideal
602     * @return true, if B is contained in this, else false
603     */
604    public boolean contains(SolvableIdeal<C> B) {
605        if (B == null || B.isZERO()) {
606            return true;
607        }
608        return contains(B.getList());
609    }
610
611
612    /**
613     * Solvable ideal containment. Test if b is contained in this ideal. Note:
614     * this is eventually modified to become a Groebner Base.
615     * @param b solvable polynomial
616     * @return true, if b is contained in this, else false
617     */
618    public boolean contains(GenSolvablePolynomial<C> b) {
619        if (b == null || b.isZERO()) {
620            return true;
621        }
622        if (this.isONE()) {
623            return true;
624        }
625        if (this.isZERO()) {
626            return false;
627        }
628        if (!isGB) {
629            doGB();
630        }
631        GenSolvablePolynomial<C> z = red.leftNormalform(getList(), b);
632        if (z == null || z.isZERO()) {
633            return true;
634        }
635        return false;
636    }
637
638
639    /**
640     * Solvable ideal containment. Test if each b in B is contained in this
641     * ideal. Note: this is eventually modified to become a Groebner Base.
642     * @param B list of solvable polynomials
643     * @return true, if each b in B is contained in this, else false
644     */
645    public boolean contains(List<GenSolvablePolynomial<C>> B) {
646        if (B == null || B.size() == 0) {
647            return true;
648        }
649        if (this.isONE()) {
650            return true;
651        }
652        if (!isGB) {
653            doGB();
654        }
655        List<GenSolvablePolynomial<C>> si = getList();
656        for (GenSolvablePolynomial<C> b : B) {
657            if (b == null) {
658                continue;
659            }
660            GenSolvablePolynomial<C> z = red.leftNormalform(si, b);
661            if (!z.isZERO()) {
662                logger.info("contains nf(b) != 0: " + z + " of " + b);
663                //        + ", si = " + si + ", ring = " + z.ring.toScript());
664                return false;
665            }
666        }
667        return true;
668    }
669
670
671    /**
672     * Solvable ideal summation. Generators for the sum of ideals. Note: if both
673     * ideals are Groebner bases, a Groebner base is returned.
674     * @param B solvable ideal
675     * @return ideal(this+B)
676     */
677    public SolvableIdeal<C> sum(SolvableIdeal<C> B) {
678        if (B == null || B.isZERO()) {
679            return this;
680        }
681        if (this.isZERO()) {
682            return B;
683        }
684        int s = getList().size() + B.getList().size();
685        List<GenSolvablePolynomial<C>> c;
686        c = new ArrayList<GenSolvablePolynomial<C>>(s);
687        c.addAll(getList());
688        c.addAll(B.getList());
689        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided);
690        if (isGB && B.isGB) {
691            I.doGB(); // left, twosided, right handled in doGB
692        }
693        return I;
694    }
695
696
697    /**
698     * Solvable summation. Generators for the sum of ideal and a polynomial.
699     * Note: if this ideal is a Groebner base, a Groebner base is returned.
700     * @param b solvable polynomial
701     * @return ideal(this+{b})
702     */
703    public SolvableIdeal<C> sum(GenSolvablePolynomial<C> b) {
704        if (b == null || b.isZERO()) {
705            return this;
706        }
707        int s = getList().size() + 1;
708        List<GenSolvablePolynomial<C>> c;
709        c = new ArrayList<GenSolvablePolynomial<C>>(s);
710        c.addAll(getList());
711        c.add(b);
712        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided);
713        if (isGB) {
714            I.doGB();
715        }
716        return I;
717    }
718
719
720    /**
721     * Solvable summation. Generators for the sum of this ideal and a list of
722     * polynomials. Note: if this ideal is a Groebner base, a Groebner base is
723     * returned.
724     * @param L list of solvable polynomials
725     * @return ideal(this+L)
726     */
727    public SolvableIdeal<C> sum(List<GenSolvablePolynomial<C>> L) {
728        if (L == null || L.isEmpty()) {
729            return this;
730        }
731        int s = getList().size() + L.size();
732        List<GenSolvablePolynomial<C>> c = new ArrayList<GenSolvablePolynomial<C>>(s);
733        c.addAll(getList());
734        c.addAll(L);
735        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided);
736        if (isGB) {
737            I.doGB();
738        }
739        return I;
740    }
741
742
743    /**
744     * Product. Generators for the product of ideals. Note: if both ideals are
745     * Groebner bases, a Groebner base is returned.
746     * @param B solvable ideal
747     * @return ideal(this*B)
748     */
749    public SolvableIdeal<C> product(SolvableIdeal<C> B) {
750        if (B == null || B.isZERO()) {
751            return B;
752        }
753        if (this.isZERO()) {
754            return this;
755        }
756        int s = getList().size() * B.getList().size();
757        List<GenSolvablePolynomial<C>> c;
758        c = new ArrayList<GenSolvablePolynomial<C>>(s);
759        for (GenSolvablePolynomial<C> p : getList()) {
760            for (GenSolvablePolynomial<C> q : B.getList()) {
761                q = p.multiply(q);
762                c.add(q);
763            }
764        }
765        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided);
766        if (isGB && B.isGB) {
767            I.doGB();
768        }
769        return I;
770    }
771
772
773    /**
774     * Left product. Generators for the product this by a polynomial.
775     * @param b solvable polynomial
776     * @return ideal(this*b)
777     */
778    public SolvableIdeal<C> product(GenSolvablePolynomial<C> b) {
779        if (b == null || b.isZERO()) {
780            return getZERO();
781        }
782        if (this.isZERO()) {
783            return this;
784        }
785        List<GenSolvablePolynomial<C>> c;
786        c = new ArrayList<GenSolvablePolynomial<C>>(getList().size());
787        for (GenSolvablePolynomial<C> p : getList()) {
788            GenSolvablePolynomial<C> q = p.multiply(b);
789            c.add(q);
790        }
791        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided);
792        if (isGB) {
793            I.doGB();
794        }
795        return I;
796    }
797
798
799    /**
800     * Intersection. Generators for the intersection of ideals. Using an
801     * iterative algorithm.
802     * @param Bl list of solvable ideals
803     * @return ideal(cap_i B_i), a Groebner base
804     */
805    public SolvableIdeal<C> intersect(List<SolvableIdeal<C>> Bl) {
806        if (Bl == null || Bl.size() == 0) {
807            return getZERO();
808        }
809        SolvableIdeal<C> I = null;
810        for (SolvableIdeal<C> B : Bl) {
811            if (I == null) {
812                I = B;
813                continue;
814            }
815            if (I.isONE()) {
816                return I;
817            }
818            I = I.intersect(B);
819        }
820        return I;
821    }
822
823
824    /**
825     * Intersection. Generators for the intersection of ideals.
826     * @param B solvable ideal
827     * @return ideal(this \cap B), a Groebner base
828     */
829    public SolvableIdeal<C> intersect(SolvableIdeal<C> B) {
830        if (B == null || B.isZERO()) { // (0)
831            return B;
832        }
833        if (this.isZERO()) {
834            return this;
835        }
836        List<GenSolvablePolynomial<C>> c = PolyGBUtil.<C> intersect(getRing(), getList(), B.getList());
837        SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, true, sided);
838        return I;
839    }
840
841
842    /**
843     * Intersection. Generators for the intersection of a ideal with a
844     * polynomial ring. The polynomial ring R must be a contraction
845     * of this ideal and the TermOrder must be an elimination order.
846     * @param R solvable polynomial ring
847     * @return ideal(this \cap R)
848     */
849    public SolvableIdeal<C> intersect(GenSolvablePolynomialRing<C> R) {
850        if (R == null) {
851            throw new IllegalArgumentException("R may not be null");
852        }
853        String[] rvars = R.getVars();
854        String[] tvars = getRing().getVars();
855        for (int i = 0; i < rvars.length; i++) {
856            if (rvars[i] != tvars[i]) {
857                throw new IllegalArgumentException("no contraction: " + R.toScript() 
858                                                 + " of " + getRing().toScript());
859            }
860        }
861        List<GenSolvablePolynomial<C>> H = PolyUtil.<C> intersect(R, getList());
862        return new SolvableIdeal<C>(R, H, isGB, sided);
863    }
864
865
866    /**
867     * Eliminate. Generators for the intersection of this ideal with a solvable
868     * polynomial ring. The solvable polynomial ring of this ideal must be a
869     * contraction of R and the TermOrder must be an elimination order.
870     * @param R solvable polynomial ring
871     * @return ideal(this \cap R)
872     */
873    public SolvableIdeal<C> eliminate(GenSolvablePolynomialRing<C> R) {
874        if (R == null) {
875            throw new IllegalArgumentException("R may not be null");
876        }
877        if (getRing().equals(R)) {
878            return this;
879        }
880        return intersect(R);
881    }
882
883
884    /**
885     * Quotient. Generators for the solvable ideal quotient.
886     * @param h solvable polynomial
887     * @return ideal(this : h), a Groebner base
888     */
889    //@SuppressWarnings("unchecked")
890    public SolvableIdeal<C> quotient(GenSolvablePolynomial<C> h) {
891        if (h == null) { // == (0)
892            return this;
893        }
894        if (h.isZERO()) {
895            return this;
896        }
897        if (this.isZERO()) {
898            return this;
899        }
900        List<GenSolvablePolynomial<C>> H;
901        H = new ArrayList<GenSolvablePolynomial<C>>(1);
902        H.add(h);
903        SolvableIdeal<C> Hi = new SolvableIdeal<C>(getRing(), H, true, sided);
904
905        SolvableIdeal<C> I = this.intersect(Hi);
906
907        List<GenSolvablePolynomial<C>> Q;
908        Q = new ArrayList<GenSolvablePolynomial<C>>(I.getList().size());
909        GenSolvablePolynomial<C> p;
910        for (GenSolvablePolynomial<C> q : I.getList()) {
911            p = q.divide(h); // remainder == 0, (GenSolvablePolynomial<C>)
912            if (!p.isZERO()) {
913                p = p.monic();
914                Q.add(p);
915            }
916            if (debug) {
917                GenSolvablePolynomial<C> r = q.remainder(h); // (GenSolvablePolynomial<C>)
918                if (!r.isZERO()) {
919                    System.out.println("error remainder !=0: " + r + ", q = " + q + ", h = " + h);
920                    throw new RuntimeException("remainder !=0");
921                }
922            }
923        }
924        return new SolvableIdeal<C>(getRing(), Q, true /*false?*/, sided);
925    }
926
927
928    /**
929     * Quotient. Generators for the solvable ideal quotient.
930     * @param H solvable ideal
931     * @return ideal(this : H), a Groebner base
932     */
933    public SolvableIdeal<C> quotient(SolvableIdeal<C> H) {
934        if (H == null || H.isZERO()) { // == (0)
935            return this;
936        }
937        if (this.isZERO()) {
938            return this;
939        }
940        SolvableIdeal<C> Q = null;
941        for (GenSolvablePolynomial<C> h : H.getList()) {
942            SolvableIdeal<C> Hi = this.quotient(h);
943            if (Q == null) {
944                Q = Hi;
945            } else {
946                Q = Q.intersect(Hi);
947            }
948        }
949        return Q;
950    }
951
952
953    /**
954     * Infinite quotient. Generators for the infinite solvable ideal quotient.
955     * @param h solvable polynomial
956     * @return ideal(this : h<sup>s</sup>), a Groebner base
957     */
958    public SolvableIdeal<C> infiniteQuotientRab(GenSolvablePolynomial<C> h) {
959        if (h == null || h.isZERO()) { // == (0)
960            return getONE();
961        }
962        if (h.isONE()) {
963            return this;
964        }
965        if (this.isZERO()) {
966            return this;
967        }
968        if (!getRing().isCommutative()) {
969            throw new UnsupportedOperationException("Rabinowich trick only for commutative polynomial rings");
970        }
971        SolvableIdeal<C> I = this.GB(); // should be already
972        List<GenSolvablePolynomial<C>> a = I.getList();
973        List<GenSolvablePolynomial<C>> c;
974        c = new ArrayList<GenSolvablePolynomial<C>>(a.size() + 1);
975
976        GenSolvablePolynomialRing<C> tfac = getRing().extend(1);
977        // term order is also adjusted
978        for (GenSolvablePolynomial<C> p : a) {
979            p = (GenSolvablePolynomial<C>) p.extend(tfac, 0, 0L); // p
980            c.add(p);
981        }
982        GenSolvablePolynomial<C> q = (GenSolvablePolynomial<C>) h.extend(tfac, 0, 1L);
983        GenSolvablePolynomial<C> r = tfac.getONE(); // h.extend( tfac, 0, 0L );
984        GenSolvablePolynomial<C> hs = (GenSolvablePolynomial<C>) q.subtract(r); // 1 - t*h // (1-t)*h
985        c.add(hs);
986        logger.warn("infiniteQuotientRab computing GB ");
987        List<GenSolvablePolynomial<C>> g = bb.leftGB(c);
988        if (debug) {
989            logger.info("infiniteQuotientRab    = " + tfac + ", c = " + c);
990            logger.info("infiniteQuotientRab GB = " + g);
991        }
992        SolvableIdeal<C> E = new SolvableIdeal<C>(tfac, g, true, sided);
993        SolvableIdeal<C> Is = E.intersect(getRing());
994        return Is;
995    }
996
997
998    /**
999     * Infinite quotient exponent.
1000     * @param h solvable polynomial
1001     * @param Q quotient this : h^\infinity
1002     * @return s with Q = this : h<sup>s</sup>
1003     */
1004    public int infiniteQuotientExponent(GenSolvablePolynomial<C> h, SolvableIdeal<C> Q) {
1005        int s = 0;
1006        if (h == null) { // == 0
1007            return s;
1008        }
1009        if (h.isZERO() || h.isONE()) {
1010            return s;
1011        }
1012        if (this.isZERO() || this.isONE()) {
1013            return s;
1014        }
1015        //see below: if (this.contains(Q)) {
1016        //    return s;
1017        //}
1018        GenSolvablePolynomial<C> p = getRing().getONE();
1019        for (GenSolvablePolynomial<C> q : Q.getList()) {
1020            if (this.contains(q)) {
1021                continue;
1022            }
1023            //System.out.println("q = " + q + ", p = " + p + ", s = " + s);
1024            GenSolvablePolynomial<C> qp = q.multiply(p);
1025            while (!this.contains(qp)) {
1026                p = p.multiply(h);
1027                s++;
1028                qp = q.multiply(p);
1029            }
1030        }
1031        return s;
1032    }
1033
1034
1035    /**
1036     * Infinite quotient. Generators for the infinite solvable ideal quotient.
1037     * @param h solvable polynomial
1038     * @return ideal(this : h<sup>s</sup>), a Groebner base
1039     */
1040    public SolvableIdeal<C> infiniteQuotient(GenSolvablePolynomial<C> h) {
1041        if (h == null) { // == (0)
1042            return this;
1043        }
1044        if (h.isZERO()) {
1045            return this;
1046        }
1047        if (this.isZERO()) {
1048            return this;
1049        }
1050        int s = 0;
1051        SolvableIdeal<C> I = this.GB(); // should be already
1052        GenSolvablePolynomial<C> hs = h;
1053        SolvableIdeal<C> Is = null;
1054        logger.info("infiniteQuotient hs = " + hs);
1055        long dm = -1;
1056        boolean eq = false;
1057        while (!eq) {
1058            Is = I.quotient(hs);
1059            Is = Is.GB(); // should be already
1060            //logger.info("ideal Is = " + Is);
1061            logger.info("infiniteQuotient s = " + s);
1062            if (Is.isZERO()) {
1063                logger.warn("infiniteQuotient does not exist");
1064                return I;
1065            }
1066            eq = Is.contains(I); // I.contains(Is) always
1067            if (!eq) {
1068                long ds = PolyUtil.<C> totalDegree(Is.list.getList());
1069                if (dm < 0) {
1070                    dm = ds;
1071                }
1072                //System.out.println("deg(Is) = " + ds);
1073                if (ds > dm) {
1074                    logger.warn("no convergence in infiniteQuotient (dm,ds): " + dm + " < " + ds);
1075                    return I;
1076                    //throw new RuntimeException("no convergence in infiniteQuotient");
1077                }
1078                I = Is;
1079                s++;
1080                // hs = hs.multiply( h );
1081            }
1082        }
1083        return Is;
1084    }
1085
1086
1087    /**
1088     * Radical membership test.
1089     * @param h solvable polynomial
1090     * @return true if h is contained in the radical of ideal(this), else false.
1091     */
1092    public boolean isRadicalMember(GenSolvablePolynomial<C> h) {
1093        if (h == null) { // == (0)
1094            return true;
1095        }
1096        if (h.isZERO()) {
1097            return true;
1098        }
1099        if (this.isZERO()) {
1100            return true;
1101        }
1102        SolvableIdeal<C> x = infiniteQuotientRab(h); // may fail
1103        if (debug) {
1104            logger.debug("infiniteQuotientRab = " + x);
1105        }
1106        return x.isONE();
1107    }
1108
1109
1110    /**
1111     * Infinite Quotient. Generators for the solvable ideal infinite quotient.
1112     * @param H solvable ideal
1113     * @return ideal(this : H<sup>s</sup>), a Groebner base
1114     */
1115    public SolvableIdeal<C> infiniteQuotient(SolvableIdeal<C> H) {
1116        if (H == null) { // == (0)
1117            return this;
1118        }
1119        if (H.isZERO()) {
1120            return this;
1121        }
1122        if (this.isZERO()) {
1123            return this;
1124        }
1125        SolvableIdeal<C> Q = null;
1126        for (GenSolvablePolynomial<C> h : H.getList()) {
1127            SolvableIdeal<C> Hi = this.infiniteQuotient(h);
1128            if (Q == null) {
1129                Q = Hi;
1130            } else {
1131                Q = Q.intersect(Hi);
1132            }
1133        }
1134        return Q;
1135    }
1136
1137
1138    /**
1139     * Infinite Quotient. Generators for the solvable ideal infinite quotient.
1140     * @param H solvable ideal
1141     * @return ideal(this : H<sup>s</sup>), a Groebner base
1142     */
1143    public SolvableIdeal<C> infiniteQuotientRab(SolvableIdeal<C> H) {
1144        if (H == null) { // == (0)
1145            return this;
1146        }
1147        if (H.isZERO()) {
1148            return this;
1149        }
1150        if (this.isZERO()) {
1151            return this;
1152        }
1153        SolvableIdeal<C> Q = null;
1154        for (GenSolvablePolynomial<C> h : H.getList()) {
1155            SolvableIdeal<C> Hi = this.infiniteQuotientRab(h); // may fail
1156            if (Q == null) {
1157                Q = Hi;
1158            } else {
1159                Q = Q.intersect(Hi);
1160            }
1161        }
1162        return Q;
1163    }
1164
1165
1166    /**
1167     * Power. Generators for the power of this solvable ideal. Note: if this
1168     * ideal is a Groebner base, a Groebner base is returned.
1169     * @param d integer
1170     * @return ideal(this^d)
1171     */
1172    public SolvableIdeal<C> power(int d) {
1173        if (d <= 0) {
1174            return getONE();
1175        }
1176        if (this.isZERO() || this.isONE()) {
1177            return this;
1178        }
1179        SolvableIdeal<C> c = this;
1180        for (int i = 1; i < d; i++) {
1181            c = c.product(this);
1182        }
1183        return c;
1184    }
1185
1186
1187    /**
1188     * Normalform for element.
1189     * @param h solvable polynomial
1190     * @return left normalform of h with respect to this
1191     */
1192    public GenSolvablePolynomial<C> normalform(GenSolvablePolynomial<C> h) {
1193        if (h == null) {
1194            return h;
1195        }
1196        if (h.isZERO()) {
1197            return h;
1198        }
1199        if (this.isZERO()) {
1200            return h;
1201        }
1202        GenSolvablePolynomial<C> r;
1203        r = red.leftNormalform(getList(), h);
1204        return r;
1205    }
1206
1207
1208    /**
1209     * Normalform for list of solvable elements.
1210     * @param L solvable polynomial list
1211     * @return list of left normalforms of the elements of L with respect to
1212     *         this
1213     */
1214    public List<GenSolvablePolynomial<C>> normalform(List<GenSolvablePolynomial<C>> L) {
1215        if (L == null) {
1216            return L;
1217        }
1218        if (L.size() == 0) {
1219            return L;
1220        }
1221        if (this.isZERO()) {
1222            return L;
1223        }
1224        List<GenSolvablePolynomial<C>> M = new ArrayList<GenSolvablePolynomial<C>>(L.size());
1225        for (GenSolvablePolynomial<C> h : L) {
1226            GenSolvablePolynomial<C> r = normalform(h);
1227            if (r != null && !r.isZERO()) {
1228                M.add(r);
1229            }
1230        }
1231        return M;
1232    }
1233
1234
1235    /**
1236     * Annihilator for element modulo this ideal.
1237     * @param h solvable polynomial
1238     * @return annihilator of h with respect to this
1239     */
1240    public SolvableIdeal<C> annihilator(GenSolvablePolynomial<C> h) {
1241        if (h == null || h.isZERO()) {
1242            return getZERO();
1243        }
1244        if (this.isZERO()) {
1245            return this;
1246        }
1247        doGB();
1248        List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + getList().size());
1249        F.add(h);
1250        F.addAll(getList());
1251        //System.out.println("F = " + F);
1252        SolvableSyzygyAbstract<C> syz = new SolvableSyzygySeq<C>(getRing().coFac);
1253        List<List<GenSolvablePolynomial<C>>> S = syz.leftZeroRelationsArbitrary(F);
1254        //System.out.println("S = " + S);
1255        List<GenSolvablePolynomial<C>> gen = new ArrayList<GenSolvablePolynomial<C>>(S.size());
1256        for (List<GenSolvablePolynomial<C>> rel : S) {
1257            if (rel == null || rel.isEmpty()) {
1258                continue;
1259            }
1260            GenSolvablePolynomial<C> p = rel.get(0);
1261            if (p == null || p.isZERO()) {
1262                continue;
1263            }
1264            gen.add(p);
1265        }
1266        SolvableIdeal<C> ann = new SolvableIdeal<C>(getRing(), gen, false, sided);
1267        //System.out.println("ann = " + ann);
1268        return ann;
1269    }
1270
1271
1272    /**
1273     * Test for annihilator of element modulo this ideal.
1274     * @param h solvable polynomial
1275     * @param A solvable ideal
1276     * @return true, if A is the annihilator of h with respect to this
1277     */
1278    public boolean isAnnihilator(GenSolvablePolynomial<C> h, SolvableIdeal<C> A) {
1279        SolvableIdeal<C> B = A.product(h);
1280        return contains(B);
1281    }
1282
1283
1284    /**
1285     * Annihilator for ideal modulo this ideal.
1286     * @param H solvable ideal
1287     * @return annihilator of H with respect to this
1288     */
1289    public SolvableIdeal<C> annihilator(SolvableIdeal<C> H) {
1290        if (H == null || H.isZERO()) {
1291            return getZERO();
1292        }
1293        if (this.isZERO()) {
1294            return this;
1295        }
1296        SolvableIdeal<C> ann = null;
1297        for (GenSolvablePolynomial<C> h : H.getList()) {
1298            SolvableIdeal<C> Hi = this.annihilator(h);
1299            if (ann == null) {
1300                ann = Hi;
1301            } else {
1302                ann = ann.intersect(Hi);
1303            }
1304        }
1305        return ann;
1306    }
1307
1308
1309    /**
1310     * Test for annihilator of ideal modulo this ideal.
1311     * @param H solvable ideal
1312     * @param A solvable ideal
1313     * @return true, if A is the annihilator of H with respect to this
1314     */
1315    public boolean isAnnihilator(SolvableIdeal<C> H, SolvableIdeal<C> A) {
1316        SolvableIdeal<C> B = A.product(H);
1317        return contains(B);
1318    }
1319
1320
1321    /**
1322     * Inverse for element modulo this ideal.
1323     * @param h solvable polynomial
1324     * @return inverse of h with respect to this, if defined
1325     */
1326    public GenSolvablePolynomial<C> inverse(GenSolvablePolynomial<C> h) {
1327        if (h == null || h.isZERO()) {
1328            throw new NotInvertibleException("zero not invertible");
1329        }
1330        if (this.isZERO()) {
1331            throw new NotInvertibleException("zero ideal");
1332        }
1333        if (h.isUnit()) {
1334            return (GenSolvablePolynomial<C>) h.inverse();
1335        }
1336        doGB();
1337        List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + list.list.size());
1338        F.add(h);
1339        F.addAll(getList());
1340        //System.out.println("F = " + F);
1341        SolvableExtendedGB<C> x = bb.extLeftGB(F);
1342        List<GenSolvablePolynomial<C>> G = x.G;
1343        //System.out.println("G = " + G);
1344        GenSolvablePolynomial<C> one = null;
1345        int i = -1;
1346        for (GenSolvablePolynomial<C> p : G) {
1347            i++;
1348            if (p == null) {
1349                continue;
1350            }
1351            if (p.isUnit()) {
1352                one = p;
1353                break;
1354            }
1355        }
1356        if (one == null) {
1357            throw new NotInvertibleException("one == null: h = " + h);
1358        }
1359        List<GenSolvablePolynomial<C>> row = x.G2F.get(i); // != -1
1360        //System.out.println("row = " + row);
1361        GenSolvablePolynomial<C> g = row.get(0);
1362        if (g == null || g.isZERO()) {
1363            throw new NotInvertibleException("g == 0: h = " + h);
1364        }
1365        GenSolvablePolynomial<C> gp = red.leftNormalform(getList(), g);
1366        if (gp.isZERO()) { // can happen with solvable rings
1367            throw new NotInvertibleException("solv|gp == 0: h = " + h + ", g = " + g);
1368        }
1369        // adjust leading coefficient of g to get g*h == 1
1370        GenSolvablePolynomial<C> f = g.multiply(h);
1371        //System.out.println("f = " + f);
1372        GenSolvablePolynomial<C> k = red.leftNormalform(getList(), f);
1373        //System.out.println("k = " + k);
1374        if (!k.isONE()) {
1375            C lbc = k.leadingBaseCoefficient();
1376            lbc = lbc.inverse();
1377            g = g.multiply(lbc);
1378        }
1379        if (debug) {
1380            //logger.info("inv G = " + G);
1381            //logger.info("inv G2F = " + x.G2F);
1382            //logger.info("inv row "+i+" = " + row);
1383            //logger.info("inv h = " + h);
1384            //logger.info("inv g = " + g);
1385            //logger.info("inv f = " + f);
1386            f = g.multiply(h);
1387            k = red.leftNormalform(getList(), f);
1388            logger.debug("inv k = " + k);
1389            if (!k.isUnit()) {
1390                throw new NotInvertibleException(" k = " + k);
1391            }
1392        }
1393        return g;
1394    }
1395
1396
1397    /**
1398     * Test if element is a unit modulo this ideal.
1399     * @param h solvable polynomial
1400     * @return true if h is a unit with respect to this, else false
1401     */
1402    public boolean isUnit(GenSolvablePolynomial<C> h) {
1403        if (h == null || h.isZERO()) {
1404            return false;
1405        }
1406        if (this.isZERO()) {
1407            return false;
1408        }
1409        List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + list.list.size());
1410        F.add(h);
1411        F.addAll(getList());
1412        List<GenSolvablePolynomial<C>> G = bb.leftGB(F);
1413        for (GenSolvablePolynomial<C> p : G) {
1414            if (p == null) {
1415                continue;
1416            }
1417            if (p.isUnit()) {
1418                return true;
1419            }
1420        }
1421        return false;
1422    }
1423
1424
1425    /**
1426     * Ideal common zero test.
1427     * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or &ge; 1.
1428     */
1429    public int commonZeroTest() {
1430        if (this.isZERO()) {
1431            return 1;
1432        }
1433        if (!isGB) {
1434            doGB();
1435        }
1436        if (this.isONE()) {
1437            return -1;
1438        }
1439        return bb.commonZeroTest(getList());
1440    }
1441
1442
1443    /**
1444     * Test if this ideal is maximal.
1445     * @return true, if this is maximal and not one, else false.
1446     */
1447    public boolean isMaximal() {
1448        if (commonZeroTest() != 0) {
1449            return false;
1450        }
1451        for (Long d : univariateDegrees()) {
1452            if (d > 1L) {
1453                // todo: test if univariate irreducible and no multiple polynomials
1454                return false;
1455            }
1456        }
1457        return true;
1458    }
1459
1460
1461    /**
1462     * Univariate head term degrees.
1463     * @return a list of the degrees of univariate head terms.
1464     */
1465    public List<Long> univariateDegrees() {
1466        List<Long> ud = new ArrayList<Long>();
1467        if (this.isZERO()) {
1468            return ud;
1469        }
1470        if (!isGB) {
1471            doGB();
1472        }
1473        if (this.isONE()) {
1474            return ud;
1475        }
1476        return bb.univariateDegrees(getList());
1477    }
1478
1479
1480    /**
1481     * Ideal dimension.
1482     * @return a dimension container (dim,maxIndep,list(maxIndep),vars).
1483     */
1484    public Dimension dimension() {
1485        Ideal<C> ci = new Ideal<C>(list);
1486        return ci.dimension();
1487    }
1488
1489
1490    /**
1491     * Construct univariate polynomials of minimal degree in all variables in
1492     * zero dimensional ideal(G).
1493     * @return list of univariate solvable polynomial of minimal degree in each
1494     *         variable in ideal(G)
1495     */
1496    public List<GenSolvablePolynomial<C>> constructUnivariate() {
1497        List<GenSolvablePolynomial<C>> univs = new ArrayList<GenSolvablePolynomial<C>>();
1498        for (int i = getRing().nvar - 1; i >= 0; i--) {
1499            GenSolvablePolynomial<C> u = constructUnivariate(i);
1500            univs.add(u);
1501        }
1502        return univs;
1503    }
1504
1505
1506    /**
1507     * Construct univariate polynomial of minimal degree in variable i in zero
1508     * dimensional ideal(G).
1509     * @param i variable index.
1510     * @return univariate solvable polynomial of minimal degree in variable i in
1511     *         ideal(G)
1512     */
1513    public GenSolvablePolynomial<C> constructUnivariate(int i) {
1514        doGB();
1515        return bb.constructUnivariate(i, getList());
1516    }
1517
1518}