Method: ReducedTestSequence.RandomReductionIterator(TestSequence, int, long, Random)
1: package org.overture.interpreter.traces;
2:
3: import java.util.Collections;
4: import java.util.HashMap;
5: import java.util.Iterator;
6: import java.util.List;
7: import java.util.Map;
8: import java.util.Map.Entry;
9: import java.util.Random;
10: import java.util.Vector;
11:
12: import org.overture.interpreter.traces.util.RandomList;
13:
14: public class ReducedTestSequence extends TestSequence
15: {
16:
17:         public interface ShapeIterator extends Iterator<CallSequence>
18:         {
19:                 int iterationCount();
20:         }
21:         
22:         /**
23:          * A random reduction iterator that only returns the elements within the random restrictions
24:          *
25:          * @author kel
26:          */
27:         private static class RandomReductionIterator implements ShapeIterator
28:         {
29:                 private TestSequence data;
30:                 private int size;
31:
32:                 private int nextIndex;
33:                 private RandomList randomList;
34:                 private int numberOfTests;
35:
36:                 public RandomReductionIterator(TestSequence data, int size,
37:                                 long numberOfTests, Random prng)
38:                 {
39:                         this.data = data;
40:                         this.size = size;
41:                         this.numberOfTests = (int) numberOfTests;
42:
43:                         final int N = size;
44:                         final int R = this.numberOfTests;
45:
46:                         this.randomList = new RandomList(N, R, prng);
47:
48:                         computeNextIndex();
49:                 }
50:
51:                 private void computeNextIndex()
52:                 {
53:                         this.nextIndex = randomList.next() - 1;
54:                 }
55:
56:                 @Override
57:                 public boolean hasNext()
58:                 {
59:                         return this.nextIndex >= 0 && this.nextIndex < size;
60:                 }
61:
62:                 @Override
63:                 public CallSequence next()
64:                 {
65:                         CallSequence next = data.get(nextIndex);
66:
67:                         computeNextIndex();
68:
69:                         return next;
70:                 }
71:
72:                 @Override
73:                 public void remove()
74:                 {
75:                         throw new UnsupportedOperationException();
76:                 }
77:
78:                 @Override
79:                 public int iterationCount()
80:                 {
81:                         return this.numberOfTests;
82:                 }
83:         }
84:
85:         /**
86:          * A shape reduction iterator that only returns the elements within the shape restrictions
87:          *
88:          * @author kel
89:          */
90:         private static class ShapeReductionIterator implements ShapeIterator
91:         {
92:
93:                 private TestSequence data;
94:                 private long delta;
95:                 private Random prng;
96:                 private int size;
97:                 private TraceReductionType type;
98:
99:                 private List<Integer> chosenTestIndices = new Vector<Integer>();
100:                 private int choosenIndexPtr = 0;
101:                 private Iterator<CallSequence> choosenTestItr;
102:                 private int choosenTestIndexPtr = 0;
103:
104:                 public ShapeReductionIterator(TestSequence data, int size, long delta,
105:                                 Random prng, TraceReductionType type)
106:                 {
107:                         this.data = data;
108:                         this.delta = delta;
109:                         this.prng = prng;
110:                         this.size = size;
111:                         this.type = type;
112:
113:                         initialize();
114:                 }
115:
116:                 private void initialize()
117:                 {
118:                         Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
119:
120:                         int index = 0;
121:                         for (Iterator<CallSequence> itr = data.iterator(); itr.hasNext();)
122:                         {
123:                                 String shape = itr.next().toShape(type);
124:                                 List<Integer> subset = map.get(shape);
125:
126:                                 if (subset == null)
127:                                 {
128:                                         subset = new Vector<Integer>();
129:                                         map.put(shape, subset);
130:                                 }
131:
132:                                 subset.add(index);
133:
134:                                 index++;
135:                         }
136:
137:                         String[] shapes = map.keySet().toArray(new String[0]);
138:
139:                         if (size - delta < shapes.length)
140:                         {
141:                                 // We must keep one test for each shape
142:                                 delta = size - shapes.length;
143:                         }
144:
145:                         for (long i = 0; i < delta; i++)
146:                         {
147:                                 int x = prng.nextInt(shapes.length);
148:                                 List<Integer> tests = map.get(shapes[x]);
149:                                 int s = tests.size();
150:
151:                                 if (s < 2)
152:                                 {
153:                                         i--; // Find another group
154:                                 } else
155:                                 {
156:                                         tests.remove(prng.nextInt(s));
157:                                 }
158:                         }
159:
160:                         for (Entry<String, List<Integer>> entry : map.entrySet())
161:                         {
162:                                 chosenTestIndices.addAll(map.get(entry.getKey()));
163:                         }
164:
165:                         Collections.sort(chosenTestIndices);
166:                 }
167:
168:                 @Override
169:                 public boolean hasNext()
170:                 {
171:                         return !chosenTestIndices.isEmpty()
172:                                         && choosenIndexPtr < chosenTestIndices.size();
173:                 }
174:
175:                 @Override
176:                 public CallSequence next()
177:                 {
178:                         if (choosenTestItr == null)
179:                         {
180:                                 choosenTestItr = data.iterator();
181:                                 choosenTestIndexPtr = -1;
182:                         }
183:
184:                         int index = chosenTestIndices.get(choosenIndexPtr++);
185:
186:                         CallSequence test = null;
187:                         do
188:                         {
189:                                 test = choosenTestItr.next();
190:                                 choosenTestIndexPtr++;
191:                         } while (choosenTestIndexPtr < index);
192:                         
193:                         return test;
194:
195:                 }
196:
197:                 @Override
198:                 public void remove()
199:                 {
200:                         throw new UnsupportedOperationException();
201:                 }
202:
203:                 @Override
204:                 public int iterationCount()
205:                 {
206:                         return chosenTestIndices.size();
207:                 }
208:
209:         }
210:
211:         /**
212:          * serial
213:          */
214:         private static final long serialVersionUID = 1L;
215:
216:         private final TestSequence data;
217:
218:         private final boolean enabled;
219:
220:         private final Random prng;
221:
222:         private int size;
223:
224:         private final float subset;
225:
226:         private final TraceReductionType type;
227:         
228:         private Iterator<CallSequence> iterator;
229:
230:         public ReducedTestSequence(TestSequence data, float subset,
231:                         TraceReductionType type, long seed)
232:         {
233:                 this.data = data;
234:                 this.subset = subset;
235:                 this.type = type;
236:                 this.prng = new Random(seed);
237:                 
238:                 this.size = this.data.size();
239:                 long n = Math.round(Math.ceil(size * subset));
240:                 this.enabled = n < size;
241:         }
242:
243:         @Override
244:         public synchronized Iterator<CallSequence> iterator()
245:         {
246:                 if(iterator != null)
247:                 {
248:                         return iterator;
249:                 }
250:                 
251:                 if (!enabled || type == TraceReductionType.NONE)
252:                 {
253:                         iterator = this.data.iterator();
254:                         return iterator;
255:                 }
256:
257:                 long n = Math.round(Math.ceil(size * subset));
258:                 long delta = size - n;
259:                 switch (type)
260:                 {
261:                         case RANDOM:
262:                                 iterator = new RandomReductionIterator(this.data, size, n, prng);
263:                                 return iterator;
264:                         case SHAPES_NOVARS:
265:                         case SHAPES_VARNAMES:
266:                         case SHAPES_VARVALUES:
267:                                 iterator = new ShapeReductionIterator(this.data, size, delta, prng, type);
268:                                 return iterator;
269:                         case NONE:
270:                         default:
271:                                 iterator = this.data.iterator();
272:                                 return iterator;
273:                 }
274:         }
275:         
276:         @Override
277:         public synchronized int size()
278:         {
279:                 if(iterator == null)
280:                 {
281:                         iterator();
282:                 }
283:                 
284:                 if(iterator instanceof ShapeIterator)
285:                 {
286:                         return ((ShapeIterator) iterator).iterationCount();
287:                 }
288:                 
289:                 return this.data.size();
290:         }
291:
292:         // private void randomReduction(long delta, Random prng)
293:         // {
294:         // int s = size();
295:         //
296:         // for (long i = 0; i < delta; i++)
297:         // {
298:         // int x = prng.nextInt(s);
299:         // this.remove(x);
300:         // s--;
301:         // }
302:         // }
303:
304:         //
305:         // private void reduce(float subset, TraceReductionType type, long seed)
306:         // {
307:         // Random prng = new Random(seed);
308:         // int s = size();
309:         // long n = Math.round(Math.ceil(s * subset));
310:         //
311:         // if (n < s)
312:         // {
313:         // long delta = s - n;
314:         //
315:         // switch (type)
316:         // {
317:         // case NONE:
318:         // break;
319:         //
320:         // case RANDOM:
321:         // randomReduction(delta, prng);
322:         // break;
323:         //
324:         // case SHAPES_NOVARS:
325:         // case SHAPES_VARNAMES:
326:         // case SHAPES_VARVALUES:
327:         // shapesReduction(delta, type, prng);
328:         // break;
329:         //
330:         // default:
331:         // throw new InternalException(53, "Unknown trace reduction");
332:         // }
333:         // }
334:         // }
335:
336: //        private void shapesReduction(long delta, TraceReductionType type,
337: //                        Random prng)
338: //        {
339: //                Map<String, TestSequence> map = new HashMap<String, TestSequence>();
340: //
341: //                for (CallSequence cs : this)
342: //                {
343: //                        String shape = cs.toShape(type);
344: //                        TestSequence subset = map.get(shape);
345: //
346: //                        if (subset == null)
347: //                        {
348: //                                subset = new TestSequence();
349: //                                map.put(shape, subset);
350: //                        }
351: //
352: //                        subset.add(cs);
353: //                }
354: //
355: //                String[] shapes = map.keySet().toArray(new String[0]);
356: //
357: //                if (size() - delta < shapes.length)
358: //                {
359: //                        // We must keep one test for each shape
360: //                        delta = size() - shapes.length;
361: //                }
362: //
363: //                for (long i = 0; i < delta; i++)
364: //                {
365: //                        int x = prng.nextInt(shapes.length);
366: //                        TestSequence tests = map.get(shapes[x]);
367: //                        int s = tests.size();
368: //
369: //                        if (s < 2)
370: //                        {
371: //                                i--; // Find another group
372: //                        } else
373: //                        {
374: //                                tests.remove(prng.nextInt(s));
375: //                        }
376: //                }
377: //
378: //                clear();
379: //
380: //                for (Entry<String, TestSequence> entry : map.entrySet())
381: //                {
382: //                        addAll(map.get(entry.getKey()));
383: //                }
384: //        }
385: }