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 }