001    /*
002     * $Id: MultiplicativeSet.java 3423 2010-12-24 10:56:50Z kredel $
003     */
004    
005    package edu.jas.gbufd;
006    
007    
008    import java.io.Serializable;
009    import java.util.ArrayList;
010    import java.util.List;
011    
012    import org.apache.log4j.Logger;
013    
014    import edu.jas.poly.GenPolynomial;
015    import edu.jas.poly.GenPolynomialRing;
016    import edu.jas.structure.GcdRingElem;
017    
018    
019    /**
020     * Multiplicative set of polynomials. a, b in M implies a*b in M, 1 in M.
021     * @param <C> coefficient type
022     * @author Heinz Kredel.
023     */
024    public class MultiplicativeSet<C extends GcdRingElem<C>> implements Serializable {
025    
026    
027        private static final Logger logger = Logger.getLogger(MultiplicativeSet.class);
028    
029    
030        private final boolean debug = logger.isDebugEnabled();
031    
032    
033        /**
034         * Data structure.
035         */
036        public final List<GenPolynomial<C>> mset;
037    
038    
039        /**
040         * Polynomial ring factory.
041         */
042        public final GenPolynomialRing<C> ring;
043    
044    
045        /**
046         * MultiplicativeSet constructor. Constructs an empty multiplicative set.
047         * @param ring polynomial ring factory for coefficients.
048         */
049        public MultiplicativeSet(GenPolynomialRing<C> ring) {
050            this(ring, new ArrayList<GenPolynomial<C>>());
051            if (ring == null) {
052                throw new IllegalArgumentException("only for non null rings");
053            }
054        }
055    
056    
057        /**
058         * MultiplicativeSet constructor.
059         * @param ring polynomial ring factory for coefficients.
060         * @param ms a list of non-zero polynomials.
061         */
062        protected MultiplicativeSet(GenPolynomialRing<C> ring, List<GenPolynomial<C>> ms) {
063            if (ms == null || ring == null) {
064                throw new IllegalArgumentException("only for non null parts");
065            }
066            this.ring = ring;
067            mset = ms;
068        }
069    
070    
071        /**
072         * toString.
073         * @see java.lang.Object#toString()
074         */
075        @Override
076        public String toString() {
077            return "MultiplicativeSet" + mset;
078        }
079    
080    
081        /**
082         * Equals.
083         * @param ob an Object.
084         * @return true if this is equal to o, else false.
085         */
086        @Override
087        @SuppressWarnings("unchecked")
088        public boolean equals(Object ob) {
089            MultiplicativeSet<C> c = null;
090            try {
091                c = (MultiplicativeSet<C>) ob;
092            } catch (ClassCastException e) {
093                return false;
094            }
095            if (c == null) {
096                return false;
097            }
098            if (!ring.equals(c.ring)) {
099                return false;
100            }
101            return mset.equals(c.mset);
102        }
103    
104    
105        /**
106         * Hash code for this condition.
107         * @see java.lang.Object#hashCode()
108         */
109        @Override
110        public int hashCode() {
111            int h;
112            h = ring.hashCode();
113            h = h << 17;
114            h += mset.hashCode();
115            return h;
116        }
117    
118    
119        /**
120         * Is set.
121         * @return true if this is the empty set, else false.
122         */
123        public boolean isEmpty() {
124            return mset.size() == 0;
125        }
126    
127    
128        /**
129         * Test if a polynomial is contained in this multiplicative set.
130         * @param c polynomial searched in mset.
131         * @return true, if c = prod_{m in mset} m, else false
132         */
133        public boolean contains(GenPolynomial<C> c) {
134            if (c == null || c.isZERO()) {
135                return false;
136            }
137            if (c.isConstant()) {
138                return true;
139            }
140            if (mset.size() == 0) {
141                return false;
142            }
143            GenPolynomial<C> d = c;
144            for (GenPolynomial<C> n : mset) {
145                // System.out.println("mset n = " + n);
146                if (n.isONE()) { // do not use 1
147                    continue;
148                }
149                GenPolynomial<C> q, r;
150                do {
151                    GenPolynomial<C>[] qr = d.quotientRemainder(n);
152                    q = qr[0];
153                    r = qr[1];
154                    // System.out.println("q = " + q + ", r = " + r + ", d = " + d +
155                    // ", n = " + n);
156                    if (r != null && !r.isZERO()) {
157                        continue;
158                    }
159                    if (q != null && q.isConstant()) {
160                        return true;
161                    }
162                    d = q;
163                } while (r.isZERO() && !d.isConstant());
164            }
165            return d.isConstant(); // false
166        }
167    
168    
169        /**
170         * Test if a list of polynomials is contained in multiplicative set.
171         * @param L list of polynomials to be searched in mset.
172         * @return true, if all c in L are in mset, else false
173         */
174        public boolean contains(List<GenPolynomial<C>> L) {
175            if (L == null || L.size() == 0) {
176                return true;
177            }
178            for (GenPolynomial<C> c : L) {
179                if (!contains(c)) {
180                    return false;
181                }
182            }
183            return true;
184        }
185    
186    
187        /**
188         * Add polynomial to mset.
189         * @param cc polynomial to be added to mset.
190         * @return new multiplicative set. <b>Note:</b> must be overridden in
191         *         sub-classes.
192         */
193        public MultiplicativeSet<C> add(GenPolynomial<C> cc) {
194            if (cc == null || cc.isZERO() || cc.isConstant()) {
195                return this;
196            }
197            if (ring.coFac.isField()) {
198                cc = cc.monic();
199            }
200            List<GenPolynomial<C>> list;
201            if (mset.size() == 0) {
202                list = new ArrayList<GenPolynomial<C>>(1);
203                list.add(cc);
204                return new MultiplicativeSet<C>(ring, list);
205            }
206            GenPolynomial<C> c = removeFactors(cc);
207            if (c.isConstant()) {
208                logger.info("skipped unit or constant = " + c);
209                return this;
210            }
211            if (ring.coFac.isField()) {
212                c = c.monic();
213            }
214            if (mset.size() == 0) {
215                logger.info("added to empty mset = " + c);
216            } else {
217                logger.info("added to mset = " + c);
218            }
219            list = new ArrayList<GenPolynomial<C>>(mset);
220            list.add(c);
221            return new MultiplicativeSet<C>(ring, list);
222        }
223    
224    
225        /**
226         * Replace polynomial list of mset.
227         * @param L polynomial list to replace mset.
228         * @return new multiplicative set. <b>Note:</b> must be overridden in
229         *         sub-classes.
230         */
231        public MultiplicativeSet<C> replace(List<GenPolynomial<C>> L) {
232            MultiplicativeSet<C> ms = new MultiplicativeSet<C>(ring);
233            if (L == null || L.size() == 0) {
234                return ms;
235            }
236            for (GenPolynomial<C> p : L) {
237                ms = ms.add(p);
238            }
239            return ms;
240        }
241    
242    
243        /**
244         * Remove factors by mset factors division.
245         * @param cc polynomial to be removed factors from mset.
246         * @return quotient polynomial.
247         */
248        public GenPolynomial<C> removeFactors(GenPolynomial<C> cc) {
249            if (cc == null || cc.isZERO() || cc.isConstant()) {
250                return cc;
251            }
252            if (mset.size() == 0) {
253                return cc;
254            }
255            GenPolynomial<C> c = cc;
256            for (GenPolynomial<C> n : mset) {
257                if (n.isConstant()) { // do not use 1, should not be in mset
258                    continue;
259                }
260                GenPolynomial<C> q, r;
261                do {
262                    GenPolynomial<C>[] qr = c.quotientRemainder(n);
263                    q = qr[0];
264                    r = qr[1];
265                    if (r != null && !r.isZERO()) {
266                        continue;
267                    }
268                    if (q != null && q.isConstant()) {
269                        return q;
270                    }
271                    c = q;
272                } while (r.isZERO() && !c.isConstant());
273            }
274            return c;
275        }
276    
277    
278        /**
279         * Remove factors by mset factors division.
280         * @param L list of polynomial to be removed factors from mset.
281         * @return quotient polynomial list.
282         */
283        public List<GenPolynomial<C>> removeFactors(List<GenPolynomial<C>> L) {
284            if (L == null || L.size() == 0) {
285                return L;
286            }
287            if (mset.size() == 0) {
288                return L;
289            }
290            List<GenPolynomial<C>> M = new ArrayList<GenPolynomial<C>>(L.size());
291            for (GenPolynomial<C> p : L) {
292                p = removeFactors(p);
293                // nono, really: if ( !p.isConstant() ) {
294                M.add(p);
295            }
296            return M;
297        }
298    
299    }