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, int rootNum) {
19 return CombinationUtil.allocateCombinationUtil().new RootsGenerator(snodevecs, rootNum);
22 public static CombineGenerator allocateCombineGenerator(Vector<Vector<ScheduleNode>> rootnodes, Vector<Vector<ScheduleNode>> node2combine) {
23 return CombinationUtil.allocateCombinationUtil().new CombineGenerator(rootnodes, node2combine);
26 public class RootsGenerator {
27 Vector<Vector<ScheduleNode>> sNodeVecs;
28 Vector<Vector<ScheduleNode>> node2Combine;
29 Vector<Vector<ScheduleNode>> rootNodes;
32 public RootsGenerator(Vector<Vector<ScheduleNode>> snodevecs, int rootNum) {
33 this.sNodeVecs = snodevecs;
34 this.rootNum = rootNum;
35 this.node2Combine = null;
36 this.rootNodes = null;
39 public boolean nextGen() {
40 boolean trial = false;
41 if(this.rootNodes == null) {
42 int num2choose = this.rootNum;
43 this.rootNodes = new Vector<Vector<ScheduleNode>>();
44 this.rootNodes.add(new Vector<ScheduleNode>());
45 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(0);
46 for(int i = 0; i < toadd.size(); i++) {
47 // should be only one element: startup object
48 this.rootNodes.elementAt(0).add(toadd.elementAt(i));
52 trial = trial(num2choose, next);
55 if(this.rootNodes.size() == 1) {
58 int next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
60 while(next == this.sNodeVecs.size()) {
62 num2choose = this.rootNodes.lastElement().size();
63 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
64 if(this.rootNodes.size() == 1) {
65 // only startup object left, no more choices
68 next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
71 // reduce one from the last one
72 this.rootNodes.lastElement().removeElementAt(this.rootNodes.lastElement().size() - 1);
73 if(this.rootNodes.lastElement().size() == 0) {
74 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
77 trial = trial(num2choose, next);
80 // left nodes are all to be combined
81 this.node2Combine = new Vector<Vector<ScheduleNode>>();
84 for(int i = 1; i < this.rootNodes.size(); i++) {
85 int tmp = this.rootNodes.elementAt(i).elementAt(0).getCid();
87 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
89 this.node2Combine.add(new Vector<ScheduleNode>());
90 for(index = 0; index < toadd.size(); index++) {
91 this.node2Combine.lastElement().add(toadd.elementAt(index));
95 this.node2Combine.add(null);
99 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(tmp);
100 if(toadd.size() > this.rootNodes.elementAt(i).size()) {
101 this.node2Combine.add(new Vector<ScheduleNode>());
102 for(index = this.rootNodes.elementAt(i).size(); index < toadd.size(); index++) {
103 this.node2Combine.lastElement().add(toadd.elementAt(index));
109 while(next < this.sNodeVecs.size()) {
110 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
112 this.node2Combine.add(new Vector<ScheduleNode>());
113 for(index = 0; index < toadd.size(); index++) {
114 this.node2Combine.lastElement().add(toadd.elementAt(index));
118 this.node2Combine.add(null);
126 private boolean trial(int num2choose, int next) {
128 boolean first = true;
129 while(num2choose > 0) {
131 if(next == this.sNodeVecs.size()) {
132 // no more nodes available to add
136 if(this.sNodeVecs.elementAt(next) != null) {
138 this.rootNodes.add(new Vector<ScheduleNode>());
141 this.rootNodes.lastElement().add(this.sNodeVecs.elementAt(next).elementAt(index));
144 if(index == this.sNodeVecs.elementAt(next).size()) {
157 public Vector<Vector<ScheduleNode>> getNode2Combine() {
161 public Vector<Vector<ScheduleNode>> getRootNodes() {
166 public class Combine {
167 public ScheduleNode node;
171 public Combine(ScheduleNode n) {
178 public class CombineGenerator {
179 Vector<Vector<ScheduleNode>> rootNodes;
180 Vector<Vector<int[]>> rootNStates;
181 Vector<Vector<ScheduleNode>> node2Combine;
182 Vector<Vector<Combine>> combine;
184 boolean first4choice;
186 public CombineGenerator(Vector<Vector<ScheduleNode>> rootnodes, Vector<Vector<ScheduleNode>> node2combine) {
187 this.rootNodes = rootnodes;
188 this.node2Combine = node2combine;
189 this.rootNStates = new Vector<Vector<int[]>>();
190 for(int i = 0; i < this.rootNodes.size(); i++) {
191 this.rootNStates.add(new Vector<int[]>());
192 for(int j = 0; j < this.rootNodes.elementAt(i).size(); j++) {
193 this.rootNStates.elementAt(i).add(new int[this.node2Combine.size()]);
194 for(int k = 0; k < this.node2Combine.size(); k++) {
195 this.rootNStates.elementAt(i).elementAt(j)[k] = 0;
199 this.combine = new Vector<Vector<Combine>>();
200 for(int i = 0; i < this.node2Combine.size(); i++) {
201 if(this.node2Combine.elementAt(i) == null) {
202 this.combine.add(null);
204 this.combine.add(new Vector<Combine>());
205 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
206 this.combine.elementAt(i).add(new Combine(this.node2Combine.elementAt(i).elementAt(j)));
210 this.lastchoices = null;
211 this.first4choice = false;
214 public Vector<Vector<Combine>> getCombine() {
218 public boolean nextGen() {
219 boolean trial = false;
220 if(this.lastchoices == null) {
222 this.lastchoices = new int[this.node2Combine.size()];
223 for(int i = 0; i < this.lastchoices.length; i++) {
224 this.lastchoices[i] = 0;
226 this.first4choice = true;
231 // no more available combination under this choice
232 // choose another choice
233 int next = this.node2Combine.size() - 1;
234 boolean iter = false;
236 if(this.node2Combine.elementAt(next) != null) {
237 this.lastchoices[next]++;
238 if((this.lastchoices[next] == this.rootNodes.size() ||
239 (this.rootNodes.elementAt(this.lastchoices[next]).elementAt(0).getCid() >
240 this.node2Combine.elementAt(next).elementAt(0).getCid()))) {
241 // break the rule that a node can only be combined to nodes with smaller colorid.
242 // or no more buckets
253 } while(iter && !(next < 0));
257 for(next += 1; next < this.node2Combine.size(); next++) {
258 this.lastchoices[next] = 0;
260 this.first4choice = true;
267 private boolean trial() {
269 if(this.first4choice) {
270 // first time for each choice
271 // put all the objects of one color into the first bucket indicated by the choice
273 suc = firstexpand(next, this.first4choice);
274 this.first4choice = false;
276 int next = this.node2Combine.size() - 1;
278 suc = innertrial(next, layer);
283 private boolean firstexpand(int next, boolean first) {
284 for(int i = next; i < this.node2Combine.size(); i++) {
285 if(this.node2Combine.elementAt(i) != null) {
286 int choice = this.lastchoices[i];
287 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
288 Combine tmp = this.combine.elementAt(i).elementAt(j);
290 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
295 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
299 this.rootNStates.elementAt(choice).elementAt(0)[i] = this.node2Combine.elementAt(i).size();
300 for(int j = 1; j < this.rootNodes.elementAt(choice).size(); j++) {
301 this.rootNStates.elementAt(choice).elementAt(j)[i] = 0;
309 private boolean innertrial(int next, int layer) {
310 if((this.combine.elementAt(next) == null) ||
311 (this.combine.elementAt(next).size() < 2)) {
312 // skip over empty buckets and bucket with only one obj ( make sure
313 // at least one obj is existing in the chosen bucket)
317 return innertrial(next - 1, ++layer);
320 Combine tmp = this.combine.elementAt(next).lastElement();
321 // try to move it backward
323 int index = tmp.index;
325 if(index == this.rootNodes.elementAt(root).size()) {
326 // no more place in this color bucket
329 } else if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
330 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
331 // break the law of non-increase order inside one color bucket
332 // try next bucket of another color
336 if(root == this.rootNodes.size()) {
341 int t = this.combine.elementAt(next).size() - 2;
344 tmp = this.combine.elementAt(next).elementAt(t);
345 if ((tmp.root != root) || (tmp.index != index)) {
351 // try the bucket in node2combine before
355 return innertrial(next - 1, ++layer);
357 } else if(tmp.root != root) {
358 if((tmp.root == this.lastchoices[next]) &&
359 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] == 1)) {
360 // only 1 obj left in the chosen bucket
361 // can not move this one
362 // try the bucket in node2combine before
366 return innertrial(next - 1, ++layer);
369 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
371 int newroot = tmp.root + 1;
374 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
375 // make all left things in this color bucket reset
376 for(t++; t < this.combine.elementAt(next).size(); t++) {
377 tmp = this.combine.elementAt(next).elementAt(t);
378 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
381 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
384 return firstexpand(next+1, this.first4choice);
387 } else if(tmp.index != index) {
388 if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] ==
389 this.rootNStates.elementAt(root).elementAt(index)[next]) {
390 // break the law of non-increase order inside one color bucket
391 // go on search forward
393 } else if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] <
394 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
395 // break the law of non-increase order inside one color bucket
396 // and now they only differ by 1
397 // propagate this difference to see if it can fix
398 boolean suc = propagateOne(next, root, index, t, tmp);
402 // go on search forward
406 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
407 int tmproot = tmp.root;
408 int tmpindex = tmp.index;
411 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
412 int desroot = tmp.root;
413 int desindex = tmp.index;
414 // make all left things in this color bucket reset
416 boolean first = true;
417 while(t < this.combine.elementAt(next).size()) {
423 for(; (k < this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) && (t < this.combine.elementAt(next).size()); t++) {
424 tmp = this.combine.elementAt(next).elementAt(t);
425 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
427 tmp.index = desindex;
428 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
430 if(k == this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) {
435 return firstexpand(next+1, this.first4choice);
442 if((tmp.root != this.lastchoices[next]) ||
443 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] > 1)) {
444 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
447 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
449 return firstexpand(next+1, this.first4choice);
453 // only 1 obj with the color next exist on the chosen bucket this time,
454 // can not move it, try objs in forward color bucket
458 return innertrial(next - 1, ++layer);
464 private boolean propagateOne(int next, int rooti, int indexi, int ti, Combine tmp) {
468 int rootbk = tmp.root;
469 int indexbk = tmp.index;
470 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
473 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
476 if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
477 this.rootNStates.elementAt(root).elementAt(index)[next]) {
478 // need to continue propagate
479 while(t < this.combine.elementAt(next).size()) {
480 tmpt = this.combine.elementAt(next).elementAt(t);
481 if ((tmpt.root != root) || (tmpt.index != index)) {
486 if(t == this.combine.elementAt(next).size()) {
487 // last element of this color bucket
488 if(index + 1 < this.rootNodes.elementAt(root).size()) {
489 // there is available place inside the same color bucket
490 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
491 boolean suc = propagateOne(next, root, index + 1, t - 1, tmpbk);
494 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
497 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
500 } else if(root+1 < this.rootNodes.size()) { // check if there are another bucket
502 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
503 tmpt.root = root + 1;
505 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
506 return firstexpand(next+1, this.first4choice);
509 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
512 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
515 } else if(tmpt.root != root) {
516 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
517 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]--;
518 tmpbk.root = tmpt.root;
520 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]++;
523 // make all left things in this color bucket reset
524 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
525 tmpt = this.combine.elementAt(next).elementAt(t);
526 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
529 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
531 return firstexpand(next+1, this.first4choice);
532 } else if(tmpt.index != index) {
533 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
534 boolean suc = propagateOne(next, root, tmpt.index, t - 1, tmpbk);
537 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
540 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
544 // won't reach here, only to avoid compiler's complain