001    /*
002     * $Id: ExpVectorIterable.java 3444 2010-12-25 17:13:53Z kredel $
003     */
004    
005    package edu.jas.ps;
006    
007    
008    import java.util.Iterator;
009    import java.util.NoSuchElementException;
010    import java.util.List;
011    import java.util.ArrayList;
012    
013    
014    import edu.jas.poly.ExpVector;
015    import edu.jas.util.CartesianProductLong;
016    import edu.jas.util.LongIterable;
017    
018    
019    /**
020     * Iterable for ExpVector, using total degree enumeration.
021     * @author Heinz Kredel
022     */
023    public class ExpVectorIterable implements Iterable<ExpVector> {
024    
025    
026        protected long upperBound;
027    
028    
029        final boolean infinite;
030    
031    
032        final int nvar;
033    
034    
035        /**
036         * Constructor.
037         * @param nv number of variables.
038         */
039        public ExpVectorIterable(int nv) {
040            this(nv,true,Long.MAX_VALUE);
041        }
042    
043    
044        /**
045         * Constructor.
046         * @param nv number of variables.
047         * @param ub upper bound for the components.
048         */
049        public ExpVectorIterable(int nv, long ub) {
050            this(nv,false,ub);
051        }
052    
053    
054        /**
055         * Constructor.
056         * @param nv number of variables.
057         * @param all true, if all elements between 0 and upper bound are enumerated, 
058                      false, if only elements of exact upper bund are to be processed.
059         * @param ub upper bound for the components.
060         */
061        public ExpVectorIterable(int nv, boolean all, long ub) {
062            upperBound = ub;
063            infinite = all;
064            nvar = nv;
065        }
066    
067    
068        /** Set the upper bound for the iterator.
069         * @param ub an upper bound for the iterator elements. 
070         */
071        public void setUpperBound(long ub) {
072            upperBound = ub;
073        }
074    
075    
076        /** Get the upper bound for the iterator.
077         * @return the upper bound for the iterator elements. 
078         */
079        public long getUpperBound() {
080            return upperBound;
081        }
082    
083    
084        /**
085         * Get an iterator over ExpVector.
086         * @return an iterator.
087         */
088        public Iterator<ExpVector> iterator() {
089            return new ExpVectorIterator(nvar,infinite,upperBound);
090        }
091    
092    }
093    
094    
095    /**
096     * ExpVector iterator using CartesianProductLongIterator.
097     * @author Heinz Kredel
098     */
099    class ExpVectorIterator implements Iterator<ExpVector> {
100    
101    
102        /**
103         * data structure.
104         */
105        ExpVector current;
106    
107    
108        Iterator<List<Long>> liter;
109    
110    
111        protected int totalDegree;
112    
113    
114        protected boolean empty;
115    
116    
117        final long upperBound;
118    
119    
120        final boolean infinite;
121    
122    
123        final int nvar;
124    
125    
126        /**
127         * ExpVector iterator constructor.
128         * @param nv number of variables.
129         */
130        public ExpVectorIterator(int nv) {
131            this(nv,true,Long.MAX_VALUE);
132        }
133    
134    
135        /**
136         * ExpVector iterator constructor.
137         * @param nv number of variables.
138         * @param ub upper bound for the components.
139         */
140        public ExpVectorIterator(int nv,long ub) {
141            this(nv,false,ub);
142        }
143    
144    
145        /**
146         * ExpVector iterator constructor.
147         * @param nv number of variables.
148         * @param inf true, if all elements between 0 and upper bound are enumerated, 
149                      false, if only elements of exact upper bund are to be processed.
150         * @param ub an upper bound for the entrys.
151         */
152        protected ExpVectorIterator(int nv, boolean inf, long ub) {
153            infinite = inf; 
154            upperBound = ub;
155            if (upperBound < 0L) {
156                throw new IllegalArgumentException("negative upper bound not allowed");
157            }
158            totalDegree = 0;
159            if ( !infinite ) {
160                totalDegree = (int)upperBound;
161            }
162            //System.out.println("totalDegree = " + totalDegree + ", upperBound = " + upperBound);
163            LongIterable li = new LongIterable();
164            li.setNonNegativeIterator();
165            li.setUpperBound(totalDegree);
166            List<LongIterable> tlist = new ArrayList<LongIterable>(nv);
167            for (int i = 0; i < nv; i++) {
168                tlist.add(li); // can reuse li
169            }
170            Iterable<List<Long>> ib = new CartesianProductLong(tlist,totalDegree);
171            liter = ib.iterator();
172            empty = (totalDegree > upperBound) || !liter.hasNext();
173            current = ExpVector.create(nv);
174            if ( !empty ) {
175                List<Long> el = liter.next();
176                current = ExpVector.create(el);
177                //System.out.println("current = " + current);
178            }
179            nvar = nv;
180        }
181    
182    
183        /**
184         * Test for availability of a next long.
185         * @return true if the iteration has more ExpVectors, else false.
186         */
187        public synchronized boolean hasNext() {
188            return !empty;
189        }
190    
191    
192        /**
193         * Get next ExpVector.
194         * @return next ExpVector.
195         */
196        public synchronized ExpVector next() {
197            ExpVector res = current;
198            if ( liter.hasNext() ) {
199                List<Long> el = liter.next();
200                current = ExpVector.create(el);
201                //System.out.println("current, liter = " + current);
202                return res;
203            } 
204            if ( totalDegree >= upperBound ) {
205                empty = true;
206                return res;
207            }
208            totalDegree++;
209            //System.out.println("totalDegree,b = " + totalDegree);
210            if ( totalDegree >= upperBound && !infinite ) {
211                throw new NoSuchElementException("invalid call of next()");
212            }
213            LongIterable li = new LongIterable();
214            li.setNonNegativeIterator();
215            li.setUpperBound(totalDegree);
216            List<LongIterable> tlist = new ArrayList<LongIterable>(nvar);
217            for (int i = 0; i < nvar; i++) {
218                tlist.add(li); // can reuse li
219            }
220            Iterable<List<Long>> ib = new CartesianProductLong(tlist,totalDegree);
221            liter = ib.iterator();
222            List<Long> el = liter.next();
223            current = ExpVector.create(el);
224            return res;
225        }
226    
227    
228        /**
229         * Remove a tuple if allowed.
230         */
231        public void remove() {
232            throw new UnsupportedOperationException("cannnot remove elements");
233        }
234    
235    }