1 package Analysis.Scheduling;
3 import java.util.Vector;
5 public class CombinationUtil {
6 static CombinationUtil cu;
8 public CombinationUtil() {
11 public static CombinationUtil allocateCombinationUtil() {
13 cu = new CombinationUtil();
18 public static RootsGenerator allocateRootsGenerator(Vector<Vector<ScheduleNode>> snodevecs,
20 return CombinationUtil.allocateCombinationUtil().new RootsGenerator(snodevecs, rootNum);
23 public static CombineGenerator allocateCombineGenerator(Vector<Vector<ScheduleNode>> rootnodes,
24 Vector<Vector<ScheduleNode>> node2combine) {
25 return CombinationUtil.allocateCombinationUtil().new CombineGenerator(rootnodes, node2combine);
28 public class RootsGenerator {
29 Vector<Vector<ScheduleNode>> sNodeVecs;
30 Vector<Vector<ScheduleNode>> node2Combine;
31 Vector<Vector<ScheduleNode>> rootNodes;
34 public RootsGenerator(Vector<Vector<ScheduleNode>> snodevecs,
36 this.sNodeVecs = snodevecs;
37 this.rootNum = rootNum;
38 this.node2Combine = null;
39 this.rootNodes = null;
42 public boolean nextGen() {
43 boolean trial = false;
44 if(this.rootNodes == null) {
45 int num2choose = this.rootNum;
46 this.rootNodes = new Vector<Vector<ScheduleNode>>();
47 this.rootNodes.add(new Vector<ScheduleNode>());
48 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(0);
49 for(int i = 0; i < toadd.size(); i++) {
50 // should be only one element: startup object
51 this.rootNodes.elementAt(0).add(toadd.elementAt(i));
55 trial = trial(num2choose, next);
58 if(this.rootNodes.size() == 1) {
61 int next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
63 while(next == this.sNodeVecs.size()) {
65 num2choose = this.rootNodes.lastElement().size();
66 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
67 if(this.rootNodes.size() == 1) {
68 // only startup object left, no more choices
71 next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
74 // reduce one from the last one
75 this.rootNodes.lastElement().removeElementAt(this.rootNodes.lastElement().size() - 1);
76 if(this.rootNodes.lastElement().size() == 0) {
77 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
80 trial = trial(num2choose, next);
83 // remaining nodes are all to be combined
84 this.node2Combine = new Vector<Vector<ScheduleNode>>();
87 for(int i = 1; i < this.rootNodes.size(); i++) {
88 int tmp = this.rootNodes.elementAt(i).elementAt(0).getCid();
90 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
92 this.node2Combine.add(new Vector<ScheduleNode>());
93 for(index = 0; index < toadd.size(); index++) {
94 this.node2Combine.lastElement().add(toadd.elementAt(index));
98 this.node2Combine.add(null);
102 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(tmp);
103 if(toadd.size() > this.rootNodes.elementAt(i).size()) {
104 this.node2Combine.add(new Vector<ScheduleNode>());
105 for(index = this.rootNodes.elementAt(i).size(); index < toadd.size(); index++) {
106 this.node2Combine.lastElement().add(toadd.elementAt(index));
112 while(next < this.sNodeVecs.size()) {
113 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
115 this.node2Combine.add(new Vector<ScheduleNode>());
116 for(index = 0; index < toadd.size(); index++) {
117 this.node2Combine.lastElement().add(toadd.elementAt(index));
121 this.node2Combine.add(null);
129 private boolean trial(int num2choose,
132 boolean first = true;
133 while(num2choose > 0) {
135 if(next == this.sNodeVecs.size()) {
136 // no more nodes available to add
140 if(this.sNodeVecs.elementAt(next) != null) {
142 this.rootNodes.add(new Vector<ScheduleNode>());
145 this.rootNodes.lastElement().add(this.sNodeVecs.elementAt(next).elementAt(index));
148 if(index == this.sNodeVecs.elementAt(next).size()) {
161 public Vector<Vector<ScheduleNode>> getNode2Combine() {
165 public Vector<Vector<ScheduleNode>> getRootNodes() {
170 public class Combine {
171 public ScheduleNode node;
175 public Combine(ScheduleNode n) {
182 public class CombineGenerator {
183 Vector<Vector<ScheduleNode>> rootNodes;
184 Vector<Vector<int[]>> rootNStates;
185 Vector<Vector<ScheduleNode>> node2Combine;
186 Vector<Vector<Combine>> combine;
188 boolean first4choice;
190 public CombineGenerator(Vector<Vector<ScheduleNode>> rootnodes,
191 Vector<Vector<ScheduleNode>> node2combine) {
192 this.rootNodes = rootnodes;
193 this.node2Combine = node2combine;
194 this.rootNStates = new Vector<Vector<int[]>>();
195 for(int i = 0; i < this.rootNodes.size(); i++) {
196 this.rootNStates.add(new Vector<int[]>());
197 for(int j = 0; j < this.rootNodes.elementAt(i).size(); j++) {
198 this.rootNStates.elementAt(i).add(new int[this.node2Combine.size()]);
199 for(int k = 0; k < this.node2Combine.size(); k++) {
200 this.rootNStates.elementAt(i).elementAt(j)[k] = 0;
204 this.combine = new Vector<Vector<Combine>>();
205 for(int i = 0; i < this.node2Combine.size(); i++) {
206 if(this.node2Combine.elementAt(i) == null) {
207 this.combine.add(null);
209 this.combine.add(new Vector<Combine>());
210 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
211 this.combine.elementAt(i).add(new Combine(this.node2Combine.elementAt(i).elementAt(j)));
215 this.lastchoices = null;
216 this.first4choice = false;
219 public Vector<Vector<Combine>> getCombine() {
223 public boolean nextGen() {
224 boolean trial = false;
225 if(this.lastchoices == null) {
227 this.lastchoices = new int[this.node2Combine.size()];
228 for(int i = 0; i < this.lastchoices.length; i++) {
229 this.lastchoices[i] = 0;
231 this.first4choice = true;
236 // no more available combination under this choice
237 // choose another choice
238 int next = this.node2Combine.size() - 1;
239 boolean iter = false;
241 if(this.node2Combine.elementAt(next) != null) {
242 this.lastchoices[next]++;
243 if((this.lastchoices[next] == this.rootNodes.size() ||
244 (this.rootNodes.elementAt(this.lastchoices[next]).elementAt(0).getCid() >
245 this.node2Combine.elementAt(next).elementAt(0).getCid()))) {
246 // break the rule that a node can only be combined to nodes with smaller colorid.
247 // or no more buckets
258 } while(iter && !(next < 0));
262 for(next += 1; next < this.node2Combine.size(); next++) {
263 this.lastchoices[next] = 0;
265 this.first4choice = true;
272 private boolean trial() {
274 if(this.first4choice) {
275 // first time for each choice
276 // put all the objects of one color into the first bucket indicated by the choice
278 suc = firstexpand(next, this.first4choice);
279 this.first4choice = false;
281 int next = this.node2Combine.size() - 1;
283 suc = innertrial(next, layer);
288 private boolean firstexpand(int next,
290 for(int i = next; i < this.node2Combine.size(); i++) {
291 if(this.node2Combine.elementAt(i) != null) {
292 int choice = this.lastchoices[i];
293 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
294 Combine tmp = this.combine.elementAt(i).elementAt(j);
296 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
301 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
305 this.rootNStates.elementAt(choice).elementAt(0)[i] = this.node2Combine.elementAt(i).size();
306 for(int j = 1; j < this.rootNodes.elementAt(choice).size(); j++) {
307 this.rootNStates.elementAt(choice).elementAt(j)[i] = 0;
315 private boolean innertrial(int next,
317 if((this.combine.elementAt(next) == null) ||
318 (this.combine.elementAt(next).size() < 2)) {
319 // skip over empty buckets and bucket with only one obj ( make sure
320 // at least one obj is existing in the chosen bucket)
324 return innertrial(next - 1, ++layer);
327 Combine tmp = this.combine.elementAt(next).lastElement();
328 // try to move it backward
330 int index = tmp.index;
332 if(index == this.rootNodes.elementAt(root).size()) {
333 // no more place in this color bucket
336 } else if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
337 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
338 // break the law of non-increase order inside one color bucket
339 // try next bucket of another color
343 if(root == this.rootNodes.size()) {
348 int t = this.combine.elementAt(next).size() - 2;
351 tmp = this.combine.elementAt(next).elementAt(t);
352 if ((tmp.root != root) || (tmp.index != index)) {
358 // try the bucket in node2combine before
362 return innertrial(next - 1, ++layer);
364 } else if(tmp.root != root) {
365 if((tmp.root == this.lastchoices[next]) &&
366 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] == 1)) {
367 // only 1 obj left in the chosen bucket
368 // can not move this one
369 // try the bucket in node2combine before
373 return innertrial(next - 1, ++layer);
376 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
378 int newroot = tmp.root + 1;
381 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
382 // make all left things in this color bucket reset
383 for(t++; t < this.combine.elementAt(next).size(); t++) {
384 tmp = this.combine.elementAt(next).elementAt(t);
385 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
388 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
391 return firstexpand(next+1, this.first4choice);
394 } else if(tmp.index != index) {
395 if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] ==
396 this.rootNStates.elementAt(root).elementAt(index)[next]) {
397 // break the law of non-increase order inside one color bucket
398 // go on search forward
400 } else if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] <
401 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
402 // break the law of non-increase order inside one color bucket
403 // and now they only differ by 1
404 // propagate this difference to see if it can fix
405 boolean suc = propagateOne(next, root, index, t, tmp);
409 // go on search forward
413 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
414 int tmproot = tmp.root;
415 int tmpindex = tmp.index;
418 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
419 int desroot = tmp.root;
420 int desindex = tmp.index;
421 // make all left things in this color bucket reset
423 boolean first = true;
424 while(t < this.combine.elementAt(next).size()) {
430 for(; (k < this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) && (t < this.combine.elementAt(next).size()); t++) {
431 tmp = this.combine.elementAt(next).elementAt(t);
432 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
434 tmp.index = desindex;
435 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
437 if(k == this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) {
442 return firstexpand(next+1, this.first4choice);
449 if((tmp.root != this.lastchoices[next]) ||
450 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] > 1)) {
451 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
454 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
456 return firstexpand(next+1, this.first4choice);
460 // only 1 obj with the color next exist on the chosen bucket this time,
461 // can not move it, try objs in forward color bucket
465 return innertrial(next - 1, ++layer);
471 private boolean propagateOne(int next,
479 int rootbk = tmp.root;
480 int indexbk = tmp.index;
481 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
484 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
487 if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
488 this.rootNStates.elementAt(root).elementAt(index)[next]) {
489 // need to continue propagate
490 while(t < this.combine.elementAt(next).size()) {
491 tmpt = this.combine.elementAt(next).elementAt(t);
492 if ((tmpt.root != root) || (tmpt.index != index)) {
497 if(t == this.combine.elementAt(next).size()) {
498 // last element of this color bucket
499 if(index + 1 < this.rootNodes.elementAt(root).size()) {
500 // there is available place inside the same color bucket
501 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
502 boolean suc = propagateOne(next, root, index + 1, t - 1, tmpbk);
505 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
508 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
511 } else if(root+1 < this.rootNodes.size()) { // check if there are another bucket
513 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
514 tmpt.root = root + 1;
516 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
517 return firstexpand(next+1, this.first4choice);
520 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
523 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
526 } else if(tmpt.root != root) {
527 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
528 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]--;
529 tmpbk.root = tmpt.root;
531 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]++;
534 // make all left things in this color bucket reset
535 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
536 tmpt = this.combine.elementAt(next).elementAt(t);
537 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
540 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
542 return firstexpand(next+1, this.first4choice);
543 } else if(tmpt.index != index) {
544 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
545 boolean suc = propagateOne(next, root, tmpt.index, t - 1, tmpbk);
548 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
551 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
555 // won't reach here, only to avoid compiler's complain